Update from tzcode2005c.
authordrepper <drepper>
Tue, 25 Jan 2005 22:15:56 +0000 (22:15 +0000)
committerdrepper <drepper>
Tue, 25 Jan 2005 22:15:56 +0000 (22:15 +0000)
timezone/private.h
timezone/tzfile.h
timezone/zdump.c
timezone/zic.c

index 5766305..5de2f7d 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifndef lint
 #ifndef NOID
-static char    privatehid[] = "@(#)private.h   7.54";
+static char    privatehid[] = "@(#)private.h   7.55";
 #endif /* !defined NOID */
 #endif /* !defined lint */
 
@@ -208,6 +208,7 @@ extern char *       asctime_r();
 /*
 ** Private function declarations.
 */
+
 char * icalloc P((int nelem, int elsize));
 char * icatalloc P((char * old, const char * new));
 char * icpyalloc P((const char * string));
@@ -217,7 +218,6 @@ void        icfree P((char * pointer));
 void   ifree P((char * pointer));
 char * scheck P((const char *string, const char *format));
 
-
 /*
 ** Finally, some convenience items.
 */
@@ -238,6 +238,15 @@ char *     scheck P((const char *string, const char *format));
 #define TYPE_SIGNED(type) (((type) -1) < 0)
 #endif /* !defined TYPE_SIGNED */
 
+/*
+** Since the definition of TYPE_INTEGRAL contains floating point numbers,
+** it cannot be used in preprocessor directives.
+*/
+
+#ifndef TYPE_INTEGRAL
+#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
+#endif /* !defined TYPE_INTEGRAL */
+
 #ifndef INT_STRLEN_MAXIMUM
 /*
 ** 302 / 1000 is log10(2.0) rounded up.
index 0921c3c..0e9966a 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifndef lint
 #ifndef NOID
-static char    tzfilehid[] = "@(#)tzfile.h     7.14";
+static char    tzfilehid[] = "@(#)tzfile.h     7.16";
 #endif /* !defined NOID */
 #endif /* !defined lint */
 
@@ -156,12 +156,21 @@ struct tzhead {
 #define EPOCH_YEAR     1970
 #define EPOCH_WDAY     TM_THURSDAY
 
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
 /*
-** Accurate only for the past couple of centuries;
-** that will probably do.
+** Since everything in isleap is modulo 400 (or a factor of 400), we know that
+**     isleap(y) == isleap(y % 400)
+** and so
+**     isleap(a + b) == isleap((a + b) % 400)
+** or
+**     isleap(a + b) == isleap(a % 400 + b % 400)
+** This is true even if % means modulo rather than Fortran remainder
+** (which is allowed by C89 but not C99).
+** We use this to avoid addition overflow problems.
 */
 
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+#define isleap_sum(a, b)       isleap((a) % 400 + (b) % 400)
 
 #ifndef USG
 
index 20bb916..bd71326 100644 (file)
@@ -1,4 +1,4 @@
-static char    elsieid[] = "@(#)zdump.c        7.40";
+static char    elsieid[] = "@(#)zdump.c        7.61";
 
 /*
 ** This code has been made independent of the rest of the time
@@ -11,6 +11,15 @@ static char  elsieid[] = "@(#)zdump.c        7.40";
 #include "sys/types.h" /* for time_t */
 #include "time.h"      /* for struct tm */
 #include "stdlib.h"    /* for exit, malloc, atoi */
+#include "float.h"     /* for FLT_MAX and DBL_MAX */
+
+#ifndef ZDUMP_LO_YEAR
+#define ZDUMP_LO_YEAR  (-500)
+#endif /* !defined ZDUMP_LO_YEAR */
+
+#ifndef ZDUMP_HI_YEAR
+#define ZDUMP_HI_YEAR  2500
+#endif /* !defined ZDUMP_HI_YEAR */
 
 #ifndef MAX_STRING_LENGTH
 #define MAX_STRING_LENGTH      1024
@@ -61,9 +70,20 @@ static char  elsieid[] = "@(#)zdump.c        7.40";
 #endif /* !defined DAYSPERNYEAR */
 
 #ifndef isleap
-#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
 #endif /* !defined isleap */
 
+#ifndef isleap_sum
+/*
+** See tzfile.h for details on isleap_sum.
+*/
+#define isleap_sum(a, b)       isleap((a) % 400 + (b) % 400)
+#endif /* !defined isleap_sum */
+
+#define SECSPERDAY     ((long) SECSPERHOUR * HOURSPERDAY)
+#define SECSPERNYEAR   (SECSPERDAY * DAYSPERNYEAR)
+#define SECSPERLYEAR   (SECSPERNYEAR + SECSPERDAY)
+
 #if HAVE_GETTEXT
 #include "locale.h"    /* for setlocale */
 #include "libintl.h"
@@ -115,18 +135,60 @@ static char       elsieid[] = "@(#)zdump.c        7.40";
 
 extern char ** environ;
 extern int     getopt P((int argc, char * const argv[],
-                         const char * options));
+                       const char * options));
 extern char *  optarg;
 extern int     optind;
 extern char *  tzname[2];
 
+static time_t  absolute_min_time;
+static time_t  absolute_max_time;
+static size_t  longest;
+static char *  progname;
+
 static char *  abbr P((struct tm * tmp));
 static long    delta P((struct tm * newp, struct tm * oldp));
+static void    dumptime P((const struct tm * tmp));
 static time_t  hunt P((char * name, time_t lot, time_t hit));
-static size_t  longest;
-static char *  progname;
+static void    setabsolutes P((void));
 static void    show P((char * zone, time_t t, int v));
-static void    dumptime P((const struct tm * tmp));
+static const char *    tformat P((void));
+static time_t  yeartot P((long y));
+
+#ifndef TYPECHECK
+#define my_localtime   localtime
+#else /* !defined TYPECHECK */
+static struct tm *
+my_localtime(tp)
+time_t *       tp;
+{
+       register struct tm *    tmp;
+
+       tmp = localtime(tp);
+       if (tp != NULL && tmp != NULL) {
+               struct tm       tm;
+               register time_t t;
+
+               tm = *tmp;
+               t = mktime(&tm);
+               if (t - *tp >= 1 || *tp - t >= 1) {
+                       (void) fflush(stdout);
+                       (void) fprintf(stderr, "\n%s: ", progname);
+                       (void) fprintf(stderr, tformat(), *tp);
+                       (void) fprintf(stderr, " ->");
+                       (void) fprintf(stderr, " sec %d", tmp->tm_sec);
+                       (void) fprintf(stderr, " min %d", tmp->tm_min);
+                       (void) fprintf(stderr, " hour %d", tmp->tm_hour);
+                       (void) fprintf(stderr, " mday %d", tmp->tm_mday);
+                       (void) fprintf(stderr, " mon %d", tmp->tm_mon);
+                       (void) fprintf(stderr, " year %d", tmp->tm_year);
+                       (void) fprintf(stderr, " -> ");
+                       (void) fprintf(stderr, tformat(), t);
+                       (void) fprintf(stderr, "\n");
+               }
+       }
+       return tmp;
+}
+#endif /* !defined TYPECHECK */
 
 int
 main(argc, argv)
@@ -136,18 +198,22 @@ char *    argv[];
        register int            i;
        register int            c;
        register int            vflag;
-       register char *         cutoff;
-       register int            cutyear;
-       register long           cuttime;
-       char **                 fakeenv;
+       register char *         cutarg;
+       register long           cutloyear = ZDUMP_LO_YEAR;
+       register long           cuthiyear = ZDUMP_HI_YEAR;
+       register time_t         cutlotime;
+       register time_t         cuthitime;
+       register char **        fakeenv;
        time_t                  now;
        time_t                  t;
        time_t                  newt;
-       time_t                  hibit;
        struct tm               tm;
        struct tm               newtm;
+       register struct tm *    tmp;
+       register struct tm *    newtmp;
 
-       INITIALIZE(cuttime);
+       INITIALIZE(cutlotime);
+       INITIALIZE(cuthitime);
 #if HAVE_GETTEXT
        (void) setlocale(LC_MESSAGES, "");
 #ifdef TZ_DOMAINDIR
@@ -162,39 +228,50 @@ char *    argv[];
                        (void) exit(EXIT_SUCCESS);
                }
        vflag = 0;
-       cutoff = NULL;
+       cutarg = NULL;
        while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
                if (c == 'v')
                        vflag = 1;
-               else    cutoff = optarg;
+               else    cutarg = optarg;
        if ((c != EOF && c != -1) ||
                (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
                        (void) fprintf(stderr,
-_("%s: usage is %s [ --version ] [ -v ] [ -c cutoff ] zonename ...\n"),
-                               argv[0], argv[0]);
+_("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
+                               progname, progname);
                        (void) exit(EXIT_FAILURE);
        }
-       if (cutoff != NULL) {
-               int     y;
-
-               cutyear = atoi(cutoff);
-               cuttime = 0;
-               for (y = EPOCH_YEAR; y < cutyear; ++y)
-                       cuttime += DAYSPERNYEAR + isleap(y);
-               cuttime *= SECSPERHOUR * HOURSPERDAY;
+       if (vflag) {
+               if (cutarg != NULL) {
+                       long    lo;
+                       long    hi;
+                       char    dummy;
+
+                       if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) {
+                               cuthiyear = hi;
+                       } else if (sscanf(cutarg, "%ld,%ld%c",
+                               &lo, &hi, &dummy) == 2) {
+                                       cutloyear = lo;
+                                       cuthiyear = hi;
+                       } else {
+(void) fprintf(stderr, _("%s: wild -c argument %s\n"),
+                                       progname, cutarg);
+                               (void) exit(EXIT_FAILURE);
+                       }
+               }
+               setabsolutes();
+               cutlotime = yeartot(cutloyear);
+               cuthitime = yeartot(cuthiyear);
        }
        (void) time(&now);
        longest = 0;
        for (i = optind; i < argc; ++i)
                if (strlen(argv[i]) > longest)
                        longest = strlen(argv[i]);
-       for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
-               continue;
        {
                register int    from;
                register int    to;
 
-               for (i = 0;  environ[i] != NULL;  ++i)
+               for (i = 0; environ[i] != NULL; ++i)
                        continue;
                fakeenv = (char **) malloc((size_t) ((i + 2) *
                        sizeof *fakeenv));
@@ -219,58 +296,129 @@ _("%s: usage is %s [ --version ] [ -v ] [ -c cutoff ] zonename ...\n"),
                        show(argv[i], now, FALSE);
                        continue;
                }
-               /*
-               ** Get lowest value of t.
-               */
-               t = hibit;
-               if (t > 0)              /* time_t is unsigned */
-                       t = 0;
+               t = absolute_min_time;
                show(argv[i], t, TRUE);
                t += SECSPERHOUR * HOURSPERDAY;
                show(argv[i], t, TRUE);
-               tm = *localtime(&t);
-               (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
+               if (t < cutlotime)
+                       t = cutlotime;
+               tmp = my_localtime(&t);
+               if (tmp != NULL) {
+                       tm = *tmp;
+                       (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
+               }
                for ( ; ; ) {
-                       if (cutoff != NULL && t >= cuttime)
+                       if (t >= cuthitime)
                                break;
                        newt = t + SECSPERHOUR * 12;
-                       if (cutoff != NULL && newt >= cuttime)
+                       if (newt >= cuthitime)
                                break;
                        if (newt <= t)
                                break;
-                       newtm = *localtime(&newt);
-                       if (delta(&newtm, &tm) != (newt - t) ||
+                       newtmp = localtime(&newt);
+                       if (newtmp != NULL)
+                               newtm = *newtmp;
+                       if ((tmp == NULL || newtmp == NULL) ?  (tmp != newtmp) :
+                               (delta(&newtm, &tm) != (newt - t) ||
                                newtm.tm_isdst != tm.tm_isdst ||
-                               strcmp(abbr(&newtm), buf) != 0) {
+                               strcmp(abbr(&newtm), buf) != 0)) {
                                        newt = hunt(argv[i], t, newt);
-                                       newtm = *localtime(&newt);
-                                       (void) strncpy(buf, abbr(&newtm),
-                                               (sizeof buf) - 1);
+                                       newtmp = localtime(&newt);
+                                       if (newtmp != NULL) {
+                                               newtm = *newtmp;
+                                               (void) strncpy(buf,
+                                                       abbr(&newtm),
+                                                       (sizeof buf) - 1);
+                                       }
                        }
                        t = newt;
                        tm = newtm;
+                       tmp = newtmp;
                }
-               /*
-               ** Get highest value of t.
-               */
-               t = ~((time_t) 0);
-               if (t < 0)              /* time_t is signed */
-                       t &= ~hibit;
+               t = absolute_max_time;
                t -= SECSPERHOUR * HOURSPERDAY;
                show(argv[i], t, TRUE);
                t += SECSPERHOUR * HOURSPERDAY;
                show(argv[i], t, TRUE);
        }
        if (fflush(stdout) || ferror(stdout)) {
-               (void) fprintf(stderr, "%s: ", argv[0]);
+               (void) fprintf(stderr, "%s: ", progname);
                (void) perror(_("Error writing standard output"));
                (void) exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
+       /* If exit fails to exit... */
+       return EXIT_FAILURE;
+}
+
+static void
+setabsolutes()
+{
+       if (0.5 == (time_t) 0.5) {
+               /*
+               ** time_t is floating.
+               */
+               if (sizeof (time_t) == sizeof (float)) {
+                       absolute_min_time = (time_t) -FLT_MAX;
+                       absolute_max_time = (time_t) FLT_MAX;
+               } else if (sizeof (time_t) == sizeof (double)) {
+                       absolute_min_time = (time_t) -DBL_MAX;
+                       absolute_max_time = (time_t) DBL_MAX;
+               } else {
+                       (void) fprintf(stderr,
+_("%s: use of -v on system with floating time_t other than float or double\n"),
+                               progname);
+                       (void) exit(EXIT_FAILURE);
+               }
+       } else if (0 > (time_t) -1) {
+               /*
+               ** time_t is signed.
+               */
+               register time_t hibit;
 
-       /* gcc -Wall pacifier */
-       for ( ; ; )
-               continue;
+               for (hibit = 1; (hibit * 2) != 0; hibit *= 2)
+                       continue;
+               absolute_min_time = hibit;
+               absolute_max_time = -(hibit + 1);
+       } else {
+               /*
+               ** time_t is unsigned.
+               */
+               absolute_min_time = 0;
+               absolute_max_time = absolute_min_time - 1;
+       }
+}
+
+static time_t
+yeartot(y)
+const long     y;
+{
+       register long   myy;
+       register long   seconds;
+       register time_t t;
+
+       myy = EPOCH_YEAR;
+       t = 0;
+       while (myy != y) {
+               if (myy < y) {
+                       seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
+                       ++myy;
+                       if (t > absolute_max_time - seconds) {
+                               t = absolute_max_time;
+                               break;
+                       }
+                       t += seconds;
+               } else {
+                       --myy;
+                       seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
+                       if (t < absolute_min_time + seconds) {
+                               t = absolute_min_time;
+                               break;
+                       }
+                       t -= seconds;
+               }
+       }
+       return t;
 }
 
 static time_t
@@ -279,25 +427,39 @@ char *    name;
 time_t lot;
 time_t hit;
 {
-       time_t          t;
-       struct tm       lotm;
-       struct tm       tm;
-       static char     loab[MAX_STRING_LENGTH];
-
-       lotm = *localtime(&lot);
-       (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
-       while ((hit - lot) >= 2) {
-               t = lot / 2 + hit / 2;
+       time_t                  t;
+       long                    diff;
+       struct tm               lotm;
+       register struct tm *    lotmp;
+       struct tm               tm;
+       register struct tm *    tmp;
+       char                    loab[MAX_STRING_LENGTH];
+
+       lotmp = my_localtime(&lot);
+       if (lotmp != NULL) {
+               lotm = *lotmp;
+               (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
+       }
+       for ( ; ; ) {
+               diff = (long) (hit - lot);
+               if (diff < 2)
+                       break;
+               t = lot;
+               t += diff / 2;
                if (t <= lot)
                        ++t;
                else if (t >= hit)
                        --t;
-               tm = *localtime(&t);
-               if (delta(&tm, &lotm) == (t - lot) &&
+               tmp = my_localtime(&t);
+               if (tmp != NULL)
+                       tm = *tmp;
+               if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) :
+                       (delta(&tm, &lotm) == (t - lot) &&
                        tm.tm_isdst == lotm.tm_isdst &&
-                       strcmp(abbr(&tm), loab) == 0) {
+                       strcmp(abbr(&tm), loab) == 0)) {
                                lot = t;
                                lotm = tm;
+                               lotmp = tmp;
                } else  hit = t;
        }
        show(name, lot, TRUE);
@@ -314,14 +476,14 @@ delta(newp, oldp)
 struct tm *    newp;
 struct tm *    oldp;
 {
-       long    result;
-       int     tmy;
+       register long   result;
+       register int    tmy;
 
        if (newp->tm_year < oldp->tm_year)
                return -delta(oldp, newp);
        result = 0;
        for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
-               result += DAYSPERNYEAR + isleap(tmy + (long) TM_YEAR_BASE);
+               result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE);
        result += newp->tm_yday - oldp->tm_yday;
        result *= HOURSPERDAY;
        result += newp->tm_hour - oldp->tm_hour;
@@ -338,22 +500,30 @@ char *    zone;
 time_t t;
 int    v;
 {
-       struct tm *     tmp;
+       register struct tm *    tmp;
 
        (void) printf("%-*s  ", (int) longest, zone);
        if (v) {
-               dumptime(gmtime(&t));
-               (void) printf(" UTC = ");
+               tmp = gmtime(&t);
+               if (tmp == NULL) {
+                       (void) printf(tformat(), t);
+               } else {
+                       dumptime(tmp);
+                       (void) printf(" UTC");
+               }
+               (void) printf(" = ");
        }
-       tmp = localtime(&t);
+       tmp = my_localtime(&t);
        dumptime(tmp);
-       if (*abbr(tmp) != '\0')
-               (void) printf(" %s", abbr(tmp));
-       if (v) {
-               (void) printf(" isdst=%d", tmp->tm_isdst);
+       if (tmp != NULL) {
+               if (*abbr(tmp) != '\0')
+                       (void) printf(" %s", abbr(tmp));
+               if (v) {
+                       (void) printf(" isdst=%d", tmp->tm_isdst);
 #ifdef TM_GMTOFF
-               (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
+                       (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
 #endif /* defined TM_GMTOFF */
+               }
        }
        (void) printf("\n");
 }
@@ -371,6 +541,33 @@ struct tm *        tmp;
        return (result == NULL) ? &nada : result;
 }
 
+/*
+** The code below can fail on certain theoretical systems;
+** it works on all known real-world systems as of 2004-12-30.
+*/
+
+static const char *
+tformat()
+{
+       if (0.5 == (time_t) 0.5) {      /* floating */
+               if (sizeof (time_t) > sizeof (double))
+                       return "%Lg";
+               return "%g";
+       }
+       if (0 > (time_t) -1) {          /* signed */
+               if (sizeof (time_t) > sizeof (long))
+                       return "%lld";
+               if (sizeof (time_t) > sizeof (int))
+                       return "%ld";
+               return "%d";
+       }
+       if (sizeof (time_t) > sizeof (unsigned long))
+               return "%llu";
+       if (sizeof (time_t) > sizeof (unsigned int))
+               return "%lu";
+       return "%u";
+}
+
 static void
 dumptime(timeptr)
 register const struct tm *     timeptr;
@@ -384,7 +581,13 @@ register const struct tm * timeptr;
        };
        register const char *   wn;
        register const char *   mn;
+       register int            lead;
+       register int            trail;
 
+       if (timeptr == NULL) {
+               (void) printf("NULL");
+               return;
+       }
        /*
        ** The packaged versions of localtime and gmtime never put out-of-range
        ** values in tm_wday or tm_mon, but since this code might be compiled
@@ -398,9 +601,23 @@ register const struct tm * timeptr;
                (int) (sizeof mon_name / sizeof mon_name[0]))
                        mn = "???";
        else            mn = mon_name[timeptr->tm_mon];
-       (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d %ld",
+       (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
                wn, mn,
                timeptr->tm_mday, timeptr->tm_hour,
-               timeptr->tm_min, timeptr->tm_sec,
-               timeptr->tm_year + (long) TM_YEAR_BASE);
+               timeptr->tm_min, timeptr->tm_sec);
+#define DIVISOR        10
+       trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR;
+       lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR +
+               trail / DIVISOR;
+       trail %= DIVISOR;
+       if (trail < 0 && lead > 0) {
+               trail += DIVISOR;
+               --lead;
+       } else if (lead < 0 && trail > 0) {
+               trail -= DIVISOR;
+               ++lead;
+       }
+       if (lead == 0)
+               (void) printf("%d", trail);
+       else    (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail));
 }
index 9bb8662..d855475 100644 (file)
@@ -1,4 +1,10 @@
-static char    elsieid[] = "@(#)zic.c  7.116";
+static char    elsieid[] = "@(#)zic.c  7.118";
+
+/*
+** Regardless of the type of time_t, we do our work using this type.
+*/
+
+typedef int    zic_t;
 
 #include "private.h"
 #include "locale.h"
@@ -50,7 +56,7 @@ struct rule {
        const char *    r_abbrvar;      /* variable part of abbreviation */
 
        int             r_todo;         /* a rule to do (used in outzone) */
-       time_t          r_temp;         /* used in outzone */
+       zic_t           r_temp;         /* used in outzone */
 };
 
 /*
@@ -76,7 +82,7 @@ struct zone {
        int             z_nrules;
 
        struct rule     z_untilrule;
-       time_t          z_untiltime;
+       zic_t           z_untiltime;
 };
 
 extern int     getopt P((int argc, char * const argv[],
@@ -85,10 +91,10 @@ extern int  link P((const char * fromname, const char * toname));
 extern char *  optarg;
 extern int     optind;
 
-static void    addtt P((time_t starttime, int type));
+static void    addtt P((zic_t starttime, int type));
 static int     addtype P((long gmtoff, const char * abbr, int isdst,
                                int ttisstd, int ttisgmt));
-static void    leapadd P((time_t t, int positive, int rolling, int count));
+static void    leapadd P((zic_t t, int positive, int rolling, int count));
 static void    adjleap P((void));
 static void    associate P((void));
 static int     ciequal P((const char * ap, const char * bp));
@@ -121,13 +127,13 @@ static long       oadd P((long t1, long t2));
 static void    outzone P((const struct zone * zp, int ntzones));
 static void    puttzcode P((long code, FILE * fp));
 static int     rcomp P((const void * leftp, const void * rightp));
-static time_t  rpytime P((const struct rule * rp, int wantedy));
+static zic_t   rpytime P((const struct rule * rp, int wantedy));
 static void    rulesub P((struct rule * rp,
                        const char * loyearp, const char * hiyearp,
                        const char * typep, const char * monthp,
                        const char * dayp, const char * timep));
 static void    setboundaries P((void));
-static time_t  tadd P((time_t t1, long t2));
+static zic_t   tadd P((zic_t t1, long t2));
 static void    usage P((void));
 static void    writezone P((const char * name));
 static int     yearistype P((int year, const char * type));
@@ -141,10 +147,10 @@ static int                errors;
 static const char *    filename;
 static int             leapcnt;
 static int             linenum;
-static time_t          max_time;
+static zic_t           max_time;
 static int             max_year;
 static int             max_year_representable;
-static time_t          min_time;
+static zic_t           min_time;
 static int             min_year;
 static int             min_year_representable;
 static int             noise;
@@ -334,7 +340,7 @@ static const int    len_years[2] = {
 };
 
 static struct attype {
-       time_t          at;
+       zic_t           at;
        unsigned char   type;
 }                      attypes[TZ_MAX_TIMES];
 static long            gmtoffs[TZ_MAX_TYPES];
@@ -343,7 +349,7 @@ static unsigned char        abbrinds[TZ_MAX_TYPES];
 static char            ttisstds[TZ_MAX_TYPES];
 static char            ttisgmts[TZ_MAX_TYPES];
 static char            chars[TZ_MAX_CHARS];
-static time_t          trans[TZ_MAX_LEAPS];
+static zic_t           trans[TZ_MAX_LEAPS];
 static long            corr[TZ_MAX_LEAPS];
 static char            roll[TZ_MAX_LEAPS];
 
@@ -629,7 +635,7 @@ const char * const  tofile;
                        register char * symlinkcontents = NULL;
                        while ((s = strchr(s+1, '/')) != NULL)
                                symlinkcontents = ecatalloc(symlinkcontents, "../");
-                       symlinkcontents = ecatalloc(symlinkcontents, fromname);
+                       symlinkcontents = ecatalloc(symlinkcontents, fromfile);
 
                        result = unlink(toname);
                        if (result != 0 && errno != ENOENT) {
@@ -676,25 +682,36 @@ warning(_("hard link failed, symbolic link used"));
 */
 
 #define MAX_BITS_IN_FILE       32
-#define TIME_T_BITS_IN_FILE    ((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE)
+#define TIME_T_BITS_IN_FILE    ((TYPE_BIT(zic_t) < MAX_BITS_IN_FILE) ? \
+                                       TYPE_BIT(zic_t) : MAX_BITS_IN_FILE)
 
 static void
 setboundaries P((void))
 {
-       if (TYPE_SIGNED(time_t)) {
-               min_time = ~ (time_t) 0;
-               min_time <<= TIME_T_BITS_IN_FILE - 1;
-               max_time = ~ (time_t) 0 - min_time;
+       register int    i;
+
+       if (TYPE_SIGNED(zic_t)) {
+               min_time = -1;
+               for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
+                       min_time *= 2;
+               max_time = -(min_time + 1);
                if (sflag)
                        min_time = 0;
        } else {
                min_time = 0;
                max_time = 2 - sflag;
-               max_time <<= TIME_T_BITS_IN_FILE - 1;
+               for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
+                       max_time *= 2;
                --max_time;
        }
-       min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
-       max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
+       {
+               time_t  t;
+
+               t = (time_t) min_time;
+               min_year = TM_YEAR_BASE + gmtime(&t)->tm_year;
+               t = (time_t) max_time;
+               max_year = TM_YEAR_BASE + gmtime(&t)->tm_year;
+       }
        min_year_representable = min_year;
        max_year_representable = max_year;
 }
@@ -1120,7 +1137,7 @@ const int         nfields;
        register int                    i, j;
        int                             year, month, day;
        long                            dayoff, tod;
-       time_t                          t;
+       zic_t                           t;
 
        if (nfields != LEAP_FIELDS) {
                error(_("wrong number of fields on Leap line"));
@@ -1164,7 +1181,7 @@ const int         nfields;
                        return;
        }
        dayoff = oadd(dayoff, eitol(day - 1));
-       if (dayoff < 0 && !TYPE_SIGNED(time_t)) {
+       if (dayoff < 0 && !TYPE_SIGNED(zic_t)) {
                error(_("time before zero"));
                return;
        }
@@ -1176,7 +1193,7 @@ const int         nfields;
                error(_("time too large"));
                return;
        }
-       t = (time_t) dayoff * SECSPERDAY;
+       t = (zic_t) dayoff * SECSPERDAY;
        tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
        cp = fields[LP_CORR];
        {
@@ -1438,7 +1455,7 @@ const char * const        name;
        register int            i, j;
        static char *           fullname;
        static struct tzhead    tzh;
-       time_t                  ats[TZ_MAX_TIMES];
+       zic_t                   ats[TZ_MAX_TIMES];
        unsigned char           types[TZ_MAX_TIMES];
 
        /*
@@ -1603,7 +1620,7 @@ const int                 zonecount;
        register struct rule *          rp;
        register int                    i, j;
        register int                    usestart, useuntil;
-       register time_t                 starttime, untiltime;
+       register zic_t                  starttime, untiltime;
        register long                   gmtoff;
        register long                   stdoff;
        register int                    year;
@@ -1672,7 +1689,7 @@ const int                 zonecount;
                        }
                        for ( ; ; ) {
                                register int    k;
-                               register time_t jtime, ktime;
+                               register zic_t  jtime, ktime;
                                register long   offset;
                                char            buf[BUFSIZ];
 
@@ -1784,7 +1801,7 @@ error(_("can't determine time zone abbreviation to use just after until time"));
 
 static void
 addtt(starttime, type)
-const time_t   starttime;
+const zic_t    starttime;
 int            type;
 {
        if (starttime <= min_time ||
@@ -1868,7 +1885,7 @@ const int         ttisgmt;
 
 static void
 leapadd(t, positive, rolling, count)
-const time_t   t;
+const zic_t    t;
 const int      positive;
 const int      rolling;
 int            count;
@@ -2056,12 +2073,12 @@ const long      t2;
        return t;
 }
 
-static time_t
+static zic_t
 tadd(t1, t2)
-const time_t   t1;
+const zic_t    t1;
 const long     t2;
 {
-       register time_t t;
+       register zic_t  t;
 
        if (t1 == max_time && t2 > 0)
                return max_time;
@@ -2080,14 +2097,14 @@ const long      t2;
 ** 1970, 00:00 LOCAL time - in that year that the rule refers to.
 */
 
-static time_t
+static zic_t
 rpytime(rp, wantedy)
 register const struct rule * const     rp;
 register const int                     wantedy;
 {
        register int    y, m, i;
        register long   dayoff;                 /* with a nod to Margaret O. */
-       register time_t t;
+       register zic_t  t;
 
        if (wantedy == INT_MIN)
                return min_time;
@@ -2154,15 +2171,13 @@ register const int                      wantedy;
                                warning(_("rule goes past start/end of month--will not work with pre-2004 versions of zic"));
                }
        }
-       if (dayoff < 0 && !TYPE_SIGNED(time_t))
+       if (dayoff < 0 && !TYPE_SIGNED(zic_t))
                return min_time;
        if (dayoff < min_time / SECSPERDAY)
                return min_time;
        if (dayoff > max_time / SECSPERDAY)
                return max_time;
-       t = (time_t) dayoff * SECSPERDAY;
-       if (t > 0 && max_time - t < rp->r_tod)
-               return max_time;
+       t = (zic_t) dayoff * SECSPERDAY;
        return tadd(t, rp->r_tod);
 }