X-Git-Url: http://git.csclub.uwaterloo.ca/?p=kopensolaris-gnu%2Fglibc.git;a=blobdiff_plain;f=time%2Fzic.c;h=ce384f9cd3048686227c98f61893bfc1a192056d;hp=c6db9599c48d6c996edce58b18bbc4eb706ea67f;hb=57ae11b32c7d2848f67898d10ae409038ae04afe;hpb=92b7bddf5bf94b0515f7aa49d7b10571ab1a08a4 diff --git a/time/zic.c b/time/zic.c index c6db9599c4..ce384f9cd3 100644 --- a/time/zic.c +++ b/time/zic.c @@ -1,6 +1,6 @@ #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)zic.c 7.7"; +static char elsieid[] = "@(#)zic.c 7.21"; #endif /* !defined NOID */ #endif /* !defined lint */ @@ -72,7 +72,7 @@ extern char * scheck P((const char * string, const char * format)); static void addtt P((time_t starttime, int type)); static int addtype P((long gmtoff, const char * abbr, int isdst, - int ttisstd)); + int ttisstd)); static void leapadd P((time_t t, int positive, int rolling, int count)); static void adjleap P((void)); static void associate P((void)); @@ -120,8 +120,10 @@ static int errors; static const char * filename; static int leapcnt; static int linenum; +static int max_int; static time_t max_time; static int max_year; +static int min_int; static time_t min_time; static int min_year; static int noise; @@ -502,7 +504,7 @@ char * argv[]; ** Find the next non-continuation zone entry. */ for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j) - ; + continue; outzone(&zones[i], j - i); } /* @@ -525,12 +527,20 @@ const char * const tofile; register char * fromname; register char * toname; - fromname = ecpyalloc(directory); - fromname = ecatalloc(fromname, "/"); - fromname = ecatalloc(fromname, fromfile); - toname = ecpyalloc(directory); - toname = ecatalloc(toname, "/"); - toname = ecatalloc(toname, tofile); + if (fromfile[0] == '/') + fromname = fromfile; + else { + fromname = ecpyalloc(directory); + fromname = ecatalloc(fromname, "/"); + fromname = ecatalloc(fromname, fromfile); + } + if (tofile[0] == '/') + toname = tofile; + else { + toname = ecpyalloc(directory); + toname = ecatalloc(toname, "/"); + toname = ecatalloc(toname, tofile); + } /* ** We get to be careful here since ** there's a fair chance of root running us. @@ -538,22 +548,29 @@ const char * const tofile; if (!itsdir(toname)) (void) remove(toname); if (link(fromname, toname) != 0) { - (void) fprintf(stderr, "%s: Can't link from %s to ", - progname, fromname); - (void) perror(toname); - (void) exit(EXIT_FAILURE); + if (mkdirs(toname) != 0) + (void) exit(EXIT_FAILURE); + if (link(fromname, toname) != 0) { + (void) fprintf(stderr, "%s: Can't link from %s to ", + progname, fromname); + (void) perror(toname); + (void) exit(EXIT_FAILURE); + } } - ifree(fromname); - ifree(toname); + if (fromname != fromfile) + ifree(fromname); + if (toname != tofile) + ifree(toname); } static void setboundaries() { register time_t bit; + register int bii; for (bit = 1; bit > 0; bit <<= 1) - ; + continue; if (bit == 0) { /* time_t is an unsigned type */ tt_signed = FALSE; min_time = 0; @@ -571,6 +588,11 @@ setboundaries() } min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year; max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year; + + for (bii = 1; bii > 0; bii <<= 1) + continue; + min_int = bii; + max_int = -1 - bii; } static int @@ -832,7 +854,7 @@ const int nfields; if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) { buf = erealloc(buf, 132 + strlen(TZDEFAULT)); (void) sprintf(buf, - "\"Zone %s\" line and -l option are mutually exclusive", +"\"Zone %s\" line and -l option are mutually exclusive", TZDEFAULT); error(buf); return FALSE; @@ -840,7 +862,7 @@ const int nfields; if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) { buf = erealloc(buf, 132 + strlen(TZDEFRULES)); (void) sprintf(buf, - "\"Zone %s\" line and -p option are mutually exclusive", +"\"Zone %s\" line and -p option are mutually exclusive", TZDEFRULES); error(buf); return FALSE; @@ -925,15 +947,20 @@ const int iscont; fields[i_untilyear], "only", "", - (nfields > i_untilmonth) ? fields[i_untilmonth] : "Jan", + (nfields > i_untilmonth) ? + fields[i_untilmonth] : "Jan", (nfields > i_untilday) ? fields[i_untilday] : "1", (nfields > i_untiltime) ? fields[i_untiltime] : "0"); - z.z_untiltime = rpytime(&z.z_untilrule, z.z_untilrule.r_loyear); - if (iscont && nzones > 0 && z.z_untiltime < max_time && + z.z_untiltime = rpytime(&z.z_untilrule, + z.z_untilrule.r_loyear); + if (iscont && nzones > 0 && z.z_untiltime > min_time && + z.z_untiltime < max_time && + zones[nzones - 1].z_untiltime > min_time && + zones[nzones - 1].z_untiltime < max_time && zones[nzones - 1].z_untiltime >= z.z_untiltime) { error("Zone continuation line end time is not after end time of previous line"); - return FALSE; + return FALSE; } } zones = (struct zone *) erealloc((char *) zones, @@ -964,8 +991,7 @@ const int nfields; } dayoff = 0; cp = fields[LP_YEAR]; - if (sscanf(cp, scheck(cp, "%d"), &year) != 1 || - year < min_year || year > max_year) { + if (sscanf(cp, scheck(cp, "%d"), &year) != 1) { /* * Leapin' Lizards! */ @@ -1111,30 +1137,27 @@ char * const timep; cp = loyearp; if ((lp = byword(cp, begin_years)) != NULL) switch ((int) lp->l_value) { case YR_MINIMUM: - rp->r_loyear = min_year; + rp->r_loyear = min_int; break; case YR_MAXIMUM: - rp->r_loyear = max_year; + rp->r_loyear = max_int; break; default: /* "cannot happen" */ (void) fprintf(stderr, "%s: panic: Invalid l_value %d\n", progname, lp->l_value); (void) exit(EXIT_FAILURE); - } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1 || - rp->r_loyear < min_year || rp->r_loyear > max_year) { - if (noise) - error("invalid starting year"); - if (rp->r_loyear > max_year) - return; + } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) { + error("invalid starting year"); + return; } cp = hiyearp; if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) { case YR_MINIMUM: - rp->r_hiyear = min_year; + rp->r_hiyear = min_int; break; case YR_MAXIMUM: - rp->r_hiyear = max_year; + rp->r_hiyear = max_int; break; case YR_ONLY: rp->r_hiyear = rp->r_loyear; @@ -1144,19 +1167,10 @@ char * const timep; "%s: panic: Invalid l_value %d\n", progname, lp->l_value); (void) exit(EXIT_FAILURE); - } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1 || - rp->r_hiyear < min_year || rp->r_hiyear > max_year) { - if (noise) - error("invalid ending year"); - if (rp->r_hiyear < min_year) - return; + } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) { + error("invalid ending year"); + return; } - if (rp->r_hiyear < min_year) - return; - if (rp->r_loyear < min_year) - rp->r_loyear = min_year; - if (rp->r_hiyear > max_year) - rp->r_hiyear = max_year; if (rp->r_loyear > rp->r_hiyear) { error("starting year greater than ending year"); return; @@ -1342,9 +1356,8 @@ const int zonecount; typecnt = 0; charcnt = 0; /* - ** Two guesses. . .the second may well be corrected later. + ** A guess that may well be corrected later. */ - gmtoff = zpfirst->z_gmtoff; stdoff = 0; /* ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au) @@ -1355,19 +1368,23 @@ const int zonecount; starttime = 0; #endif /* defined lint */ for (i = 0; i < zonecount; ++i) { - usestart = i > 0; - useuntil = i < (zonecount - 1); zp = &zpfirst[i]; + usestart = i > 0 && (zp - 1)->z_untiltime > min_time; + useuntil = i < (zonecount - 1); + if (useuntil && zp->z_untiltime <= min_time) + continue; + gmtoff = zp->z_gmtoff; eat(zp->z_filename, zp->z_linenum); startisdst = -1; if (zp->z_nrules == 0) { - type = addtype(oadd(zp->z_gmtoff, zp->z_stdoff), - zp->z_format, zp->z_stdoff != 0, - startttisstd); + stdoff = zp->z_stdoff; + (void) strcpy(startbuf, zp->z_format); + type = addtype(oadd(zp->z_gmtoff, stdoff), + startbuf, stdoff != 0, startttisstd); if (usestart) addtt(starttime, type); - gmtoff = zp->z_gmtoff; - stdoff = zp->z_stdoff; + else if (stdoff != 0) + addtt(min_time, type); } else for (year = min_year; year <= max_year; ++year) { if (useuntil && year > zp->z_untilrule.r_hiyear) break; @@ -1397,11 +1414,11 @@ const int zonecount; ** assuming the current gmtoff and ** stdoff values. */ - offset = gmtoff; - if (!zp->z_untilrule.r_todisstd) - offset = oadd(offset, stdoff); untiltime = tadd(zp->z_untiltime, - -offset); + -gmtoff); + if (!zp->z_untilrule.r_todisstd) + untiltime = tadd(untiltime, + -stdoff); } /* ** Find the rule (of those to do, if any) @@ -1437,21 +1454,33 @@ const int zonecount; if (useuntil && ktime >= untiltime) break; if (usestart) { - if (ktime < starttime) { - stdoff = rp->r_stdoff; - startoff = oadd(zp->z_gmtoff, - rp->r_stdoff); - (void) sprintf(startbuf, - zp->z_format, - rp->r_abbrvar); - startisdst = - rp->r_stdoff != 0; - continue; + if (ktime < starttime) { + stdoff = rp->r_stdoff; + startoff = oadd(zp->z_gmtoff, + rp->r_stdoff); + (void) sprintf(startbuf, zp->z_format, + rp->r_abbrvar); + startisdst = rp->r_stdoff != 0; + continue; + } + usestart = FALSE; + if (ktime != starttime) { + if (startisdst < 0 && + zp->z_gmtoff != + (zp - 1)->z_gmtoff) { + type = (timecnt == 0) ? 0 : + types[timecnt - 1]; + startoff = oadd(gmtoffs[type], + -(zp - 1)->z_gmtoff); + startisdst = startoff != 0; + startoff = oadd(startoff, + zp->z_gmtoff); + (void) strcpy(startbuf, + &chars[abbrinds[type]]); } - if (ktime != starttime && - startisdst >= 0) + if (startisdst >= 0) addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd)); - usestart = FALSE; + } } eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); @@ -1460,9 +1489,7 @@ addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd)); offset = oadd(zp->z_gmtoff, rp->r_stdoff); type = addtype(offset, buf, rp->r_stdoff != 0, rp->r_todisstd); - if (timecnt != 0 || rp->r_stdoff != 0) - addtt(ktime, type); - gmtoff = zp->z_gmtoff; + addtt(ktime, type); stdoff = rp->r_stdoff; } } @@ -1470,9 +1497,10 @@ addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd)); ** Now we may get to set starttime for the next zone line. */ if (useuntil) { - starttime = tadd(zp->z_untiltime, - -gmtoffs[types[timecnt - 1]]); + starttime = tadd(zp->z_untiltime, -gmtoff); startttisstd = zp->z_untilrule.r_todisstd; + if (!startttisstd) + starttime = tadd(starttime, -stdoff); } } writezone(zpfirst->z_name); @@ -1485,6 +1513,8 @@ const int type; { if (timecnt != 0 && type == types[timecnt - 1]) return; /* easy enough! */ + if (timecnt == 0 && type == 0 && isdsts[0] == 0) + return; /* handled by default rule */ if (timecnt >= TZ_MAX_TIMES) { error("too many transitions?!"); (void) exit(EXIT_FAILURE); @@ -1756,6 +1786,10 @@ register const int wantedy; register long dayoff; /* with a nod to Margaret O. */ register time_t t; + if (wantedy == min_int) + return min_time; + if (wantedy == max_int) + return max_time; dayoff = 0; m = TM_JANUARY; y = EPOCH_YEAR; @@ -1809,7 +1843,7 @@ register const int wantedy; } else { dayoff = oadd(dayoff, (long) -1); if (--wday < 0) - wday = LDAYSPERWEEK; + wday = LDAYSPERWEEK - 1; --i; } if (i < 0 || i >= len_months[isleap(y)][m]) { @@ -1817,24 +1851,14 @@ register const int wantedy; (void) exit(EXIT_FAILURE); } } - if (dayoff < 0 && !tt_signed) { - if (wantedy == rp->r_loyear) - return min_time; - error("time before zero"); - (void) exit(EXIT_FAILURE); - } + if (dayoff < 0 && !tt_signed) + return min_time; t = (time_t) dayoff * SECSPERDAY; /* ** Cheap overflow check. */ - if (t / SECSPERDAY != dayoff) { - if (wantedy == rp->r_hiyear) - return max_time; - if (wantedy == rp->r_loyear) - return min_time; - error("time overflow"); - (void) exit(EXIT_FAILURE); - } + if (t / SECSPERDAY != dayoff) + return (dayoff > 0) ? max_time : min_time; return tadd(t, rp->r_tod); } @@ -1845,7 +1869,7 @@ const char * const string; register int i; i = strlen(string) + 1; - if (charcnt + i >= TZ_MAX_CHARS) { + if (charcnt + i > TZ_MAX_CHARS) { error("too many, or too long, time zone abbreviations"); (void) exit(EXIT_FAILURE); } @@ -1853,14 +1877,20 @@ const char * const string; charcnt += eitol(i); } + static int -mkdirs(name) -char * const name; +mkdirs(argname) +char * const argname; { register char * cp; + /* We must make a copy in case the + passed pointer is a read-only string. */ + char *name = ecpyalloc (argname); - if ((cp = name) == NULL || *cp == '\0') - return 0; + if (*cp == '\0') { + ifree (name); + return 0; + } while ((cp = strchr(cp + 1, '/')) != 0) { *cp = '\0'; #ifndef unix @@ -1882,11 +1912,13 @@ char * const name; "%s: Can't create directory ", progname); (void) perror(name); + free (name); return -1; } } *cp = '/'; } + free (name); return 0; } @@ -1898,7 +1930,8 @@ const int i; l = i; if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) { - (void) fprintf(stderr, "%s: %d did not sign extend correctly\n", + (void) fprintf(stderr, + "%s: %d did not sign extend correctly\n", progname, i); (void) exit(EXIT_FAILURE); }