Formerly ../time/sys/time.h.~16~
[kopensolaris-gnu/glibc.git] / time / zic.c
index c6db959..ce384f9 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef lint
 #ifndef NOID
 #ifndef lint
 #ifndef NOID
-static char    elsieid[] = "@(#)zic.c  7.7";
+static char    elsieid[] = "@(#)zic.c  7.21";
 #endif /* !defined NOID */
 #endif /* !defined lint */
 
 #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,
 
 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));
 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 const char *    filename;
 static int             leapcnt;
 static int             linenum;
+static int             max_int;
 static time_t          max_time;
 static int             max_year;
 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;
 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)
                ** 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);
        }
        /*
                outzone(&zones[i], j - i);
        }
        /*
@@ -525,12 +527,20 @@ const char * const        tofile;
        register char * fromname;
        register char * toname;
 
        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.
        /*
        ** 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) {
        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;
 }
 
 static void
 setboundaries()
 {
        register time_t bit;
+       register int bii;
 
        for (bit = 1; bit > 0; bit <<= 1)
 
        for (bit = 1; bit > 0; bit <<= 1)
-               ;
+               continue;
        if (bit == 0) {         /* time_t is an unsigned type */
                tt_signed = FALSE;
                min_time = 0;
        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;
        }
        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
 }
 
 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,
        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;
                        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,
        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;
                        TZDEFRULES);
                error(buf);
                return FALSE;
@@ -925,15 +947,20 @@ const int         iscont;
                        fields[i_untilyear],
                        "only",
                        "",
                        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");
                        (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 > 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");
                        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,
                }
        }
        zones = (struct zone *) erealloc((char *) zones,
@@ -964,8 +991,7 @@ const int           nfields;
        }
        dayoff = 0;
        cp = fields[LP_YEAR];
        }
        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!
                         */
                        /*
                         * 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:
        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:
                        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);
                        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:
        }
        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:
                        break;
                case YR_MAXIMUM:
-                       rp->r_hiyear = max_year;
+                       rp->r_hiyear = max_int;
                        break;
                case YR_ONLY:
                        rp->r_hiyear = rp->r_loyear;
                        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);
                                "%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;
        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;
        /*
        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)
        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) {
        starttime = 0;
 #endif /* defined lint */
        for (i = 0; i < zonecount; ++i) {
-               usestart = i > 0;
-               useuntil = i < (zonecount - 1);
                zp = &zpfirst[i];
                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) {
                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);
                        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;
                } 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.
                                        */
                                        ** assuming the current gmtoff and
                                        ** stdoff values.
                                        */
-                                       offset = gmtoff;
-                                       if (!zp->z_untilrule.r_todisstd)
-                                               offset = oadd(offset, stdoff);
                                        untiltime = tadd(zp->z_untiltime,
                                        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)
                                }
                                /*
                                ** Find the rule (of those to do, if any)
@@ -1437,21 +1454,33 @@ const int                       zonecount;
                                if (useuntil && ktime >= untiltime)
                                        break;
                                if (usestart) {
                                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));
 addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd));
-                                       usestart = FALSE;
+                                   }
                                }
                                eats(zp->z_filename, zp->z_linenum,
                                        rp->r_filename, rp->r_linenum);
                                }
                                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);
                                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;
                        }
                }
                                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) {
                ** 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;
                        startttisstd = zp->z_untilrule.r_todisstd;
+                       if (!startttisstd)
+                               starttime = tadd(starttime, -stdoff);
                }
        }
        writezone(zpfirst->z_name);
                }
        }
        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 == 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);
        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;
 
        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;
        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)
                        } else {
                                dayoff = oadd(dayoff, (long) -1);
                                if (--wday < 0)
-                                       wday = LDAYSPERWEEK;
+                                       wday = LDAYSPERWEEK - 1;
                                --i;
                        }
                if (i < 0 || i >= len_months[isleap(y)][m]) {
                                --i;
                        }
                if (i < 0 || i >= len_months[isleap(y)][m]) {
@@ -1817,24 +1851,14 @@ register const int                      wantedy;
                        (void) exit(EXIT_FAILURE);
                }
        }
                        (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.
        */
        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);
 }
 
        return tadd(t, rp->r_tod);
 }
 
@@ -1845,7 +1869,7 @@ const char * const        string;
        register int    i;
 
        i = strlen(string) + 1;
        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);
        }
                error("too many, or too long, time zone abbreviations");
                (void) exit(EXIT_FAILURE);
        }
@@ -1853,14 +1877,20 @@ const char * const      string;
        charcnt += eitol(i);
 }
 
        charcnt += eitol(i);
 }
 
+
 static int
 static int
-mkdirs(name)
-char * const   name;
+mkdirs(argname)
+char * const   argname;
 {
        register char * cp;
 {
        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
        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);
                                        "%s: Can't create directory ",
                                        progname);
                                (void) perror(name);
+                               free (name);
                                return -1;
                        }
                }
                *cp = '/';
        }
                                return -1;
                        }
                }
                *cp = '/';
        }
+       free (name);
        return 0;
 }
 
        return 0;
 }
 
@@ -1898,7 +1930,8 @@ const int i;
 
        l = i;
        if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) {
 
        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);
        }
                        progname, i);
                (void) exit(EXIT_FAILURE);
        }