]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Convert DOS newlines to Unix newlines.
authorBruce Momjian <bruce@momjian.us>
Fri, 30 Apr 2004 04:44:06 +0000 (04:44 +0000)
committerBruce Momjian <bruce@momjian.us>
Fri, 30 Apr 2004 04:44:06 +0000 (04:44 +0000)
src/timezone/asctime.c
src/timezone/difftime.c
src/timezone/ialloc.c
src/timezone/localtime.c
src/timezone/pgtz.h
src/timezone/private.h
src/timezone/scheck.c
src/timezone/tzfile.h
src/timezone/zic.c

index 31a6275edc933596eb5f4881c128bb126f73b2db..d19e1dc1925052f21a35420adb84c66ba524058e 100644 (file)
@@ -1,75 +1,75 @@
-#include "pgtz.h"\r
-/*\r
-** This file is in the public domain, so clarified as of\r
-** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).\r
-*/\r
-\r
-#ifndef lint\r
-#ifndef NOID\r
-static char    elsieid[] = "@(#)asctime.c      7.9";\r
-#endif /* !defined NOID */\r
-#endif /* !defined lint */\r
-\r
-/*LINTLIBRARY*/\r
-\r
-#include "private.h"\r
-#include "tzfile.h"\r
-\r
-/*\r
-** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, Second Edition, 1996-07-12.\r
-*/\r
-\r
-char *\r
-asctime_r(timeptr, buf)\r
-register const struct tm *     timeptr;\r
-char *                         buf;\r
-{\r
-       static const char       wday_name[][3] = {\r
-               "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"\r
-       };\r
-       static const char       mon_name[][3] = {\r
-               "Jan", "Feb", "Mar", "Apr", "May", "Jun",\r
-               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"\r
-       };\r
-       register const char *   wn;\r
-       register const char *   mn;\r
-\r
-       if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)\r
-               wn = "???";\r
-       else    wn = wday_name[timeptr->tm_wday];\r
-       if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)\r
-               mn = "???";\r
-       else    mn = mon_name[timeptr->tm_mon];\r
-       /*\r
-       ** The X3J11-suggested format is\r
-       **      "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"\r
-       ** Since the .2 in 02.2d is ignored, we drop it.\r
-       */\r
-       (void) sprintf(buf, "%.3s %.3s%3d %02d:%02d:%02d %d\n",\r
-               wn, mn,\r
-               timeptr->tm_mday, timeptr->tm_hour,\r
-               timeptr->tm_min, timeptr->tm_sec,\r
-               TM_YEAR_BASE + timeptr->tm_year);\r
-       return buf;\r
-}\r
-\r
-/*\r
-** A la X3J11, with core dump avoidance.\r
-*/\r
-\r
-char *\r
-asctime(timeptr)\r
-register const struct tm *     timeptr;\r
-{\r
-       /*\r
-       ** Big enough for something such as\r
-       ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n\r
-       ** (two three-character abbreviations, five strings denoting integers,\r
-       ** three explicit spaces, two explicit colons, a newline,\r
-       ** and a trailing ASCII nul).\r
-       */\r
-       static char             result[3 * 2 + 5 * INT_STRLEN_MAXIMUM(int) +\r
-                                       3 + 2 + 1 + 1];\r
-\r
-       return asctime_r(timeptr, result);\r
-}\r
+#include "pgtz.h"
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+#ifndef lint
+#ifndef NOID
+static char    elsieid[] = "@(#)asctime.c      7.9";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+#include "tzfile.h"
+
+/*
+** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, Second Edition, 1996-07-12.
+*/
+
+char *
+asctime_r(timeptr, buf)
+register const struct tm *     timeptr;
+char *                         buf;
+{
+       static const char       wday_name[][3] = {
+               "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+       };
+       static const char       mon_name[][3] = {
+               "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+       };
+       register const char *   wn;
+       register const char *   mn;
+
+       if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
+               wn = "???";
+       else    wn = wday_name[timeptr->tm_wday];
+       if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
+               mn = "???";
+       else    mn = mon_name[timeptr->tm_mon];
+       /*
+       ** The X3J11-suggested format is
+       **      "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"
+       ** Since the .2 in 02.2d is ignored, we drop it.
+       */
+       (void) sprintf(buf, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
+               wn, mn,
+               timeptr->tm_mday, timeptr->tm_hour,
+               timeptr->tm_min, timeptr->tm_sec,
+               TM_YEAR_BASE + timeptr->tm_year);
+       return buf;
+}
+
+/*
+** A la X3J11, with core dump avoidance.
+*/
+
+char *
+asctime(timeptr)
+register const struct tm *     timeptr;
+{
+       /*
+       ** Big enough for something such as
+       ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
+       ** (two three-character abbreviations, five strings denoting integers,
+       ** three explicit spaces, two explicit colons, a newline,
+       ** and a trailing ASCII nul).
+       */
+       static char             result[3 * 2 + 5 * INT_STRLEN_MAXIMUM(int) +
+                                       3 + 2 + 1 + 1];
+
+       return asctime_r(timeptr, result);
+}
index 636640d6f572e0ba02a8c33fd6066cbd0ae8099b..57b88deafee79848714e80ceec7c6c13b19bea5f 100644 (file)
@@ -1,84 +1,84 @@
-#include "pgtz.h"\r
-/*\r
-** This file is in the public domain, so clarified as of\r
-** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).\r
-*/\r
-\r
-#ifndef lint\r
-#ifndef NOID\r
-static char    elsieid[] = "@(#)difftime.c     7.9";\r
-#endif /* !defined NOID */\r
-#endif /* !defined lint */\r
-\r
-/*LINTLIBRARY*/\r
-\r
-#include "private.h"\r
-\r
-/*\r
-** Algorithm courtesy Paul Eggert (eggert@twinsun.com).\r
-*/\r
-\r
-#ifdef HAVE_LONG_DOUBLE\r
-#define long_double    long double\r
-#endif /* defined HAVE_LONG_DOUBLE */\r
-#ifndef HAVE_LONG_DOUBLE\r
-#define long_double    double\r
-#endif /* !defined HAVE_LONG_DOUBLE */\r
-\r
-double\r
-difftime(time1, time0)\r
-const time_t   time1;\r
-const time_t   time0;\r
-{\r
-       time_t  delta;\r
-       time_t  hibit;\r
-\r
-       {\r
-               time_t          tt;\r
-               double          d;\r
-               long_double     ld;\r
-\r
-               if (sizeof tt < sizeof d)\r
-                       return (double) time1 - (double) time0;\r
-               if (sizeof tt < sizeof ld)\r
-                       return (long_double) time1 - (long_double) time0;\r
-       }\r
-       if (time1 < time0)\r
-               return -difftime(time0, time1);\r
-       /*\r
-       ** As much as possible, avoid loss of precision\r
-       ** by computing the difference before converting to double.\r
-       */\r
-       delta = time1 - time0;\r
-       if (delta >= 0)\r
-               return delta;\r
-       /*\r
-       ** Repair delta overflow.\r
-       */\r
-       hibit = (~ (time_t) 0) << (TYPE_BIT(time_t) - 1);\r
-       /*\r
-       ** The following expression rounds twice, which means\r
-       ** the result may not be the closest to the true answer.\r
-       ** For example, suppose time_t is 64-bit signed int,\r
-       ** long_double is IEEE 754 double with default rounding,\r
-       ** time1 = 9223372036854775807 and time0 = -1536.\r
-       ** Then the true difference is 9223372036854777343,\r
-       ** which rounds to 9223372036854777856\r
-       ** with a total error of 513.\r
-       ** But delta overflows to -9223372036854774273,\r
-       ** which rounds to -9223372036854774784, and correcting\r
-       ** this by subtracting 2 * (long_double) hibit\r
-       ** (i.e. by adding 2**64 = 18446744073709551616)\r
-       ** yields 9223372036854776832, which\r
-       ** rounds to 9223372036854775808\r
-       ** with a total error of 1535 instead.\r
-       ** This problem occurs only with very large differences.\r
-       ** It's too painful to fix this portably.\r
-       ** We are not alone in this problem;\r
-       ** some C compilers round twice when converting\r
-       ** large unsigned types to small floating types,\r
-       ** so if time_t is unsigned the "return delta" above\r
-       ** has the same double-rounding problem with those compilers.\r
-       */\r
-       return delta - 2 * (long_double) hibit;\r
-}\r
+#include "pgtz.h"
+/*
+** This file is in the public domain, so clarified as of
+** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+#ifndef lint
+#ifndef NOID
+static char    elsieid[] = "@(#)difftime.c     7.9";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+
+/*
+** Algorithm courtesy Paul Eggert (eggert@twinsun.com).
+*/
+
+#ifdef HAVE_LONG_DOUBLE
+#define long_double    long double
+#endif /* defined HAVE_LONG_DOUBLE */
+#ifndef HAVE_LONG_DOUBLE
+#define long_double    double
+#endif /* !defined HAVE_LONG_DOUBLE */
+
+double
+difftime(time1, time0)
+const time_t   time1;
+const time_t   time0;
+{
+       time_t  delta;
+       time_t  hibit;
+
+       {
+               time_t          tt;
+               double          d;
+               long_double     ld;
+
+               if (sizeof tt < sizeof d)
+                       return (double) time1 - (double) time0;
+               if (sizeof tt < sizeof ld)
+                       return (long_double) time1 - (long_double) time0;
+       }
+       if (time1 < time0)
+               return -difftime(time0, time1);
+       /*
+       ** As much as possible, avoid loss of precision
+       ** by computing the difference before converting to double.
+       */
+       delta = time1 - time0;
+       if (delta >= 0)
+               return delta;
+       /*
+       ** Repair delta overflow.
+       */
+       hibit = (~ (time_t) 0) << (TYPE_BIT(time_t) - 1);
+       /*
+       ** The following expression rounds twice, which means
+       ** the result may not be the closest to the true answer.
+       ** For example, suppose time_t is 64-bit signed int,
+       ** long_double is IEEE 754 double with default rounding,
+       ** time1 = 9223372036854775807 and time0 = -1536.
+       ** Then the true difference is 9223372036854777343,
+       ** which rounds to 9223372036854777856
+       ** with a total error of 513.
+       ** But delta overflows to -9223372036854774273,
+       ** which rounds to -9223372036854774784, and correcting
+       ** this by subtracting 2 * (long_double) hibit
+       ** (i.e. by adding 2**64 = 18446744073709551616)
+       ** yields 9223372036854776832, which
+       ** rounds to 9223372036854775808
+       ** with a total error of 1535 instead.
+       ** This problem occurs only with very large differences.
+       ** It's too painful to fix this portably.
+       ** We are not alone in this problem;
+       ** some C compilers round twice when converting
+       ** large unsigned types to small floating types,
+       ** so if time_t is unsigned the "return delta" above
+       ** has the same double-rounding problem with those compilers.
+       */
+       return delta - 2 * (long_double) hibit;
+}
index ea457aeb6646f9d85d40594b8f6205f08d1d591b..8a0c7015789022a3dbf82bdf2257bd8fb0512975 100644 (file)
@@ -1,81 +1,81 @@
-#ifndef lint\r
-#ifndef NOID\r
-static char    elsieid[] = "@(#)ialloc.c       8.29";\r
-#endif /* !defined NOID */\r
-#endif /* !defined lint */\r
-\r
-/*LINTLIBRARY*/\r
-\r
-#include "private.h"\r
-\r
-#define nonzero(n)     (((n) == 0) ? 1 : (n))\r
-\r
-char *\r
-imalloc(n)\r
-const int      n;\r
-{\r
-       return malloc((size_t) nonzero(n));\r
-}\r
-\r
-char *\r
-icalloc(nelem, elsize)\r
-int    nelem;\r
-int    elsize;\r
-{\r
-       if (nelem == 0 || elsize == 0)\r
-               nelem = elsize = 1;\r
-       return calloc((size_t) nelem, (size_t) elsize);\r
-}\r
-\r
-void *\r
-irealloc(pointer, size)\r
-void * const   pointer;\r
-const int      size;\r
-{\r
-       if (pointer == NULL)\r
-               return imalloc(size);\r
-       return realloc((void *) pointer, (size_t) nonzero(size));\r
-}\r
-\r
-char *\r
-icatalloc(old, new)\r
-char * const           old;\r
-const char * const     new;\r
-{\r
-       register char * result;\r
-       register int    oldsize, newsize;\r
-\r
-       newsize = (new == NULL) ? 0 : strlen(new);\r
-       if (old == NULL)\r
-               oldsize = 0;\r
-       else if (newsize == 0)\r
-               return old;\r
-       else    oldsize = strlen(old);\r
-       if ((result = irealloc(old, oldsize + newsize + 1)) != NULL)\r
-               if (new != NULL)\r
-                       (void) strcpy(result + oldsize, new);\r
-       return result;\r
-}\r
-\r
-char *\r
-icpyalloc(string)\r
-const char * const     string;\r
-{\r
-       return icatalloc((char *) NULL, string);\r
-}\r
-\r
-void\r
-ifree(p)\r
-char * const   p;\r
-{\r
-       if (p != NULL)\r
-               (void) free(p);\r
-}\r
-\r
-void\r
-icfree(p)\r
-char * const   p;\r
-{\r
-       if (p != NULL)\r
-               (void) free(p);\r
-}\r
+#ifndef lint
+#ifndef NOID
+static char    elsieid[] = "@(#)ialloc.c       8.29";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+
+#define nonzero(n)     (((n) == 0) ? 1 : (n))
+
+char *
+imalloc(n)
+const int      n;
+{
+       return malloc((size_t) nonzero(n));
+}
+
+char *
+icalloc(nelem, elsize)
+int    nelem;
+int    elsize;
+{
+       if (nelem == 0 || elsize == 0)
+               nelem = elsize = 1;
+       return calloc((size_t) nelem, (size_t) elsize);
+}
+
+void *
+irealloc(pointer, size)
+void * const   pointer;
+const int      size;
+{
+       if (pointer == NULL)
+               return imalloc(size);
+       return realloc((void *) pointer, (size_t) nonzero(size));
+}
+
+char *
+icatalloc(old, new)
+char * const           old;
+const char * const     new;
+{
+       register char * result;
+       register int    oldsize, newsize;
+
+       newsize = (new == NULL) ? 0 : strlen(new);
+       if (old == NULL)
+               oldsize = 0;
+       else if (newsize == 0)
+               return old;
+       else    oldsize = strlen(old);
+       if ((result = irealloc(old, oldsize + newsize + 1)) != NULL)
+               if (new != NULL)
+                       (void) strcpy(result + oldsize, new);
+       return result;
+}
+
+char *
+icpyalloc(string)
+const char * const     string;
+{
+       return icatalloc((char *) NULL, string);
+}
+
+void
+ifree(p)
+char * const   p;
+{
+       if (p != NULL)
+               (void) free(p);
+}
+
+void
+icfree(p)
+char * const   p;
+{
+       if (p != NULL)
+               (void) free(p);
+}
index 4f389b52dee13dff7bc433058417a29637902403..6936cd674be050bf0cd32a317f0847230c86e9b4 100644 (file)
-#include "pgtz.h"\r
-#undef open\r
-#define timezone pg_timezone\r
-#define USG_COMPAT\r
-extern time_t pg_timezone;\r
-/*\r
-** This file is in the public domain, so clarified as of\r
-** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).\r
-*/\r
-\r
-#ifndef lint\r
-#ifndef NOID\r
-static char    elsieid[] = "@(#)localtime.c    7.78";\r
-#endif /* !defined NOID */\r
-#endif /* !defined lint */\r
-\r
-/*\r
-** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).\r
-** POSIX-style TZ environment variable handling from Guy Harris\r
-** (guy@auspex.com).\r
-*/\r
-\r
-/*LINTLIBRARY*/\r
-\r
-#include "private.h"\r
-#include "tzfile.h"\r
-#include "fcntl.h"\r
-\r
-/*\r
-** SunOS 4.1.1 headers lack O_BINARY.\r
-*/\r
-\r
-#ifdef O_BINARY\r
-#define OPEN_MODE      (O_RDONLY | O_BINARY)\r
-#endif /* defined O_BINARY */\r
-#ifndef O_BINARY\r
-#define OPEN_MODE      O_RDONLY\r
-#endif /* !defined O_BINARY */\r
-\r
-#ifndef WILDABBR\r
-/*\r
-** Someone might make incorrect use of a time zone abbreviation:\r
-**     1.      They might reference tzname[0] before calling tzset (explicitly\r
-**             or implicitly).\r
-**     2.      They might reference tzname[1] before calling tzset (explicitly\r
-**             or implicitly).\r
-**     3.      They might reference tzname[1] after setting to a time zone\r
-**             in which Daylight Saving Time is never observed.\r
-**     4.      They might reference tzname[0] after setting to a time zone\r
-**             in which Standard Time is never observed.\r
-**     5.      They might reference tm.TM_ZONE after calling offtime.\r
-** What's best to do in the above cases is open to debate;\r
-** for now, we just set things up so that in any of the five cases\r
-** WILDABBR is used.  Another possibility:  initialize tzname[0] to the\r
-** string "tzname[0] used before set", and similarly for the other cases.\r
-** And another:  initialize tzname[0] to "ERA", with an explanation in the\r
-** manual page of what this "time zone abbreviation" means (doing this so\r
-** that tzname[0] has the "normal" length of three characters).\r
-*/\r
-#define WILDABBR       "   "\r
-#endif /* !defined WILDABBR */\r
-\r
-static char            wildabbr[] = "WILDABBR";\r
-\r
-static const char      gmt[] = "GMT";\r
-\r
-/*\r
-** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.\r
-** We default to US rules as of 1999-08-17.\r
-** POSIX 1003.1 section 8.1.1 says that the default DST rules are\r
-** implementation dependent; for historical reasons, US rules are a\r
-** common default.\r
-*/\r
-#ifndef TZDEFRULESTRING\r
-#define TZDEFRULESTRING ",M4.1.0,M10.5.0"\r
-#endif /* !defined TZDEFDST */\r
-\r
-struct ttinfo {                                /* time type information */\r
-       long            tt_gmtoff;      /* UTC offset in seconds */\r
-       int             tt_isdst;       /* used to set tm_isdst */\r
-       int             tt_abbrind;     /* abbreviation list index */\r
-       int             tt_ttisstd;     /* TRUE if transition is std time */\r
-       int             tt_ttisgmt;     /* TRUE if transition is UTC */\r
-};\r
-\r
-struct lsinfo {                                /* leap second information */\r
-       time_t          ls_trans;       /* transition time */\r
-       long            ls_corr;        /* correction to apply */\r
-};\r
-\r
-#define BIGGEST(a, b)  (((a) > (b)) ? (a) : (b))\r
-\r
-#ifdef TZNAME_MAX\r
-#define MY_TZNAME_MAX  TZNAME_MAX\r
-#endif /* defined TZNAME_MAX */\r
-#ifndef TZNAME_MAX\r
-#define MY_TZNAME_MAX  255\r
-#endif /* !defined TZNAME_MAX */\r
-\r
-struct state {\r
-       int             leapcnt;\r
-       int             timecnt;\r
-       int             typecnt;\r
-       int             charcnt;\r
-       time_t          ats[TZ_MAX_TIMES];\r
-       unsigned char   types[TZ_MAX_TIMES];\r
-       struct ttinfo   ttis[TZ_MAX_TYPES];\r
-       char            chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),\r
-                               (2 * (MY_TZNAME_MAX + 1)))];\r
-       struct lsinfo   lsis[TZ_MAX_LEAPS];\r
-};\r
-\r
-struct rule {\r
-       int             r_type;         /* type of rule--see below */\r
-       int             r_day;          /* day number of rule */\r
-       int             r_week;         /* week number of rule */\r
-       int             r_mon;          /* month number of rule */\r
-       long            r_time;         /* transition time of rule */\r
-};\r
-\r
-#define JULIAN_DAY             0       /* Jn - Julian day */\r
-#define DAY_OF_YEAR            1       /* n - day of year */\r
-#define MONTH_NTH_DAY_OF_WEEK  2       /* Mm.n.d - month, week, day of week */\r
-\r
-/*\r
-** Prototypes for static functions.\r
-*/\r
-\r
-static long            detzcode P((const char * codep));\r
-static const char *    getzname P((const char * strp));\r
-static const char *    getnum P((const char * strp, int * nump, int min,\r
-                               int max));\r
-static const char *    getsecs P((const char * strp, long * secsp));\r
-static const char *    getoffset P((const char * strp, long * offsetp));\r
-static const char *    getrule P((const char * strp, struct rule * rulep));\r
-static void            gmtload P((struct state * sp));\r
-static void            gmtsub P((const time_t * timep, long offset,\r
-                               struct tm * tmp));\r
-static void            localsub P((const time_t * timep, long offset,\r
-                               struct tm * tmp));\r
-static int             increment_overflow P((int * number, int delta));\r
-static int             normalize_overflow P((int * tensptr, int * unitsptr,\r
-                               int base));\r
-static void            settzname P((void));\r
-static time_t          time1 P((struct tm * tmp,\r
-                               void(*funcp) P((const time_t *,\r
-                               long, struct tm *)),\r
-                               long offset));\r
-static time_t          time2 P((struct tm *tmp,\r
-                               void(*funcp) P((const time_t *,\r
-                               long, struct tm*)),\r
-                               long offset, int * okayp));\r
-static time_t          time2sub P((struct tm *tmp,\r
-                               void(*funcp) P((const time_t *,\r
-                               long, struct tm*)),\r
-                               long offset, int * okayp, int do_norm_secs));\r
-static void            timesub P((const time_t * timep, long offset,\r
-                               const struct state * sp, struct tm * tmp));\r
-static int             tmcomp P((const struct tm * atmp,\r
-                               const struct tm * btmp));\r
-static time_t          transtime P((time_t janfirst, int year,\r
-                               const struct rule * rulep, long offset));\r
-static int             tzload P((const char * name, struct state * sp));\r
-static int             tzparse P((const char * name, struct state * sp,\r
-                               int lastditch));\r
-\r
-#ifdef ALL_STATE\r
-static struct state *  lclptr;\r
-static struct state *  gmtptr;\r
-#endif /* defined ALL_STATE */\r
-\r
-#ifndef ALL_STATE\r
-static struct state    lclmem;\r
-static struct state    gmtmem;\r
-#define lclptr         (&lclmem)\r
-#define gmtptr         (&gmtmem)\r
-#endif /* State Farm */\r
-\r
-#ifndef TZ_STRLEN_MAX\r
-#define TZ_STRLEN_MAX 255\r
-#endif /* !defined TZ_STRLEN_MAX */\r
-\r
-static char            lcl_TZname[TZ_STRLEN_MAX + 1];\r
-static int             lcl_is_set;\r
-static int             gmt_is_set;\r
-\r
-char *                 tzname[2] = {\r
-       wildabbr,\r
-       wildabbr\r
-};\r
-\r
-/*\r
-** Section 4.12.3 of X3.159-1989 requires that\r
-**     Except for the strftime function, these functions [asctime,\r
-**     ctime, gmtime, localtime] return values in one of two static\r
-**     objects: a broken-down time structure and an array of char.\r
-** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.\r
-*/\r
-\r
-static struct tm       tm;\r
-\r
-#ifdef USG_COMPAT\r
-time_t                 timezone = 0;\r
-int                    daylight = 0;\r
-#endif /* defined USG_COMPAT */\r
-\r
-#ifdef ALTZONE\r
-time_t                 altzone = 0;\r
-#endif /* defined ALTZONE */\r
-\r
-static long\r
-detzcode(codep)\r
-const char * const     codep;\r
-{\r
-       register long   result;\r
-       register int    i;\r
-\r
-       result = (codep[0] & 0x80) ? ~0L : 0L;\r
-       for (i = 0; i < 4; ++i)\r
-               result = (result << 8) | (codep[i] & 0xff);\r
-       return result;\r
-}\r
-\r
-static void\r
-settzname P((void))\r
-{\r
-       register struct state * const   sp = lclptr;\r
-       register int                    i;\r
-\r
-       tzname[0] = wildabbr;\r
-       tzname[1] = wildabbr;\r
-#ifdef USG_COMPAT\r
-       daylight = 0;\r
-       timezone = 0;\r
-#endif /* defined USG_COMPAT */\r
-#ifdef ALTZONE\r
-       altzone = 0;\r
-#endif /* defined ALTZONE */\r
-#ifdef ALL_STATE\r
-       if (sp == NULL) {\r
-               tzname[0] = tzname[1] = gmt;\r
-               return;\r
-       }\r
-#endif /* defined ALL_STATE */\r
-       for (i = 0; i < sp->typecnt; ++i) {\r
-               register const struct ttinfo * const    ttisp = &sp->ttis[i];\r
-\r
-               tzname[ttisp->tt_isdst] =\r
-                       &sp->chars[ttisp->tt_abbrind];\r
-#ifdef USG_COMPAT\r
-               if (ttisp->tt_isdst)\r
-                       daylight = 1;\r
-               if (i == 0 || !ttisp->tt_isdst)\r
-                       timezone = -(ttisp->tt_gmtoff);\r
-#endif /* defined USG_COMPAT */\r
-#ifdef ALTZONE\r
-               if (i == 0 || ttisp->tt_isdst)\r
-                       altzone = -(ttisp->tt_gmtoff);\r
-#endif /* defined ALTZONE */\r
-       }\r
-       /*\r
-       ** And to get the latest zone names into tzname. . .\r
-       */\r
-       for (i = 0; i < sp->timecnt; ++i) {\r
-               register const struct ttinfo * const    ttisp =\r
-                                                       &sp->ttis[\r
-                                                               sp->types[i]];\r
-\r
-               tzname[ttisp->tt_isdst] =\r
-                       &sp->chars[ttisp->tt_abbrind];\r
-       }\r
-}\r
-\r
-static int\r
-tzload(name, sp)\r
-register const char *          name;\r
-register struct state * const  sp;\r
-{\r
-       register const char *   p;\r
-       register int            i;\r
-       register int            fid;\r
-\r
-       if (name == NULL && (name = TZDEFAULT) == NULL)\r
-               return -1;\r
-       {\r
-               register int    doaccess;\r
-               /*\r
-               ** Section 4.9.1 of the C standard says that\r
-               ** "FILENAME_MAX expands to an integral constant expression\r
-               ** that is the size needed for an array of char large enough\r
-               ** to hold the longest file name string that the implementation\r
-               ** guarantees can be opened."\r
-               */\r
-               char            fullname[FILENAME_MAX + 1];\r
-\r
-               if (name[0] == ':')\r
-                       ++name;\r
-               doaccess = name[0] == '/';\r
-               if (!doaccess) {\r
-                       if ((p = TZDIR) == NULL)\r
-                               return -1;\r
-                       if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)\r
-                               return -1;\r
-                       (void) strcpy(fullname, p);\r
-                       (void) strcat(fullname, "/");\r
-                       (void) strcat(fullname, name);\r
-                       /*\r
-                       ** Set doaccess if '.' (as in "../") shows up in name.\r
-                       */\r
-                       if (strchr(name, '.') != NULL)\r
-                               doaccess = TRUE;\r
-                       name = fullname;\r
-               }\r
-               if (doaccess && access(name, R_OK) != 0)\r
-                       return -1;\r
-               if ((fid = open(name, OPEN_MODE)) == -1)\r
-                       return -1;\r
-       }\r
-       {\r
-               struct tzhead * tzhp;\r
-               union {\r
-                       struct tzhead   tzhead;\r
-                       char            buf[sizeof *sp + sizeof *tzhp];\r
-               } u;\r
-               int             ttisstdcnt;\r
-               int             ttisgmtcnt;\r
-\r
-               i = read(fid, u.buf, sizeof u.buf);\r
-               if (close(fid) != 0)\r
-                       return -1;\r
-               ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);\r
-               ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);\r
-               sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);\r
-               sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);\r
-               sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);\r
-               sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);\r
-               p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;\r
-               if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||\r
-                       sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||\r
-                       sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||\r
-                       sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||\r
-                       (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||\r
-                       (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))\r
-                               return -1;\r
-               if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */\r
-                       sp->timecnt +                   /* types */\r
-                       sp->typecnt * (4 + 2) +         /* ttinfos */\r
-                       sp->charcnt +                   /* chars */\r
-                       sp->leapcnt * (4 + 4) +         /* lsinfos */\r
-                       ttisstdcnt +                    /* ttisstds */\r
-                       ttisgmtcnt)                     /* ttisgmts */\r
-                               return -1;\r
-               for (i = 0; i < sp->timecnt; ++i) {\r
-                       sp->ats[i] = detzcode(p);\r
-                       p += 4;\r
-               }\r
-               for (i = 0; i < sp->timecnt; ++i) {\r
-                       sp->types[i] = (unsigned char) *p++;\r
-                       if (sp->types[i] >= sp->typecnt)\r
-                               return -1;\r
-               }\r
-               for (i = 0; i < sp->typecnt; ++i) {\r
-                       register struct ttinfo *        ttisp;\r
-\r
-                       ttisp = &sp->ttis[i];\r
-                       ttisp->tt_gmtoff = detzcode(p);\r
-                       p += 4;\r
-                       ttisp->tt_isdst = (unsigned char) *p++;\r
-                       if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)\r
-                               return -1;\r
-                       ttisp->tt_abbrind = (unsigned char) *p++;\r
-                       if (ttisp->tt_abbrind < 0 ||\r
-                               ttisp->tt_abbrind > sp->charcnt)\r
-                                       return -1;\r
-               }\r
-               for (i = 0; i < sp->charcnt; ++i)\r
-                       sp->chars[i] = *p++;\r
-               sp->chars[i] = '\0';    /* ensure '\0' at end */\r
-               for (i = 0; i < sp->leapcnt; ++i) {\r
-                       register struct lsinfo *        lsisp;\r
-\r
-                       lsisp = &sp->lsis[i];\r
-                       lsisp->ls_trans = detzcode(p);\r
-                       p += 4;\r
-                       lsisp->ls_corr = detzcode(p);\r
-                       p += 4;\r
-               }\r
-               for (i = 0; i < sp->typecnt; ++i) {\r
-                       register struct ttinfo *        ttisp;\r
-\r
-                       ttisp = &sp->ttis[i];\r
-                       if (ttisstdcnt == 0)\r
-                               ttisp->tt_ttisstd = FALSE;\r
-                       else {\r
-                               ttisp->tt_ttisstd = *p++;\r
-                               if (ttisp->tt_ttisstd != TRUE &&\r
-                                       ttisp->tt_ttisstd != FALSE)\r
-                                               return -1;\r
-                       }\r
-               }\r
-               for (i = 0; i < sp->typecnt; ++i) {\r
-                       register struct ttinfo *        ttisp;\r
-\r
-                       ttisp = &sp->ttis[i];\r
-                       if (ttisgmtcnt == 0)\r
-                               ttisp->tt_ttisgmt = FALSE;\r
-                       else {\r
-                               ttisp->tt_ttisgmt = *p++;\r
-                               if (ttisp->tt_ttisgmt != TRUE &&\r
-                                       ttisp->tt_ttisgmt != FALSE)\r
-                                               return -1;\r
-                       }\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-\r
-static const int       mon_lengths[2][MONSPERYEAR] = {\r
-       { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },\r
-       { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }\r
-};\r
-\r
-static const int       year_lengths[2] = {\r
-       DAYSPERNYEAR, DAYSPERLYEAR\r
-};\r
-\r
-/*\r
-** Given a pointer into a time zone string, scan until a character that is not\r
-** a valid character in a zone name is found.  Return a pointer to that\r
-** character.\r
-*/\r
-\r
-static const char *\r
-getzname(strp)\r
-register const char *  strp;\r
-{\r
-       register char   c;\r
-\r
-       while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&\r
-               c != '+')\r
-                       ++strp;\r
-       return strp;\r
-}\r
-\r
-/*\r
-** Given a pointer into a time zone string, extract a number from that string.\r
-** Check that the number is within a specified range; if it is not, return\r
-** NULL.\r
-** Otherwise, return a pointer to the first character not part of the number.\r
-*/\r
-\r
-static const char *\r
-getnum(strp, nump, min, max)\r
-register const char *  strp;\r
-int * const            nump;\r
-const int              min;\r
-const int              max;\r
-{\r
-       register char   c;\r
-       register int    num;\r
-\r
-       if (strp == NULL || !is_digit(c = *strp))\r
-               return NULL;\r
-       num = 0;\r
-       do {\r
-               num = num * 10 + (c - '0');\r
-               if (num > max)\r
-                       return NULL;    /* illegal value */\r
-               c = *++strp;\r
-       } while (is_digit(c));\r
-       if (num < min)\r
-               return NULL;            /* illegal value */\r
-       *nump = num;\r
-       return strp;\r
-}\r
-\r
-/*\r
-** Given a pointer into a time zone string, extract a number of seconds,\r
-** in hh[:mm[:ss]] form, from the string.\r
-** If any error occurs, return NULL.\r
-** Otherwise, return a pointer to the first character not part of the number\r
-** of seconds.\r
-*/\r
-\r
-static const char *\r
-getsecs(strp, secsp)\r
-register const char *  strp;\r
-long * const           secsp;\r
-{\r
-       int     num;\r
-\r
-       /*\r
-       ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like\r
-       ** "M10.4.6/26", which does not conform to Posix,\r
-       ** but which specifies the equivalent of\r
-       ** ``02:00 on the first Sunday on or after 23 Oct''.\r
-       */\r
-       strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);\r
-       if (strp == NULL)\r
-               return NULL;\r
-       *secsp = num * (long) SECSPERHOUR;\r
-       if (*strp == ':') {\r
-               ++strp;\r
-               strp = getnum(strp, &num, 0, MINSPERHOUR - 1);\r
-               if (strp == NULL)\r
-                       return NULL;\r
-               *secsp += num * SECSPERMIN;\r
-               if (*strp == ':') {\r
-                       ++strp;\r
-                       /* `SECSPERMIN' allows for leap seconds.  */\r
-                       strp = getnum(strp, &num, 0, SECSPERMIN);\r
-                       if (strp == NULL)\r
-                               return NULL;\r
-                       *secsp += num;\r
-               }\r
-       }\r
-       return strp;\r
-}\r
-\r
-/*\r
-** Given a pointer into a time zone string, extract an offset, in\r
-** [+-]hh[:mm[:ss]] form, from the string.\r
-** If any error occurs, return NULL.\r
-** Otherwise, return a pointer to the first character not part of the time.\r
-*/\r
-\r
-static const char *\r
-getoffset(strp, offsetp)\r
-register const char *  strp;\r
-long * const           offsetp;\r
-{\r
-       register int    neg = 0;\r
-\r
-       if (*strp == '-') {\r
-               neg = 1;\r
-               ++strp;\r
-       } else if (*strp == '+')\r
-               ++strp;\r
-       strp = getsecs(strp, offsetp);\r
-       if (strp == NULL)\r
-               return NULL;            /* illegal time */\r
-       if (neg)\r
-               *offsetp = -*offsetp;\r
-       return strp;\r
-}\r
-\r
-/*\r
-** Given a pointer into a time zone string, extract a rule in the form\r
-** date[/time].  See POSIX section 8 for the format of "date" and "time".\r
-** If a valid rule is not found, return NULL.\r
-** Otherwise, return a pointer to the first character not part of the rule.\r
-*/\r
-\r
-static const char *\r
-getrule(strp, rulep)\r
-const char *                   strp;\r
-register struct rule * const   rulep;\r
-{\r
-       if (*strp == 'J') {\r
-               /*\r
-               ** Julian day.\r
-               */\r
-               rulep->r_type = JULIAN_DAY;\r
-               ++strp;\r
-               strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);\r
-       } else if (*strp == 'M') {\r
-               /*\r
-               ** Month, week, day.\r
-               */\r
-               rulep->r_type = MONTH_NTH_DAY_OF_WEEK;\r
-               ++strp;\r
-               strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);\r
-               if (strp == NULL)\r
-                       return NULL;\r
-               if (*strp++ != '.')\r
-                       return NULL;\r
-               strp = getnum(strp, &rulep->r_week, 1, 5);\r
-               if (strp == NULL)\r
-                       return NULL;\r
-               if (*strp++ != '.')\r
-                       return NULL;\r
-               strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);\r
-       } else if (is_digit(*strp)) {\r
-               /*\r
-               ** Day of year.\r
-               */\r
-               rulep->r_type = DAY_OF_YEAR;\r
-               strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);\r
-       } else  return NULL;            /* invalid format */\r
-       if (strp == NULL)\r
-               return NULL;\r
-       if (*strp == '/') {\r
-               /*\r
-               ** Time specified.\r
-               */\r
-               ++strp;\r
-               strp = getsecs(strp, &rulep->r_time);\r
-       } else  rulep->r_time = 2 * SECSPERHOUR;        /* default = 2:00:00 */\r
-       return strp;\r
-}\r
-\r
-/*\r
-** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the\r
-** year, a rule, and the offset from UTC at the time that rule takes effect,\r
-** calculate the Epoch-relative time that rule takes effect.\r
-*/\r
-\r
-static time_t\r
-transtime(janfirst, year, rulep, offset)\r
-const time_t                           janfirst;\r
-const int                              year;\r
-register const struct rule * const     rulep;\r
-const long                             offset;\r
-{\r
-       register int    leapyear;\r
-       register time_t value;\r
-       register int    i;\r
-       int             d, m1, yy0, yy1, yy2, dow;\r
-\r
-       INITIALIZE(value);\r
-       leapyear = isleap(year);\r
-       switch (rulep->r_type) {\r
-\r
-       case JULIAN_DAY:\r
-               /*\r
-               ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap\r
-               ** years.\r
-               ** In non-leap years, or if the day number is 59 or less, just\r
-               ** add SECSPERDAY times the day number-1 to the time of\r
-               ** January 1, midnight, to get the day.\r
-               */\r
-               value = janfirst + (rulep->r_day - 1) * SECSPERDAY;\r
-               if (leapyear && rulep->r_day >= 60)\r
-                       value += SECSPERDAY;\r
-               break;\r
-\r
-       case DAY_OF_YEAR:\r
-               /*\r
-               ** n - day of year.\r
-               ** Just add SECSPERDAY times the day number to the time of\r
-               ** January 1, midnight, to get the day.\r
-               */\r
-               value = janfirst + rulep->r_day * SECSPERDAY;\r
-               break;\r
-\r
-       case MONTH_NTH_DAY_OF_WEEK:\r
-               /*\r
-               ** Mm.n.d - nth "dth day" of month m.\r
-               */\r
-               value = janfirst;\r
-               for (i = 0; i < rulep->r_mon - 1; ++i)\r
-                       value += mon_lengths[leapyear][i] * SECSPERDAY;\r
-\r
-               /*\r
-               ** Use Zeller's Congruence to get day-of-week of first day of\r
-               ** month.\r
-               */\r
-               m1 = (rulep->r_mon + 9) % 12 + 1;\r
-               yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;\r
-               yy1 = yy0 / 100;\r
-               yy2 = yy0 % 100;\r
-               dow = ((26 * m1 - 2) / 10 +\r
-                       1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;\r
-               if (dow < 0)\r
-                       dow += DAYSPERWEEK;\r
-\r
-               /*\r
-               ** "dow" is the day-of-week of the first day of the month.  Get\r
-               ** the day-of-month (zero-origin) of the first "dow" day of the\r
-               ** month.\r
-               */\r
-               d = rulep->r_day - dow;\r
-               if (d < 0)\r
-                       d += DAYSPERWEEK;\r
-               for (i = 1; i < rulep->r_week; ++i) {\r
-                       if (d + DAYSPERWEEK >=\r
-                               mon_lengths[leapyear][rulep->r_mon - 1])\r
-                                       break;\r
-                       d += DAYSPERWEEK;\r
-               }\r
-\r
-               /*\r
-               ** "d" is the day-of-month (zero-origin) of the day we want.\r
-               */\r
-               value += d * SECSPERDAY;\r
-               break;\r
-       }\r
-\r
-       /*\r
-       ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in\r
-       ** question.  To get the Epoch-relative time of the specified local\r
-       ** time on that day, add the transition time and the current offset\r
-       ** from UTC.\r
-       */\r
-       return value + rulep->r_time + offset;\r
-}\r
-\r
-/*\r
-** Given a POSIX section 8-style TZ string, fill in the rule tables as\r
-** appropriate.\r
-*/\r
-\r
-static int\r
-tzparse(name, sp, lastditch)\r
-const char *                   name;\r
-register struct state * const  sp;\r
-const int                      lastditch;\r
-{\r
-       const char *                    stdname;\r
-       const char *                    dstname;\r
-       size_t                          stdlen;\r
-       size_t                          dstlen;\r
-       long                            stdoffset;\r
-       long                            dstoffset;\r
-       register time_t *               atp;\r
-       register unsigned char *        typep;\r
-       register char *                 cp;\r
-       register int                    load_result;\r
-\r
-       INITIALIZE(dstname);\r
-       stdname = name;\r
-       if (lastditch) {\r
-               stdlen = strlen(name);  /* length of standard zone name */\r
-               name += stdlen;\r
-               if (stdlen >= sizeof sp->chars)\r
-                       stdlen = (sizeof sp->chars) - 1;\r
-               stdoffset = 0;\r
-       } else {\r
-               name = getzname(name);\r
-               stdlen = name - stdname;\r
-               if (stdlen < 3)\r
-                       return -1;\r
-               if (*name == '\0')\r
-                       return -1;\r
-               name = getoffset(name, &stdoffset);\r
-               if (name == NULL)\r
-                       return -1;\r
-       }\r
-       load_result = tzload(TZDEFRULES, sp);\r
-       if (load_result != 0)\r
-               sp->leapcnt = 0;                /* so, we're off a little */\r
-       if (*name != '\0') {\r
-               dstname = name;\r
-               name = getzname(name);\r
-               dstlen = name - dstname;        /* length of DST zone name */\r
-               if (dstlen < 3)\r
-                       return -1;\r
-               if (*name != '\0' && *name != ',' && *name != ';') {\r
-                       name = getoffset(name, &dstoffset);\r
-                       if (name == NULL)\r
-                               return -1;\r
-               } else  dstoffset = stdoffset - SECSPERHOUR;\r
-               if (*name == '\0' && load_result != 0)\r
-                       name = TZDEFRULESTRING;\r
-               if (*name == ',' || *name == ';') {\r
-                       struct rule     start;\r
-                       struct rule     end;\r
-                       register int    year;\r
-                       register time_t janfirst;\r
-                       time_t          starttime;\r
-                       time_t          endtime;\r
-\r
-                       ++name;\r
-                       if ((name = getrule(name, &start)) == NULL)\r
-                               return -1;\r
-                       if (*name++ != ',')\r
-                               return -1;\r
-                       if ((name = getrule(name, &end)) == NULL)\r
-                               return -1;\r
-                       if (*name != '\0')\r
-                               return -1;\r
-                       sp->typecnt = 2;        /* standard time and DST */\r
-                       /*\r
-                       ** Two transitions per year, from EPOCH_YEAR to 2037.\r
-                       */\r
-                       sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);\r
-                       if (sp->timecnt > TZ_MAX_TIMES)\r
-                               return -1;\r
-                       sp->ttis[0].tt_gmtoff = -dstoffset;\r
-                       sp->ttis[0].tt_isdst = 1;\r
-                       sp->ttis[0].tt_abbrind = stdlen + 1;\r
-                       sp->ttis[1].tt_gmtoff = -stdoffset;\r
-                       sp->ttis[1].tt_isdst = 0;\r
-                       sp->ttis[1].tt_abbrind = 0;\r
-                       atp = sp->ats;\r
-                       typep = sp->types;\r
-                       janfirst = 0;\r
-                       for (year = EPOCH_YEAR; year <= 2037; ++year) {\r
-                               starttime = transtime(janfirst, year, &start,\r
-                                       stdoffset);\r
-                               endtime = transtime(janfirst, year, &end,\r
-                                       dstoffset);\r
-                               if (starttime > endtime) {\r
-                                       *atp++ = endtime;\r
-                                       *typep++ = 1;   /* DST ends */\r
-                                       *atp++ = starttime;\r
-                                       *typep++ = 0;   /* DST begins */\r
-                               } else {\r
-                                       *atp++ = starttime;\r
-                                       *typep++ = 0;   /* DST begins */\r
-                                       *atp++ = endtime;\r
-                                       *typep++ = 1;   /* DST ends */\r
-                               }\r
-                               janfirst += year_lengths[isleap(year)] *\r
-                                       SECSPERDAY;\r
-                       }\r
-               } else {\r
-                       register long   theirstdoffset;\r
-                       register long   theirdstoffset;\r
-                       register long   theiroffset;\r
-                       register int    isdst;\r
-                       register int    i;\r
-                       register int    j;\r
-\r
-                       if (*name != '\0')\r
-                               return -1;\r
-                       /*\r
-                       ** Initial values of theirstdoffset and theirdstoffset.\r
-                       */\r
-                       theirstdoffset = 0;\r
-                       for (i = 0; i < sp->timecnt; ++i) {\r
-                               j = sp->types[i];\r
-                               if (!sp->ttis[j].tt_isdst) {\r
-                                       theirstdoffset =\r
-                                               -sp->ttis[j].tt_gmtoff;\r
-                                       break;\r
-                               }\r
-                       }\r
-                       theirdstoffset = 0;\r
-                       for (i = 0; i < sp->timecnt; ++i) {\r
-                               j = sp->types[i];\r
-                               if (sp->ttis[j].tt_isdst) {\r
-                                       theirdstoffset =\r
-                                               -sp->ttis[j].tt_gmtoff;\r
-                                       break;\r
-                               }\r
-                       }\r
-                       /*\r
-                       ** Initially we're assumed to be in standard time.\r
-                       */\r
-                       isdst = FALSE;\r
-                       theiroffset = theirstdoffset;\r
-                       /*\r
-                       ** Now juggle transition times and types\r
-                       ** tracking offsets as you do.\r
-                       */\r
-                       for (i = 0; i < sp->timecnt; ++i) {\r
-                               j = sp->types[i];\r
-                               sp->types[i] = sp->ttis[j].tt_isdst;\r
-                               if (sp->ttis[j].tt_ttisgmt) {\r
-                                       /* No adjustment to transition time */\r
-                               } else {\r
-                                       /*\r
-                                       ** If summer time is in effect, and the\r
-                                       ** transition time was not specified as\r
-                                       ** standard time, add the summer time\r
-                                       ** offset to the transition time;\r
-                                       ** otherwise, add the standard time\r
-                                       ** offset to the transition time.\r
-                                       */\r
-                                       /*\r
-                                       ** Transitions from DST to DDST\r
-                                       ** will effectively disappear since\r
-                                       ** POSIX provides for only one DST\r
-                                       ** offset.\r
-                                       */\r
-                                       if (isdst && !sp->ttis[j].tt_ttisstd) {\r
-                                               sp->ats[i] += dstoffset -\r
-                                                       theirdstoffset;\r
-                                       } else {\r
-                                               sp->ats[i] += stdoffset -\r
-                                                       theirstdoffset;\r
-                                       }\r
-                               }\r
-                               theiroffset = -sp->ttis[j].tt_gmtoff;\r
-                               if (sp->ttis[j].tt_isdst)\r
-                                       theirdstoffset = theiroffset;\r
-                               else    theirstdoffset = theiroffset;\r
-                       }\r
-                       /*\r
-                       ** Finally, fill in ttis.\r
-                       ** ttisstd and ttisgmt need not be handled.\r
-                       */\r
-                       sp->ttis[0].tt_gmtoff = -stdoffset;\r
-                       sp->ttis[0].tt_isdst = FALSE;\r
-                       sp->ttis[0].tt_abbrind = 0;\r
-                       sp->ttis[1].tt_gmtoff = -dstoffset;\r
-                       sp->ttis[1].tt_isdst = TRUE;\r
-                       sp->ttis[1].tt_abbrind = stdlen + 1;\r
-                       sp->typecnt = 2;\r
-               }\r
-       } else {\r
-               dstlen = 0;\r
-               sp->typecnt = 1;                /* only standard time */\r
-               sp->timecnt = 0;\r
-               sp->ttis[0].tt_gmtoff = -stdoffset;\r
-               sp->ttis[0].tt_isdst = 0;\r
-               sp->ttis[0].tt_abbrind = 0;\r
-       }\r
-       sp->charcnt = stdlen + 1;\r
-       if (dstlen != 0)\r
-               sp->charcnt += dstlen + 1;\r
-       if ((size_t) sp->charcnt > sizeof sp->chars)\r
-               return -1;\r
-       cp = sp->chars;\r
-       (void) strncpy(cp, stdname, stdlen);\r
-       cp += stdlen;\r
-       *cp++ = '\0';\r
-       if (dstlen != 0) {\r
-               (void) strncpy(cp, dstname, dstlen);\r
-               *(cp + dstlen) = '\0';\r
-       }\r
-       return 0;\r
-}\r
-\r
-static void\r
-gmtload(sp)\r
-struct state * const   sp;\r
-{\r
-       if (tzload(gmt, sp) != 0)\r
-               (void) tzparse(gmt, sp, TRUE);\r
-}\r
-\r
-#ifndef STD_INSPIRED\r
-/*\r
-** A non-static declaration of tzsetwall in a system header file\r
-** may cause a warning about this upcoming static declaration...\r
-*/\r
-static\r
-#endif /* !defined STD_INSPIRED */\r
-void\r
-tzsetwall P((void))\r
-{\r
-       if (lcl_is_set < 0)\r
-               return;\r
-       lcl_is_set = -1;\r
-\r
-#ifdef ALL_STATE\r
-       if (lclptr == NULL) {\r
-               lclptr = (struct state *) malloc(sizeof *lclptr);\r
-               if (lclptr == NULL) {\r
-                       settzname();    /* all we can do */\r
-                       return;\r
-               }\r
-       }\r
-#endif /* defined ALL_STATE */\r
-       if (tzload((char *) NULL, lclptr) != 0)\r
-               gmtload(lclptr);\r
-       settzname();\r
-}\r
-\r
-void\r
-tzset P((void))\r
-{\r
-       register const char *   name;\r
-\r
-       name = getenv("TZ");\r
-       if (name == NULL) {\r
-               tzsetwall();\r
-               return;\r
-       }\r
-\r
-       if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)\r
-               return;\r
-       lcl_is_set = strlen(name) < sizeof lcl_TZname;\r
-       if (lcl_is_set)\r
-               (void) strcpy(lcl_TZname, name);\r
-\r
-#ifdef ALL_STATE\r
-       if (lclptr == NULL) {\r
-               lclptr = (struct state *) malloc(sizeof *lclptr);\r
-               if (lclptr == NULL) {\r
-                       settzname();    /* all we can do */\r
-                       return;\r
-               }\r
-       }\r
-#endif /* defined ALL_STATE */\r
-       if (*name == '\0') {\r
-               /*\r
-               ** User wants it fast rather than right.\r
-               */\r
-               lclptr->leapcnt = 0;            /* so, we're off a little */\r
-               lclptr->timecnt = 0;\r
-               lclptr->typecnt = 0;\r
-               lclptr->ttis[0].tt_isdst = 0;\r
-               lclptr->ttis[0].tt_gmtoff = 0;\r
-               lclptr->ttis[0].tt_abbrind = 0;\r
-               (void) strcpy(lclptr->chars, gmt);\r
-       } else if (tzload(name, lclptr) != 0)\r
-               if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)\r
-                       (void) gmtload(lclptr);\r
-       settzname();\r
-}\r
-\r
-/*\r
-** The easy way to behave "as if no library function calls" localtime\r
-** is to not call it--so we drop its guts into "localsub", which can be\r
-** freely called.  (And no, the PANS doesn't require the above behavior--\r
-** but it *is* desirable.)\r
-**\r
-** The unused offset argument is for the benefit of mktime variants.\r
-*/\r
-\r
-/*ARGSUSED*/\r
-static void\r
-localsub(timep, offset, tmp)\r
-const time_t * const   timep;\r
-const long             offset;\r
-struct tm * const      tmp;\r
-{\r
-       register struct state *         sp;\r
-       register const struct ttinfo *  ttisp;\r
-       register int                    i;\r
-       const time_t                    t = *timep;\r
-\r
-       sp = lclptr;\r
-#ifdef ALL_STATE\r
-       if (sp == NULL) {\r
-               gmtsub(timep, offset, tmp);\r
-               return;\r
-       }\r
-#endif /* defined ALL_STATE */\r
-       if (sp->timecnt == 0 || t < sp->ats[0]) {\r
-               i = 0;\r
-               while (sp->ttis[i].tt_isdst)\r
-                       if (++i >= sp->typecnt) {\r
-                               i = 0;\r
-                               break;\r
-                       }\r
-       } else {\r
-               for (i = 1; i < sp->timecnt; ++i)\r
-                       if (t < sp->ats[i])\r
-                               break;\r
-               i = sp->types[i - 1];\r
-       }\r
-       ttisp = &sp->ttis[i];\r
-       /*\r
-       ** To get (wrong) behavior that's compatible with System V Release 2.0\r
-       ** you'd replace the statement below with\r
-       **      t += ttisp->tt_gmtoff;\r
-       **      timesub(&t, 0L, sp, tmp);\r
-       */\r
-       timesub(&t, ttisp->tt_gmtoff, sp, tmp);\r
-       tmp->tm_isdst = ttisp->tt_isdst;\r
-       tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];\r
-#ifdef TM_ZONE\r
-       tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];\r
-#endif /* defined TM_ZONE */\r
-}\r
-\r
-struct tm *\r
-localtime(timep)\r
-const time_t * const   timep;\r
-{\r
-       tzset();\r
-       localsub(timep, 0L, &tm);\r
-       return &tm;\r
-}\r
-\r
-/*\r
-** Re-entrant version of localtime.\r
-*/\r
-\r
-struct tm *\r
-localtime_r(timep, tm)\r
-const time_t * const   timep;\r
-struct tm *            tm;\r
-{\r
-       localsub(timep, 0L, tm);\r
-       return tm;\r
-}\r
-\r
-/*\r
-** gmtsub is to gmtime as localsub is to localtime.\r
-*/\r
-\r
-static void\r
-gmtsub(timep, offset, tmp)\r
-const time_t * const   timep;\r
-const long             offset;\r
-struct tm * const      tmp;\r
-{\r
-       if (!gmt_is_set) {\r
-               gmt_is_set = TRUE;\r
-#ifdef ALL_STATE\r
-               gmtptr = (struct state *) malloc(sizeof *gmtptr);\r
-               if (gmtptr != NULL)\r
-#endif /* defined ALL_STATE */\r
-                       gmtload(gmtptr);\r
-       }\r
-       timesub(timep, offset, gmtptr, tmp);\r
-#ifdef TM_ZONE\r
-       /*\r
-       ** Could get fancy here and deliver something such as\r
-       ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,\r
-       ** but this is no time for a treasure hunt.\r
-       */\r
-       if (offset != 0)\r
-               tmp->TM_ZONE = wildabbr;\r
-       else {\r
-#ifdef ALL_STATE\r
-               if (gmtptr == NULL)\r
-                       tmp->TM_ZONE = gmt;\r
-               else    tmp->TM_ZONE = gmtptr->chars;\r
-#endif /* defined ALL_STATE */\r
-#ifndef ALL_STATE\r
-               tmp->TM_ZONE = gmtptr->chars;\r
-#endif /* State Farm */\r
-       }\r
-#endif /* defined TM_ZONE */\r
-}\r
-\r
-struct tm *\r
-gmtime(timep)\r
-const time_t * const   timep;\r
-{\r
-       gmtsub(timep, 0L, &tm);\r
-       return &tm;\r
-}\r
-\r
-/*\r
-* Re-entrant version of gmtime.\r
-*/\r
-\r
-struct tm *\r
-gmtime_r(timep, tm)\r
-const time_t * const   timep;\r
-struct tm *            tm;\r
-{\r
-       gmtsub(timep, 0L, tm);\r
-       return tm;\r
-}\r
-\r
-#ifdef STD_INSPIRED\r
-\r
-struct tm *\r
-offtime(timep, offset)\r
-const time_t * const   timep;\r
-const long             offset;\r
-{\r
-       gmtsub(timep, offset, &tm);\r
-       return &tm;\r
-}\r
-\r
-#endif /* defined STD_INSPIRED */\r
-\r
-static void\r
-timesub(timep, offset, sp, tmp)\r
-const time_t * const                   timep;\r
-const long                             offset;\r
-register const struct state * const    sp;\r
-register struct tm * const             tmp;\r
-{\r
-       register const struct lsinfo *  lp;\r
-       register long                   days;\r
-       register long                   rem;\r
-       register int                    y;\r
-       register int                    yleap;\r
-       register const int *            ip;\r
-       register long                   corr;\r
-       register int                    hit;\r
-       register int                    i;\r
-\r
-       corr = 0;\r
-       hit = 0;\r
-#ifdef ALL_STATE\r
-       i = (sp == NULL) ? 0 : sp->leapcnt;\r
-#endif /* defined ALL_STATE */\r
-#ifndef ALL_STATE\r
-       i = sp->leapcnt;\r
-#endif /* State Farm */\r
-       while (--i >= 0) {\r
-               lp = &sp->lsis[i];\r
-               if (*timep >= lp->ls_trans) {\r
-                       if (*timep == lp->ls_trans) {\r
-                               hit = ((i == 0 && lp->ls_corr > 0) ||\r
-                                       lp->ls_corr > sp->lsis[i - 1].ls_corr);\r
-                               if (hit)\r
-                                       while (i > 0 &&\r
-                                               sp->lsis[i].ls_trans ==\r
-                                               sp->lsis[i - 1].ls_trans + 1 &&\r
-                                               sp->lsis[i].ls_corr ==\r
-                                               sp->lsis[i - 1].ls_corr + 1) {\r
-                                                       ++hit;\r
-                                                       --i;\r
-                                       }\r
-                       }\r
-                       corr = lp->ls_corr;\r
-                       break;\r
-               }\r
-       }\r
-       days = *timep / SECSPERDAY;\r
-       rem = *timep % SECSPERDAY;\r
-#ifdef mc68k\r
-       if (*timep == 0x80000000) {\r
-               /*\r
-               ** A 3B1 muffs the division on the most negative number.\r
-               */\r
-               days = -24855;\r
-               rem = -11648;\r
-       }\r
-#endif /* defined mc68k */\r
-       rem += (offset - corr);\r
-       while (rem < 0) {\r
-               rem += SECSPERDAY;\r
-               --days;\r
-       }\r
-       while (rem >= SECSPERDAY) {\r
-               rem -= SECSPERDAY;\r
-               ++days;\r
-       }\r
-       tmp->tm_hour = (int) (rem / SECSPERHOUR);\r
-       rem = rem % SECSPERHOUR;\r
-       tmp->tm_min = (int) (rem / SECSPERMIN);\r
-       /*\r
-       ** A positive leap second requires a special\r
-       ** representation.  This uses "... ??:59:60" et seq.\r
-       */\r
-       tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;\r
-       tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);\r
-       if (tmp->tm_wday < 0)\r
-               tmp->tm_wday += DAYSPERWEEK;\r
-       y = EPOCH_YEAR;\r
-#define LEAPS_THRU_END_OF(y)   ((y) / 4 - (y) / 100 + (y) / 400)\r
-       while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {\r
-               register int    newy;\r
-\r
-               newy = y + days / DAYSPERNYEAR;\r
-               if (days < 0)\r
-                       --newy;\r
-               days -= (newy - y) * DAYSPERNYEAR +\r
-                       LEAPS_THRU_END_OF(newy - 1) -\r
-                       LEAPS_THRU_END_OF(y - 1);\r
-               y = newy;\r
-       }\r
-       tmp->tm_year = y - TM_YEAR_BASE;\r
-       tmp->tm_yday = (int) days;\r
-       ip = mon_lengths[yleap];\r
-       for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))\r
-               days = days - (long) ip[tmp->tm_mon];\r
-       tmp->tm_mday = (int) (days + 1);\r
-       tmp->tm_isdst = 0;\r
-#ifdef TM_GMTOFF\r
-       tmp->TM_GMTOFF = offset;\r
-#endif /* defined TM_GMTOFF */\r
-}\r
-\r
-char *\r
-ctime(timep)\r
-const time_t * const   timep;\r
-{\r
-/*\r
-** Section 4.12.3.2 of X3.159-1989 requires that\r
-**     The ctime function converts the calendar time pointed to by timer\r
-**     to local time in the form of a string.  It is equivalent to\r
-**             asctime(localtime(timer))\r
-*/\r
-       return asctime(localtime(timep));\r
-}\r
-\r
-char *\r
-ctime_r(timep, buf)\r
-const time_t * const   timep;\r
-char *                 buf;\r
-{\r
-       struct tm       tm;\r
-\r
-       return asctime_r(localtime_r(timep, &tm), buf);\r
-}\r
-\r
-/*\r
-** Adapted from code provided by Robert Elz, who writes:\r
-**     The "best" way to do mktime I think is based on an idea of Bob\r
-**     Kridle's (so its said...) from a long time ago.\r
-**     [kridle@xinet.com as of 1996-01-16.]\r
-**     It does a binary search of the time_t space.  Since time_t's are\r
-**     just 32 bits, its a max of 32 iterations (even at 64 bits it\r
-**     would still be very reasonable).\r
-*/\r
-\r
-#ifndef WRONG\r
-#define WRONG  (-1)\r
-#endif /* !defined WRONG */\r
-\r
-/*\r
-** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).\r
-*/\r
-\r
-static int\r
-increment_overflow(number, delta)\r
-int *  number;\r
-int    delta;\r
-{\r
-       int     number0;\r
-\r
-       number0 = *number;\r
-       *number += delta;\r
-       return (*number < number0) != (delta < 0);\r
-}\r
-\r
-static int\r
-normalize_overflow(tensptr, unitsptr, base)\r
-int * const    tensptr;\r
-int * const    unitsptr;\r
-const int      base;\r
-{\r
-       register int    tensdelta;\r
-\r
-       tensdelta = (*unitsptr >= 0) ?\r
-               (*unitsptr / base) :\r
-               (-1 - (-1 - *unitsptr) / base);\r
-       *unitsptr -= tensdelta * base;\r
-       return increment_overflow(tensptr, tensdelta);\r
-}\r
-\r
-static int\r
-tmcomp(atmp, btmp)\r
-register const struct tm * const atmp;\r
-register const struct tm * const btmp;\r
-{\r
-       register int    result;\r
-\r
-       if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&\r
-               (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&\r
-               (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&\r
-               (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&\r
-               (result = (atmp->tm_min - btmp->tm_min)) == 0)\r
-                       result = atmp->tm_sec - btmp->tm_sec;\r
-       return result;\r
-}\r
-\r
-static time_t\r
-time2sub(tmp, funcp, offset, okayp, do_norm_secs)\r
-struct tm * const      tmp;\r
-void (* const          funcp) P((const time_t*, long, struct tm*));\r
-const long             offset;\r
-int * const            okayp;\r
-const int              do_norm_secs;\r
-{\r
-       register const struct state *   sp;\r
-       register int                    dir;\r
-       register int                    bits;\r
-       register int                    i, j ;\r
-       register int                    saved_seconds;\r
-       time_t                          newt;\r
-       time_t                          t;\r
-       struct tm                       yourtm, mytm;\r
-\r
-       *okayp = FALSE;\r
-       yourtm = *tmp;\r
-       if (do_norm_secs) {\r
-               if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,\r
-                       SECSPERMIN))\r
-                               return WRONG;\r
-       }\r
-       if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))\r
-               return WRONG;\r
-       if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))\r
-               return WRONG;\r
-       if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))\r
-               return WRONG;\r
-       /*\r
-       ** Turn yourtm.tm_year into an actual year number for now.\r
-       ** It is converted back to an offset from TM_YEAR_BASE later.\r
-       */\r
-       if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))\r
-               return WRONG;\r
-       while (yourtm.tm_mday <= 0) {\r
-               if (increment_overflow(&yourtm.tm_year, -1))\r
-                       return WRONG;\r
-               i = yourtm.tm_year + (1 < yourtm.tm_mon);\r
-               yourtm.tm_mday += year_lengths[isleap(i)];\r
-       }\r
-       while (yourtm.tm_mday > DAYSPERLYEAR) {\r
-               i = yourtm.tm_year + (1 < yourtm.tm_mon);\r
-               yourtm.tm_mday -= year_lengths[isleap(i)];\r
-               if (increment_overflow(&yourtm.tm_year, 1))\r
-                       return WRONG;\r
-       }\r
-       for ( ; ; ) {\r
-               i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];\r
-               if (yourtm.tm_mday <= i)\r
-                       break;\r
-               yourtm.tm_mday -= i;\r
-               if (++yourtm.tm_mon >= MONSPERYEAR) {\r
-                       yourtm.tm_mon = 0;\r
-                       if (increment_overflow(&yourtm.tm_year, 1))\r
-                               return WRONG;\r
-               }\r
-       }\r
-       if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))\r
-               return WRONG;\r
-       if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)\r
-               saved_seconds = 0;\r
-       else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {\r
-               /*\r
-               ** We can't set tm_sec to 0, because that might push the\r
-               ** time below the minimum representable time.\r
-               ** Set tm_sec to 59 instead.\r
-               ** This assumes that the minimum representable time is\r
-               ** not in the same minute that a leap second was deleted from,\r
-               ** which is a safer assumption than using 58 would be.\r
-               */\r
-               if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))\r
-                       return WRONG;\r
-               saved_seconds = yourtm.tm_sec;\r
-               yourtm.tm_sec = SECSPERMIN - 1;\r
-       } else {\r
-               saved_seconds = yourtm.tm_sec;\r
-               yourtm.tm_sec = 0;\r
-       }\r
-       /*\r
-       ** Divide the search space in half\r
-       ** (this works whether time_t is signed or unsigned).\r
-       */\r
-       bits = TYPE_BIT(time_t) - 1;\r
-       /*\r
-       ** If time_t is signed, then 0 is just above the median,\r
-       ** assuming two's complement arithmetic.\r
-       ** If time_t is unsigned, then (1 << bits) is just above the median.\r
-       */\r
-       t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);\r
-       for ( ; ; ) {\r
-               (*funcp)(&t, offset, &mytm);\r
-               dir = tmcomp(&mytm, &yourtm);\r
-               if (dir != 0) {\r
-                       if (bits-- < 0)\r
-                               return WRONG;\r
-                       if (bits < 0)\r
-                               --t; /* may be needed if new t is minimal */\r
-                       else if (dir > 0)\r
-                               t -= ((time_t) 1) << bits;\r
-                       else    t += ((time_t) 1) << bits;\r
-                       continue;\r
-               }\r
-               if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)\r
-                       break;\r
-               /*\r
-               ** Right time, wrong type.\r
-               ** Hunt for right time, right type.\r
-               ** It's okay to guess wrong since the guess\r
-               ** gets checked.\r
-               */\r
-               /*\r
-               ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.\r
-               */\r
-               sp = (const struct state *)\r
-                       (((void *) funcp == (void *) localsub) ?\r
-                       lclptr : gmtptr);\r
-#ifdef ALL_STATE\r
-               if (sp == NULL)\r
-                       return WRONG;\r
-#endif /* defined ALL_STATE */\r
-               for (i = sp->typecnt - 1; i >= 0; --i) {\r
-                       if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)\r
-                               continue;\r
-                       for (j = sp->typecnt - 1; j >= 0; --j) {\r
-                               if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)\r
-                                       continue;\r
-                               newt = t + sp->ttis[j].tt_gmtoff -\r
-                                       sp->ttis[i].tt_gmtoff;\r
-                               (*funcp)(&newt, offset, &mytm);\r
-                               if (tmcomp(&mytm, &yourtm) != 0)\r
-                                       continue;\r
-                               if (mytm.tm_isdst != yourtm.tm_isdst)\r
-                                       continue;\r
-                               /*\r
-                               ** We have a match.\r
-                               */\r
-                               t = newt;\r
-                               goto label;\r
-                       }\r
-               }\r
-               return WRONG;\r
-       }\r
-label:\r
-       newt = t + saved_seconds;\r
-       if ((newt < t) != (saved_seconds < 0))\r
-               return WRONG;\r
-       t = newt;\r
-       (*funcp)(&t, offset, tmp);\r
-       *okayp = TRUE;\r
-       return t;\r
-}\r
-\r
-static time_t\r
-time2(tmp, funcp, offset, okayp)\r
-struct tm * const      tmp;\r
-void (* const          funcp) P((const time_t*, long, struct tm*));\r
-const long             offset;\r
-int * const            okayp;\r
-{\r
-       time_t  t;\r
-\r
-       /*\r
-       ** First try without normalization of seconds\r
-       ** (in case tm_sec contains a value associated with a leap second).\r
-       ** If that fails, try with normalization of seconds.\r
-       */\r
-       t = time2sub(tmp, funcp, offset, okayp, FALSE);\r
-       return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);\r
-}\r
-\r
-static time_t\r
-time1(tmp, funcp, offset)\r
-struct tm * const      tmp;\r
-void (* const          funcp) P((const time_t *, long, struct tm *));\r
-const long             offset;\r
-{\r
-       register time_t                 t;\r
-       register const struct state *   sp;\r
-       register int                    samei, otheri;\r
-       register int                    sameind, otherind;\r
-       register int                    i;\r
-       register int                    nseen;\r
-       int                             seen[TZ_MAX_TYPES];\r
-       int                             types[TZ_MAX_TYPES];\r
-       int                             okay;\r
-\r
-       if (tmp->tm_isdst > 1)\r
-               tmp->tm_isdst = 1;\r
-       t = time2(tmp, funcp, offset, &okay);\r
-#ifdef PCTS\r
-       /*\r
-       ** PCTS code courtesy Grant Sullivan (grant@osf.org).\r
-       */\r
-       if (okay)\r
-               return t;\r
-       if (tmp->tm_isdst < 0)\r
-               tmp->tm_isdst = 0;      /* reset to std and try again */\r
-#endif /* defined PCTS */\r
-#ifndef PCTS\r
-       if (okay || tmp->tm_isdst < 0)\r
-               return t;\r
-#endif /* !defined PCTS */\r
-       /*\r
-       ** We're supposed to assume that somebody took a time of one type\r
-       ** and did some math on it that yielded a "struct tm" that's bad.\r
-       ** We try to divine the type they started from and adjust to the\r
-       ** type they need.\r
-       */\r
-       /*\r
-       ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.\r
-       */\r
-       sp = (const struct state *) (((void *) funcp == (void *) localsub) ?\r
-               lclptr : gmtptr);\r
-#ifdef ALL_STATE\r
-       if (sp == NULL)\r
-               return WRONG;\r
-#endif /* defined ALL_STATE */\r
-       for (i = 0; i < sp->typecnt; ++i)\r
-               seen[i] = FALSE;\r
-       nseen = 0;\r
-       for (i = sp->timecnt - 1; i >= 0; --i)\r
-               if (!seen[sp->types[i]]) {\r
-                       seen[sp->types[i]] = TRUE;\r
-                       types[nseen++] = sp->types[i];\r
-               }\r
-       for (sameind = 0; sameind < nseen; ++sameind) {\r
-               samei = types[sameind];\r
-               if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)\r
-                       continue;\r
-               for (otherind = 0; otherind < nseen; ++otherind) {\r
-                       otheri = types[otherind];\r
-                       if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)\r
-                               continue;\r
-                       tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -\r
-                                       sp->ttis[samei].tt_gmtoff;\r
-                       tmp->tm_isdst = !tmp->tm_isdst;\r
-                       t = time2(tmp, funcp, offset, &okay);\r
-                       if (okay)\r
-                               return t;\r
-                       tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -\r
-                                       sp->ttis[samei].tt_gmtoff;\r
-                       tmp->tm_isdst = !tmp->tm_isdst;\r
-               }\r
-       }\r
-       return WRONG;\r
-}\r
-\r
-time_t\r
-mktime(tmp)\r
-struct tm * const      tmp;\r
-{\r
-       tzset();\r
-       return time1(tmp, localsub, 0L);\r
-}\r
-\r
-#ifdef STD_INSPIRED\r
-\r
-time_t\r
-timelocal(tmp)\r
-struct tm * const      tmp;\r
-{\r
-       tmp->tm_isdst = -1;     /* in case it wasn't initialized */\r
-       return mktime(tmp);\r
-}\r
-\r
-time_t\r
-timegm(tmp)\r
-struct tm * const      tmp;\r
-{\r
-       tmp->tm_isdst = 0;\r
-       return time1(tmp, gmtsub, 0L);\r
-}\r
-\r
-time_t\r
-timeoff(tmp, offset)\r
-struct tm * const      tmp;\r
-const long             offset;\r
-{\r
-       tmp->tm_isdst = 0;\r
-       return time1(tmp, gmtsub, offset);\r
-}\r
-\r
-#endif /* defined STD_INSPIRED */\r
-\r
-#ifdef CMUCS\r
-\r
-/*\r
-** The following is supplied for compatibility with\r
-** previous versions of the CMUCS runtime library.\r
-*/\r
-\r
-long\r
-gtime(tmp)\r
-struct tm * const      tmp;\r
-{\r
-       const time_t    t = mktime(tmp);\r
-\r
-       if (t == WRONG)\r
-               return -1;\r
-       return t;\r
-}\r
-\r
-#endif /* defined CMUCS */\r
-\r
-/*\r
-** XXX--is the below the right way to conditionalize??\r
-*/\r
-\r
-#ifdef STD_INSPIRED\r
-\r
-/*\r
-** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599\r
-** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which\r
-** is not the case if we are accounting for leap seconds.\r
-** So, we provide the following conversion routines for use\r
-** when exchanging timestamps with POSIX conforming systems.\r
-*/\r
-\r
-static long\r
-leapcorr(timep)\r
-time_t *       timep;\r
-{\r
-       register struct state *         sp;\r
-       register struct lsinfo *        lp;\r
-       register int                    i;\r
-\r
-       sp = lclptr;\r
-       i = sp->leapcnt;\r
-       while (--i >= 0) {\r
-               lp = &sp->lsis[i];\r
-               if (*timep >= lp->ls_trans)\r
-                       return lp->ls_corr;\r
-       }\r
-       return 0;\r
-}\r
-\r
-time_t\r
-time2posix(t)\r
-time_t t;\r
-{\r
-       tzset();\r
-       return t - leapcorr(&t);\r
-}\r
-\r
-time_t\r
-posix2time(t)\r
-time_t t;\r
-{\r
-       time_t  x;\r
-       time_t  y;\r
-\r
-       tzset();\r
-       /*\r
-       ** For a positive leap second hit, the result\r
-       ** is not unique.  For a negative leap second\r
-       ** hit, the corresponding time doesn't exist,\r
-       ** so we return an adjacent second.\r
-       */\r
-       x = t + leapcorr(&t);\r
-       y = x - leapcorr(&x);\r
-       if (y < t) {\r
-               do {\r
-                       x++;\r
-                       y = x - leapcorr(&x);\r
-               } while (y < t);\r
-               if (t != y)\r
-                       return x - 1;\r
-       } else if (y > t) {\r
-               do {\r
-                       --x;\r
-                       y = x - leapcorr(&x);\r
-               } while (y > t);\r
-               if (t != y)\r
-                       return x + 1;\r
-       }\r
-       return x;\r
-}\r
-\r
-#endif /* defined STD_INSPIRED */\r
+#include "pgtz.h"
+#undef open
+#define timezone pg_timezone
+#define USG_COMPAT
+extern time_t pg_timezone;
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+#ifndef lint
+#ifndef NOID
+static char    elsieid[] = "@(#)localtime.c    7.78";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*
+** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
+** POSIX-style TZ environment variable handling from Guy Harris
+** (guy@auspex.com).
+*/
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+#include "tzfile.h"
+#include "fcntl.h"
+
+/*
+** SunOS 4.1.1 headers lack O_BINARY.
+*/
+
+#ifdef O_BINARY
+#define OPEN_MODE      (O_RDONLY | O_BINARY)
+#endif /* defined O_BINARY */
+#ifndef O_BINARY
+#define OPEN_MODE      O_RDONLY
+#endif /* !defined O_BINARY */
+
+#ifndef WILDABBR
+/*
+** Someone might make incorrect use of a time zone abbreviation:
+**     1.      They might reference tzname[0] before calling tzset (explicitly
+**             or implicitly).
+**     2.      They might reference tzname[1] before calling tzset (explicitly
+**             or implicitly).
+**     3.      They might reference tzname[1] after setting to a time zone
+**             in which Daylight Saving Time is never observed.
+**     4.      They might reference tzname[0] after setting to a time zone
+**             in which Standard Time is never observed.
+**     5.      They might reference tm.TM_ZONE after calling offtime.
+** What's best to do in the above cases is open to debate;
+** for now, we just set things up so that in any of the five cases
+** WILDABBR is used.  Another possibility:  initialize tzname[0] to the
+** string "tzname[0] used before set", and similarly for the other cases.
+** And another:  initialize tzname[0] to "ERA", with an explanation in the
+** manual page of what this "time zone abbreviation" means (doing this so
+** that tzname[0] has the "normal" length of three characters).
+*/
+#define WILDABBR       "   "
+#endif /* !defined WILDABBR */
+
+static char            wildabbr[] = "WILDABBR";
+
+static const char      gmt[] = "GMT";
+
+/*
+** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
+** We default to US rules as of 1999-08-17.
+** POSIX 1003.1 section 8.1.1 says that the default DST rules are
+** implementation dependent; for historical reasons, US rules are a
+** common default.
+*/
+#ifndef TZDEFRULESTRING
+#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
+#endif /* !defined TZDEFDST */
+
+struct ttinfo {                                /* time type information */
+       long            tt_gmtoff;      /* UTC offset in seconds */
+       int             tt_isdst;       /* used to set tm_isdst */
+       int             tt_abbrind;     /* abbreviation list index */
+       int             tt_ttisstd;     /* TRUE if transition is std time */
+       int             tt_ttisgmt;     /* TRUE if transition is UTC */
+};
+
+struct lsinfo {                                /* leap second information */
+       time_t          ls_trans;       /* transition time */
+       long            ls_corr;        /* correction to apply */
+};
+
+#define BIGGEST(a, b)  (((a) > (b)) ? (a) : (b))
+
+#ifdef TZNAME_MAX
+#define MY_TZNAME_MAX  TZNAME_MAX
+#endif /* defined TZNAME_MAX */
+#ifndef TZNAME_MAX
+#define MY_TZNAME_MAX  255
+#endif /* !defined TZNAME_MAX */
+
+struct state {
+       int             leapcnt;
+       int             timecnt;
+       int             typecnt;
+       int             charcnt;
+       time_t          ats[TZ_MAX_TIMES];
+       unsigned char   types[TZ_MAX_TIMES];
+       struct ttinfo   ttis[TZ_MAX_TYPES];
+       char            chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
+                               (2 * (MY_TZNAME_MAX + 1)))];
+       struct lsinfo   lsis[TZ_MAX_LEAPS];
+};
+
+struct rule {
+       int             r_type;         /* type of rule--see below */
+       int             r_day;          /* day number of rule */
+       int             r_week;         /* week number of rule */
+       int             r_mon;          /* month number of rule */
+       long            r_time;         /* transition time of rule */
+};
+
+#define JULIAN_DAY             0       /* Jn - Julian day */
+#define DAY_OF_YEAR            1       /* n - day of year */
+#define MONTH_NTH_DAY_OF_WEEK  2       /* Mm.n.d - month, week, day of week */
+
+/*
+** Prototypes for static functions.
+*/
+
+static long            detzcode P((const char * codep));
+static const char *    getzname P((const char * strp));
+static const char *    getnum P((const char * strp, int * nump, int min,
+                               int max));
+static const char *    getsecs P((const char * strp, long * secsp));
+static const char *    getoffset P((const char * strp, long * offsetp));
+static const char *    getrule P((const char * strp, struct rule * rulep));
+static void            gmtload P((struct state * sp));
+static void            gmtsub P((const time_t * timep, long offset,
+                               struct tm * tmp));
+static void            localsub P((const time_t * timep, long offset,
+                               struct tm * tmp));
+static int             increment_overflow P((int * number, int delta));
+static int             normalize_overflow P((int * tensptr, int * unitsptr,
+                               int base));
+static void            settzname P((void));
+static time_t          time1 P((struct tm * tmp,
+                               void(*funcp) P((const time_t *,
+                               long, struct tm *)),
+                               long offset));
+static time_t          time2 P((struct tm *tmp,
+                               void(*funcp) P((const time_t *,
+                               long, struct tm*)),
+                               long offset, int * okayp));
+static time_t          time2sub P((struct tm *tmp,
+                               void(*funcp) P((const time_t *,
+                               long, struct tm*)),
+                               long offset, int * okayp, int do_norm_secs));
+static void            timesub P((const time_t * timep, long offset,
+                               const struct state * sp, struct tm * tmp));
+static int             tmcomp P((const struct tm * atmp,
+                               const struct tm * btmp));
+static time_t          transtime P((time_t janfirst, int year,
+                               const struct rule * rulep, long offset));
+static int             tzload P((const char * name, struct state * sp));
+static int             tzparse P((const char * name, struct state * sp,
+                               int lastditch));
+
+#ifdef ALL_STATE
+static struct state *  lclptr;
+static struct state *  gmtptr;
+#endif /* defined ALL_STATE */
+
+#ifndef ALL_STATE
+static struct state    lclmem;
+static struct state    gmtmem;
+#define lclptr         (&lclmem)
+#define gmtptr         (&gmtmem)
+#endif /* State Farm */
+
+#ifndef TZ_STRLEN_MAX
+#define TZ_STRLEN_MAX 255
+#endif /* !defined TZ_STRLEN_MAX */
+
+static char            lcl_TZname[TZ_STRLEN_MAX + 1];
+static int             lcl_is_set;
+static int             gmt_is_set;
+
+char *                 tzname[2] = {
+       wildabbr,
+       wildabbr
+};
+
+/*
+** Section 4.12.3 of X3.159-1989 requires that
+**     Except for the strftime function, these functions [asctime,
+**     ctime, gmtime, localtime] return values in one of two static
+**     objects: a broken-down time structure and an array of char.
+** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
+*/
+
+static struct tm       tm;
+
+#ifdef USG_COMPAT
+time_t                 timezone = 0;
+int                    daylight = 0;
+#endif /* defined USG_COMPAT */
+
+#ifdef ALTZONE
+time_t                 altzone = 0;
+#endif /* defined ALTZONE */
+
+static long
+detzcode(codep)
+const char * const     codep;
+{
+       register long   result;
+       register int    i;
+
+       result = (codep[0] & 0x80) ? ~0L : 0L;
+       for (i = 0; i < 4; ++i)
+               result = (result << 8) | (codep[i] & 0xff);
+       return result;
+}
+
+static void
+settzname P((void))
+{
+       register struct state * const   sp = lclptr;
+       register int                    i;
+
+       tzname[0] = wildabbr;
+       tzname[1] = wildabbr;
+#ifdef USG_COMPAT
+       daylight = 0;
+       timezone = 0;
+#endif /* defined USG_COMPAT */
+#ifdef ALTZONE
+       altzone = 0;
+#endif /* defined ALTZONE */
+#ifdef ALL_STATE
+       if (sp == NULL) {
+               tzname[0] = tzname[1] = gmt;
+               return;
+       }
+#endif /* defined ALL_STATE */
+       for (i = 0; i < sp->typecnt; ++i) {
+               register const struct ttinfo * const    ttisp = &sp->ttis[i];
+
+               tzname[ttisp->tt_isdst] =
+                       &sp->chars[ttisp->tt_abbrind];
+#ifdef USG_COMPAT
+               if (ttisp->tt_isdst)
+                       daylight = 1;
+               if (i == 0 || !ttisp->tt_isdst)
+                       timezone = -(ttisp->tt_gmtoff);
+#endif /* defined USG_COMPAT */
+#ifdef ALTZONE
+               if (i == 0 || ttisp->tt_isdst)
+                       altzone = -(ttisp->tt_gmtoff);
+#endif /* defined ALTZONE */
+       }
+       /*
+       ** And to get the latest zone names into tzname. . .
+       */
+       for (i = 0; i < sp->timecnt; ++i) {
+               register const struct ttinfo * const    ttisp =
+                                                       &sp->ttis[
+                                                               sp->types[i]];
+
+               tzname[ttisp->tt_isdst] =
+                       &sp->chars[ttisp->tt_abbrind];
+       }
+}
+
+static int
+tzload(name, sp)
+register const char *          name;
+register struct state * const  sp;
+{
+       register const char *   p;
+       register int            i;
+       register int            fid;
+
+       if (name == NULL && (name = TZDEFAULT) == NULL)
+               return -1;
+       {
+               register int    doaccess;
+               /*
+               ** Section 4.9.1 of the C standard says that
+               ** "FILENAME_MAX expands to an integral constant expression
+               ** that is the size needed for an array of char large enough
+               ** to hold the longest file name string that the implementation
+               ** guarantees can be opened."
+               */
+               char            fullname[FILENAME_MAX + 1];
+
+               if (name[0] == ':')
+                       ++name;
+               doaccess = name[0] == '/';
+               if (!doaccess) {
+                       if ((p = TZDIR) == NULL)
+                               return -1;
+                       if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
+                               return -1;
+                       (void) strcpy(fullname, p);
+                       (void) strcat(fullname, "/");
+                       (void) strcat(fullname, name);
+                       /*
+                       ** Set doaccess if '.' (as in "../") shows up in name.
+                       */
+                       if (strchr(name, '.') != NULL)
+                               doaccess = TRUE;
+                       name = fullname;
+               }
+               if (doaccess && access(name, R_OK) != 0)
+                       return -1;
+               if ((fid = open(name, OPEN_MODE)) == -1)
+                       return -1;
+       }
+       {
+               struct tzhead * tzhp;
+               union {
+                       struct tzhead   tzhead;
+                       char            buf[sizeof *sp + sizeof *tzhp];
+               } u;
+               int             ttisstdcnt;
+               int             ttisgmtcnt;
+
+               i = read(fid, u.buf, sizeof u.buf);
+               if (close(fid) != 0)
+                       return -1;
+               ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
+               ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
+               sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
+               sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
+               sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
+               sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
+               p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
+               if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
+                       sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
+                       sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
+                       sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
+                       (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
+                       (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
+                               return -1;
+               if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */
+                       sp->timecnt +                   /* types */
+                       sp->typecnt * (4 + 2) +         /* ttinfos */
+                       sp->charcnt +                   /* chars */
+                       sp->leapcnt * (4 + 4) +         /* lsinfos */
+                       ttisstdcnt +                    /* ttisstds */
+                       ttisgmtcnt)                     /* ttisgmts */
+                               return -1;
+               for (i = 0; i < sp->timecnt; ++i) {
+                       sp->ats[i] = detzcode(p);
+                       p += 4;
+               }
+               for (i = 0; i < sp->timecnt; ++i) {
+                       sp->types[i] = (unsigned char) *p++;
+                       if (sp->types[i] >= sp->typecnt)
+                               return -1;
+               }
+               for (i = 0; i < sp->typecnt; ++i) {
+                       register struct ttinfo *        ttisp;
+
+                       ttisp = &sp->ttis[i];
+                       ttisp->tt_gmtoff = detzcode(p);
+                       p += 4;
+                       ttisp->tt_isdst = (unsigned char) *p++;
+                       if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
+                               return -1;
+                       ttisp->tt_abbrind = (unsigned char) *p++;
+                       if (ttisp->tt_abbrind < 0 ||
+                               ttisp->tt_abbrind > sp->charcnt)
+                                       return -1;
+               }
+               for (i = 0; i < sp->charcnt; ++i)
+                       sp->chars[i] = *p++;
+               sp->chars[i] = '\0';    /* ensure '\0' at end */
+               for (i = 0; i < sp->leapcnt; ++i) {
+                       register struct lsinfo *        lsisp;
+
+                       lsisp = &sp->lsis[i];
+                       lsisp->ls_trans = detzcode(p);
+                       p += 4;
+                       lsisp->ls_corr = detzcode(p);
+                       p += 4;
+               }
+               for (i = 0; i < sp->typecnt; ++i) {
+                       register struct ttinfo *        ttisp;
+
+                       ttisp = &sp->ttis[i];
+                       if (ttisstdcnt == 0)
+                               ttisp->tt_ttisstd = FALSE;
+                       else {
+                               ttisp->tt_ttisstd = *p++;
+                               if (ttisp->tt_ttisstd != TRUE &&
+                                       ttisp->tt_ttisstd != FALSE)
+                                               return -1;
+                       }
+               }
+               for (i = 0; i < sp->typecnt; ++i) {
+                       register struct ttinfo *        ttisp;
+
+                       ttisp = &sp->ttis[i];
+                       if (ttisgmtcnt == 0)
+                               ttisp->tt_ttisgmt = FALSE;
+                       else {
+                               ttisp->tt_ttisgmt = *p++;
+                               if (ttisp->tt_ttisgmt != TRUE &&
+                                       ttisp->tt_ttisgmt != FALSE)
+                                               return -1;
+                       }
+               }
+       }
+       return 0;
+}
+
+static const int       mon_lengths[2][MONSPERYEAR] = {
+       { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+       { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static const int       year_lengths[2] = {
+       DAYSPERNYEAR, DAYSPERLYEAR
+};
+
+/*
+** Given a pointer into a time zone string, scan until a character that is not
+** a valid character in a zone name is found.  Return a pointer to that
+** character.
+*/
+
+static const char *
+getzname(strp)
+register const char *  strp;
+{
+       register char   c;
+
+       while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
+               c != '+')
+                       ++strp;
+       return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract a number from that string.
+** Check that the number is within a specified range; if it is not, return
+** NULL.
+** Otherwise, return a pointer to the first character not part of the number.
+*/
+
+static const char *
+getnum(strp, nump, min, max)
+register const char *  strp;
+int * const            nump;
+const int              min;
+const int              max;
+{
+       register char   c;
+       register int    num;
+
+       if (strp == NULL || !is_digit(c = *strp))
+               return NULL;
+       num = 0;
+       do {
+               num = num * 10 + (c - '0');
+               if (num > max)
+                       return NULL;    /* illegal value */
+               c = *++strp;
+       } while (is_digit(c));
+       if (num < min)
+               return NULL;            /* illegal value */
+       *nump = num;
+       return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract a number of seconds,
+** in hh[:mm[:ss]] form, from the string.
+** If any error occurs, return NULL.
+** Otherwise, return a pointer to the first character not part of the number
+** of seconds.
+*/
+
+static const char *
+getsecs(strp, secsp)
+register const char *  strp;
+long * const           secsp;
+{
+       int     num;
+
+       /*
+       ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
+       ** "M10.4.6/26", which does not conform to Posix,
+       ** but which specifies the equivalent of
+       ** ``02:00 on the first Sunday on or after 23 Oct''.
+       */
+       strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
+       if (strp == NULL)
+               return NULL;
+       *secsp = num * (long) SECSPERHOUR;
+       if (*strp == ':') {
+               ++strp;
+               strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
+               if (strp == NULL)
+                       return NULL;
+               *secsp += num * SECSPERMIN;
+               if (*strp == ':') {
+                       ++strp;
+                       /* `SECSPERMIN' allows for leap seconds.  */
+                       strp = getnum(strp, &num, 0, SECSPERMIN);
+                       if (strp == NULL)
+                               return NULL;
+                       *secsp += num;
+               }
+       }
+       return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract an offset, in
+** [+-]hh[:mm[:ss]] form, from the string.
+** If any error occurs, return NULL.
+** Otherwise, return a pointer to the first character not part of the time.
+*/
+
+static const char *
+getoffset(strp, offsetp)
+register const char *  strp;
+long * const           offsetp;
+{
+       register int    neg = 0;
+
+       if (*strp == '-') {
+               neg = 1;
+               ++strp;
+       } else if (*strp == '+')
+               ++strp;
+       strp = getsecs(strp, offsetp);
+       if (strp == NULL)
+               return NULL;            /* illegal time */
+       if (neg)
+               *offsetp = -*offsetp;
+       return strp;
+}
+
+/*
+** Given a pointer into a time zone string, extract a rule in the form
+** date[/time].  See POSIX section 8 for the format of "date" and "time".
+** If a valid rule is not found, return NULL.
+** Otherwise, return a pointer to the first character not part of the rule.
+*/
+
+static const char *
+getrule(strp, rulep)
+const char *                   strp;
+register struct rule * const   rulep;
+{
+       if (*strp == 'J') {
+               /*
+               ** Julian day.
+               */
+               rulep->r_type = JULIAN_DAY;
+               ++strp;
+               strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
+       } else if (*strp == 'M') {
+               /*
+               ** Month, week, day.
+               */
+               rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
+               ++strp;
+               strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
+               if (strp == NULL)
+                       return NULL;
+               if (*strp++ != '.')
+                       return NULL;
+               strp = getnum(strp, &rulep->r_week, 1, 5);
+               if (strp == NULL)
+                       return NULL;
+               if (*strp++ != '.')
+                       return NULL;
+               strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
+       } else if (is_digit(*strp)) {
+               /*
+               ** Day of year.
+               */
+               rulep->r_type = DAY_OF_YEAR;
+               strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
+       } else  return NULL;            /* invalid format */
+       if (strp == NULL)
+               return NULL;
+       if (*strp == '/') {
+               /*
+               ** Time specified.
+               */
+               ++strp;
+               strp = getsecs(strp, &rulep->r_time);
+       } else  rulep->r_time = 2 * SECSPERHOUR;        /* default = 2:00:00 */
+       return strp;
+}
+
+/*
+** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
+** year, a rule, and the offset from UTC at the time that rule takes effect,
+** calculate the Epoch-relative time that rule takes effect.
+*/
+
+static time_t
+transtime(janfirst, year, rulep, offset)
+const time_t                           janfirst;
+const int                              year;
+register const struct rule * const     rulep;
+const long                             offset;
+{
+       register int    leapyear;
+       register time_t value;
+       register int    i;
+       int             d, m1, yy0, yy1, yy2, dow;
+
+       INITIALIZE(value);
+       leapyear = isleap(year);
+       switch (rulep->r_type) {
+
+       case JULIAN_DAY:
+               /*
+               ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
+               ** years.
+               ** In non-leap years, or if the day number is 59 or less, just
+               ** add SECSPERDAY times the day number-1 to the time of
+               ** January 1, midnight, to get the day.
+               */
+               value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
+               if (leapyear && rulep->r_day >= 60)
+                       value += SECSPERDAY;
+               break;
+
+       case DAY_OF_YEAR:
+               /*
+               ** n - day of year.
+               ** Just add SECSPERDAY times the day number to the time of
+               ** January 1, midnight, to get the day.
+               */
+               value = janfirst + rulep->r_day * SECSPERDAY;
+               break;
+
+       case MONTH_NTH_DAY_OF_WEEK:
+               /*
+               ** Mm.n.d - nth "dth day" of month m.
+               */
+               value = janfirst;
+               for (i = 0; i < rulep->r_mon - 1; ++i)
+                       value += mon_lengths[leapyear][i] * SECSPERDAY;
+
+               /*
+               ** Use Zeller's Congruence to get day-of-week of first day of
+               ** month.
+               */
+               m1 = (rulep->r_mon + 9) % 12 + 1;
+               yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
+               yy1 = yy0 / 100;
+               yy2 = yy0 % 100;
+               dow = ((26 * m1 - 2) / 10 +
+                       1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
+               if (dow < 0)
+                       dow += DAYSPERWEEK;
+
+               /*
+               ** "dow" is the day-of-week of the first day of the month.  Get
+               ** the day-of-month (zero-origin) of the first "dow" day of the
+               ** month.
+               */
+               d = rulep->r_day - dow;
+               if (d < 0)
+                       d += DAYSPERWEEK;
+               for (i = 1; i < rulep->r_week; ++i) {
+                       if (d + DAYSPERWEEK >=
+                               mon_lengths[leapyear][rulep->r_mon - 1])
+                                       break;
+                       d += DAYSPERWEEK;
+               }
+
+               /*
+               ** "d" is the day-of-month (zero-origin) of the day we want.
+               */
+               value += d * SECSPERDAY;
+               break;
+       }
+
+       /*
+       ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
+       ** question.  To get the Epoch-relative time of the specified local
+       ** time on that day, add the transition time and the current offset
+       ** from UTC.
+       */
+       return value + rulep->r_time + offset;
+}
+
+/*
+** Given a POSIX section 8-style TZ string, fill in the rule tables as
+** appropriate.
+*/
+
+static int
+tzparse(name, sp, lastditch)
+const char *                   name;
+register struct state * const  sp;
+const int                      lastditch;
+{
+       const char *                    stdname;
+       const char *                    dstname;
+       size_t                          stdlen;
+       size_t                          dstlen;
+       long                            stdoffset;
+       long                            dstoffset;
+       register time_t *               atp;
+       register unsigned char *        typep;
+       register char *                 cp;
+       register int                    load_result;
+
+       INITIALIZE(dstname);
+       stdname = name;
+       if (lastditch) {
+               stdlen = strlen(name);  /* length of standard zone name */
+               name += stdlen;
+               if (stdlen >= sizeof sp->chars)
+                       stdlen = (sizeof sp->chars) - 1;
+               stdoffset = 0;
+       } else {
+               name = getzname(name);
+               stdlen = name - stdname;
+               if (stdlen < 3)
+                       return -1;
+               if (*name == '\0')
+                       return -1;
+               name = getoffset(name, &stdoffset);
+               if (name == NULL)
+                       return -1;
+       }
+       load_result = tzload(TZDEFRULES, sp);
+       if (load_result != 0)
+               sp->leapcnt = 0;                /* so, we're off a little */
+       if (*name != '\0') {
+               dstname = name;
+               name = getzname(name);
+               dstlen = name - dstname;        /* length of DST zone name */
+               if (dstlen < 3)
+                       return -1;
+               if (*name != '\0' && *name != ',' && *name != ';') {
+                       name = getoffset(name, &dstoffset);
+                       if (name == NULL)
+                               return -1;
+               } else  dstoffset = stdoffset - SECSPERHOUR;
+               if (*name == '\0' && load_result != 0)
+                       name = TZDEFRULESTRING;
+               if (*name == ',' || *name == ';') {
+                       struct rule     start;
+                       struct rule     end;
+                       register int    year;
+                       register time_t janfirst;
+                       time_t          starttime;
+                       time_t          endtime;
+
+                       ++name;
+                       if ((name = getrule(name, &start)) == NULL)
+                               return -1;
+                       if (*name++ != ',')
+                               return -1;
+                       if ((name = getrule(name, &end)) == NULL)
+                               return -1;
+                       if (*name != '\0')
+                               return -1;
+                       sp->typecnt = 2;        /* standard time and DST */
+                       /*
+                       ** Two transitions per year, from EPOCH_YEAR to 2037.
+                       */
+                       sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
+                       if (sp->timecnt > TZ_MAX_TIMES)
+                               return -1;
+                       sp->ttis[0].tt_gmtoff = -dstoffset;
+                       sp->ttis[0].tt_isdst = 1;
+                       sp->ttis[0].tt_abbrind = stdlen + 1;
+                       sp->ttis[1].tt_gmtoff = -stdoffset;
+                       sp->ttis[1].tt_isdst = 0;
+                       sp->ttis[1].tt_abbrind = 0;
+                       atp = sp->ats;
+                       typep = sp->types;
+                       janfirst = 0;
+                       for (year = EPOCH_YEAR; year <= 2037; ++year) {
+                               starttime = transtime(janfirst, year, &start,
+                                       stdoffset);
+                               endtime = transtime(janfirst, year, &end,
+                                       dstoffset);
+                               if (starttime > endtime) {
+                                       *atp++ = endtime;
+                                       *typep++ = 1;   /* DST ends */
+                                       *atp++ = starttime;
+                                       *typep++ = 0;   /* DST begins */
+                               } else {
+                                       *atp++ = starttime;
+                                       *typep++ = 0;   /* DST begins */
+                                       *atp++ = endtime;
+                                       *typep++ = 1;   /* DST ends */
+                               }
+                               janfirst += year_lengths[isleap(year)] *
+                                       SECSPERDAY;
+                       }
+               } else {
+                       register long   theirstdoffset;
+                       register long   theirdstoffset;
+                       register long   theiroffset;
+                       register int    isdst;
+                       register int    i;
+                       register int    j;
+
+                       if (*name != '\0')
+                               return -1;
+                       /*
+                       ** Initial values of theirstdoffset and theirdstoffset.
+                       */
+                       theirstdoffset = 0;
+                       for (i = 0; i < sp->timecnt; ++i) {
+                               j = sp->types[i];
+                               if (!sp->ttis[j].tt_isdst) {
+                                       theirstdoffset =
+                                               -sp->ttis[j].tt_gmtoff;
+                                       break;
+                               }
+                       }
+                       theirdstoffset = 0;
+                       for (i = 0; i < sp->timecnt; ++i) {
+                               j = sp->types[i];
+                               if (sp->ttis[j].tt_isdst) {
+                                       theirdstoffset =
+                                               -sp->ttis[j].tt_gmtoff;
+                                       break;
+                               }
+                       }
+                       /*
+                       ** Initially we're assumed to be in standard time.
+                       */
+                       isdst = FALSE;
+                       theiroffset = theirstdoffset;
+                       /*
+                       ** Now juggle transition times and types
+                       ** tracking offsets as you do.
+                       */
+                       for (i = 0; i < sp->timecnt; ++i) {
+                               j = sp->types[i];
+                               sp->types[i] = sp->ttis[j].tt_isdst;
+                               if (sp->ttis[j].tt_ttisgmt) {
+                                       /* No adjustment to transition time */
+                               } else {
+                                       /*
+                                       ** If summer time is in effect, and the
+                                       ** transition time was not specified as
+                                       ** standard time, add the summer time
+                                       ** offset to the transition time;
+                                       ** otherwise, add the standard time
+                                       ** offset to the transition time.
+                                       */
+                                       /*
+                                       ** Transitions from DST to DDST
+                                       ** will effectively disappear since
+                                       ** POSIX provides for only one DST
+                                       ** offset.
+                                       */
+                                       if (isdst && !sp->ttis[j].tt_ttisstd) {
+                                               sp->ats[i] += dstoffset -
+                                                       theirdstoffset;
+                                       } else {
+                                               sp->ats[i] += stdoffset -
+                                                       theirstdoffset;
+                                       }
+                               }
+                               theiroffset = -sp->ttis[j].tt_gmtoff;
+                               if (sp->ttis[j].tt_isdst)
+                                       theirdstoffset = theiroffset;
+                               else    theirstdoffset = theiroffset;
+                       }
+                       /*
+                       ** Finally, fill in ttis.
+                       ** ttisstd and ttisgmt need not be handled.
+                       */
+                       sp->ttis[0].tt_gmtoff = -stdoffset;
+                       sp->ttis[0].tt_isdst = FALSE;
+                       sp->ttis[0].tt_abbrind = 0;
+                       sp->ttis[1].tt_gmtoff = -dstoffset;
+                       sp->ttis[1].tt_isdst = TRUE;
+                       sp->ttis[1].tt_abbrind = stdlen + 1;
+                       sp->typecnt = 2;
+               }
+       } else {
+               dstlen = 0;
+               sp->typecnt = 1;                /* only standard time */
+               sp->timecnt = 0;
+               sp->ttis[0].tt_gmtoff = -stdoffset;
+               sp->ttis[0].tt_isdst = 0;
+               sp->ttis[0].tt_abbrind = 0;
+       }
+       sp->charcnt = stdlen + 1;
+       if (dstlen != 0)
+               sp->charcnt += dstlen + 1;
+       if ((size_t) sp->charcnt > sizeof sp->chars)
+               return -1;
+       cp = sp->chars;
+       (void) strncpy(cp, stdname, stdlen);
+       cp += stdlen;
+       *cp++ = '\0';
+       if (dstlen != 0) {
+               (void) strncpy(cp, dstname, dstlen);
+               *(cp + dstlen) = '\0';
+       }
+       return 0;
+}
+
+static void
+gmtload(sp)
+struct state * const   sp;
+{
+       if (tzload(gmt, sp) != 0)
+               (void) tzparse(gmt, sp, TRUE);
+}
+
+#ifndef STD_INSPIRED
+/*
+** A non-static declaration of tzsetwall in a system header file
+** may cause a warning about this upcoming static declaration...
+*/
+static
+#endif /* !defined STD_INSPIRED */
+void
+tzsetwall P((void))
+{
+       if (lcl_is_set < 0)
+               return;
+       lcl_is_set = -1;
+
+#ifdef ALL_STATE
+       if (lclptr == NULL) {
+               lclptr = (struct state *) malloc(sizeof *lclptr);
+               if (lclptr == NULL) {
+                       settzname();    /* all we can do */
+                       return;
+               }
+       }
+#endif /* defined ALL_STATE */
+       if (tzload((char *) NULL, lclptr) != 0)
+               gmtload(lclptr);
+       settzname();
+}
+
+void
+tzset P((void))
+{
+       register const char *   name;
+
+       name = getenv("TZ");
+       if (name == NULL) {
+               tzsetwall();
+               return;
+       }
+
+       if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
+               return;
+       lcl_is_set = strlen(name) < sizeof lcl_TZname;
+       if (lcl_is_set)
+               (void) strcpy(lcl_TZname, name);
+
+#ifdef ALL_STATE
+       if (lclptr == NULL) {
+               lclptr = (struct state *) malloc(sizeof *lclptr);
+               if (lclptr == NULL) {
+                       settzname();    /* all we can do */
+                       return;
+               }
+       }
+#endif /* defined ALL_STATE */
+       if (*name == '\0') {
+               /*
+               ** User wants it fast rather than right.
+               */
+               lclptr->leapcnt = 0;            /* so, we're off a little */
+               lclptr->timecnt = 0;
+               lclptr->typecnt = 0;
+               lclptr->ttis[0].tt_isdst = 0;
+               lclptr->ttis[0].tt_gmtoff = 0;
+               lclptr->ttis[0].tt_abbrind = 0;
+               (void) strcpy(lclptr->chars, gmt);
+       } else if (tzload(name, lclptr) != 0)
+               if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
+                       (void) gmtload(lclptr);
+       settzname();
+}
+
+/*
+** The easy way to behave "as if no library function calls" localtime
+** is to not call it--so we drop its guts into "localsub", which can be
+** freely called.  (And no, the PANS doesn't require the above behavior--
+** but it *is* desirable.)
+**
+** The unused offset argument is for the benefit of mktime variants.
+*/
+
+/*ARGSUSED*/
+static void
+localsub(timep, offset, tmp)
+const time_t * const   timep;
+const long             offset;
+struct tm * const      tmp;
+{
+       register struct state *         sp;
+       register const struct ttinfo *  ttisp;
+       register int                    i;
+       const time_t                    t = *timep;
+
+       sp = lclptr;
+#ifdef ALL_STATE
+       if (sp == NULL) {
+               gmtsub(timep, offset, tmp);
+               return;
+       }
+#endif /* defined ALL_STATE */
+       if (sp->timecnt == 0 || t < sp->ats[0]) {
+               i = 0;
+               while (sp->ttis[i].tt_isdst)
+                       if (++i >= sp->typecnt) {
+                               i = 0;
+                               break;
+                       }
+       } else {
+               for (i = 1; i < sp->timecnt; ++i)
+                       if (t < sp->ats[i])
+                               break;
+               i = sp->types[i - 1];
+       }
+       ttisp = &sp->ttis[i];
+       /*
+       ** To get (wrong) behavior that's compatible with System V Release 2.0
+       ** you'd replace the statement below with
+       **      t += ttisp->tt_gmtoff;
+       **      timesub(&t, 0L, sp, tmp);
+       */
+       timesub(&t, ttisp->tt_gmtoff, sp, tmp);
+       tmp->tm_isdst = ttisp->tt_isdst;
+       tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
+#ifdef TM_ZONE
+       tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
+#endif /* defined TM_ZONE */
+}
+
+struct tm *
+localtime(timep)
+const time_t * const   timep;
+{
+       tzset();
+       localsub(timep, 0L, &tm);
+       return &tm;
+}
+
+/*
+** Re-entrant version of localtime.
+*/
+
+struct tm *
+localtime_r(timep, tm)
+const time_t * const   timep;
+struct tm *            tm;
+{
+       localsub(timep, 0L, tm);
+       return tm;
+}
+
+/*
+** gmtsub is to gmtime as localsub is to localtime.
+*/
+
+static void
+gmtsub(timep, offset, tmp)
+const time_t * const   timep;
+const long             offset;
+struct tm * const      tmp;
+{
+       if (!gmt_is_set) {
+               gmt_is_set = TRUE;
+#ifdef ALL_STATE
+               gmtptr = (struct state *) malloc(sizeof *gmtptr);
+               if (gmtptr != NULL)
+#endif /* defined ALL_STATE */
+                       gmtload(gmtptr);
+       }
+       timesub(timep, offset, gmtptr, tmp);
+#ifdef TM_ZONE
+       /*
+       ** Could get fancy here and deliver something such as
+       ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
+       ** but this is no time for a treasure hunt.
+       */
+       if (offset != 0)
+               tmp->TM_ZONE = wildabbr;
+       else {
+#ifdef ALL_STATE
+               if (gmtptr == NULL)
+                       tmp->TM_ZONE = gmt;
+               else    tmp->TM_ZONE = gmtptr->chars;
+#endif /* defined ALL_STATE */
+#ifndef ALL_STATE
+               tmp->TM_ZONE = gmtptr->chars;
+#endif /* State Farm */
+       }
+#endif /* defined TM_ZONE */
+}
+
+struct tm *
+gmtime(timep)
+const time_t * const   timep;
+{
+       gmtsub(timep, 0L, &tm);
+       return &tm;
+}
+
+/*
+* Re-entrant version of gmtime.
+*/
+
+struct tm *
+gmtime_r(timep, tm)
+const time_t * const   timep;
+struct tm *            tm;
+{
+       gmtsub(timep, 0L, tm);
+       return tm;
+}
+
+#ifdef STD_INSPIRED
+
+struct tm *
+offtime(timep, offset)
+const time_t * const   timep;
+const long             offset;
+{
+       gmtsub(timep, offset, &tm);
+       return &tm;
+}
+
+#endif /* defined STD_INSPIRED */
+
+static void
+timesub(timep, offset, sp, tmp)
+const time_t * const                   timep;
+const long                             offset;
+register const struct state * const    sp;
+register struct tm * const             tmp;
+{
+       register const struct lsinfo *  lp;
+       register long                   days;
+       register long                   rem;
+       register int                    y;
+       register int                    yleap;
+       register const int *            ip;
+       register long                   corr;
+       register int                    hit;
+       register int                    i;
+
+       corr = 0;
+       hit = 0;
+#ifdef ALL_STATE
+       i = (sp == NULL) ? 0 : sp->leapcnt;
+#endif /* defined ALL_STATE */
+#ifndef ALL_STATE
+       i = sp->leapcnt;
+#endif /* State Farm */
+       while (--i >= 0) {
+               lp = &sp->lsis[i];
+               if (*timep >= lp->ls_trans) {
+                       if (*timep == lp->ls_trans) {
+                               hit = ((i == 0 && lp->ls_corr > 0) ||
+                                       lp->ls_corr > sp->lsis[i - 1].ls_corr);
+                               if (hit)
+                                       while (i > 0 &&
+                                               sp->lsis[i].ls_trans ==
+                                               sp->lsis[i - 1].ls_trans + 1 &&
+                                               sp->lsis[i].ls_corr ==
+                                               sp->lsis[i - 1].ls_corr + 1) {
+                                                       ++hit;
+                                                       --i;
+                                       }
+                       }
+                       corr = lp->ls_corr;
+                       break;
+               }
+       }
+       days = *timep / SECSPERDAY;
+       rem = *timep % SECSPERDAY;
+#ifdef mc68k
+       if (*timep == 0x80000000) {
+               /*
+               ** A 3B1 muffs the division on the most negative number.
+               */
+               days = -24855;
+               rem = -11648;
+       }
+#endif /* defined mc68k */
+       rem += (offset - corr);
+       while (rem < 0) {
+               rem += SECSPERDAY;
+               --days;
+       }
+       while (rem >= SECSPERDAY) {
+               rem -= SECSPERDAY;
+               ++days;
+       }
+       tmp->tm_hour = (int) (rem / SECSPERHOUR);
+       rem = rem % SECSPERHOUR;
+       tmp->tm_min = (int) (rem / SECSPERMIN);
+       /*
+       ** A positive leap second requires a special
+       ** representation.  This uses "... ??:59:60" et seq.
+       */
+       tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
+       tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
+       if (tmp->tm_wday < 0)
+               tmp->tm_wday += DAYSPERWEEK;
+       y = EPOCH_YEAR;
+#define LEAPS_THRU_END_OF(y)   ((y) / 4 - (y) / 100 + (y) / 400)
+       while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
+               register int    newy;
+
+               newy = y + days / DAYSPERNYEAR;
+               if (days < 0)
+                       --newy;
+               days -= (newy - y) * DAYSPERNYEAR +
+                       LEAPS_THRU_END_OF(newy - 1) -
+                       LEAPS_THRU_END_OF(y - 1);
+               y = newy;
+       }
+       tmp->tm_year = y - TM_YEAR_BASE;
+       tmp->tm_yday = (int) days;
+       ip = mon_lengths[yleap];
+       for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
+               days = days - (long) ip[tmp->tm_mon];
+       tmp->tm_mday = (int) (days + 1);
+       tmp->tm_isdst = 0;
+#ifdef TM_GMTOFF
+       tmp->TM_GMTOFF = offset;
+#endif /* defined TM_GMTOFF */
+}
+
+char *
+ctime(timep)
+const time_t * const   timep;
+{
+/*
+** Section 4.12.3.2 of X3.159-1989 requires that
+**     The ctime function converts the calendar time pointed to by timer
+**     to local time in the form of a string.  It is equivalent to
+**             asctime(localtime(timer))
+*/
+       return asctime(localtime(timep));
+}
+
+char *
+ctime_r(timep, buf)
+const time_t * const   timep;
+char *                 buf;
+{
+       struct tm       tm;
+
+       return asctime_r(localtime_r(timep, &tm), buf);
+}
+
+/*
+** Adapted from code provided by Robert Elz, who writes:
+**     The "best" way to do mktime I think is based on an idea of Bob
+**     Kridle's (so its said...) from a long time ago.
+**     [kridle@xinet.com as of 1996-01-16.]
+**     It does a binary search of the time_t space.  Since time_t's are
+**     just 32 bits, its a max of 32 iterations (even at 64 bits it
+**     would still be very reasonable).
+*/
+
+#ifndef WRONG
+#define WRONG  (-1)
+#endif /* !defined WRONG */
+
+/*
+** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
+*/
+
+static int
+increment_overflow(number, delta)
+int *  number;
+int    delta;
+{
+       int     number0;
+
+       number0 = *number;
+       *number += delta;
+       return (*number < number0) != (delta < 0);
+}
+
+static int
+normalize_overflow(tensptr, unitsptr, base)
+int * const    tensptr;
+int * const    unitsptr;
+const int      base;
+{
+       register int    tensdelta;
+
+       tensdelta = (*unitsptr >= 0) ?
+               (*unitsptr / base) :
+               (-1 - (-1 - *unitsptr) / base);
+       *unitsptr -= tensdelta * base;
+       return increment_overflow(tensptr, tensdelta);
+}
+
+static int
+tmcomp(atmp, btmp)
+register const struct tm * const atmp;
+register const struct tm * const btmp;
+{
+       register int    result;
+
+       if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
+               (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+               (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
+               (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
+               (result = (atmp->tm_min - btmp->tm_min)) == 0)
+                       result = atmp->tm_sec - btmp->tm_sec;
+       return result;
+}
+
+static time_t
+time2sub(tmp, funcp, offset, okayp, do_norm_secs)
+struct tm * const      tmp;
+void (* const          funcp) P((const time_t*, long, struct tm*));
+const long             offset;
+int * const            okayp;
+const int              do_norm_secs;
+{
+       register const struct state *   sp;
+       register int                    dir;
+       register int                    bits;
+       register int                    i, j ;
+       register int                    saved_seconds;
+       time_t                          newt;
+       time_t                          t;
+       struct tm                       yourtm, mytm;
+
+       *okayp = FALSE;
+       yourtm = *tmp;
+       if (do_norm_secs) {
+               if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
+                       SECSPERMIN))
+                               return WRONG;
+       }
+       if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
+               return WRONG;
+       if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
+               return WRONG;
+       if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
+               return WRONG;
+       /*
+       ** Turn yourtm.tm_year into an actual year number for now.
+       ** It is converted back to an offset from TM_YEAR_BASE later.
+       */
+       if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
+               return WRONG;
+       while (yourtm.tm_mday <= 0) {
+               if (increment_overflow(&yourtm.tm_year, -1))
+                       return WRONG;
+               i = yourtm.tm_year + (1 < yourtm.tm_mon);
+               yourtm.tm_mday += year_lengths[isleap(i)];
+       }
+       while (yourtm.tm_mday > DAYSPERLYEAR) {
+               i = yourtm.tm_year + (1 < yourtm.tm_mon);
+               yourtm.tm_mday -= year_lengths[isleap(i)];
+               if (increment_overflow(&yourtm.tm_year, 1))
+                       return WRONG;
+       }
+       for ( ; ; ) {
+               i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
+               if (yourtm.tm_mday <= i)
+                       break;
+               yourtm.tm_mday -= i;
+               if (++yourtm.tm_mon >= MONSPERYEAR) {
+                       yourtm.tm_mon = 0;
+                       if (increment_overflow(&yourtm.tm_year, 1))
+                               return WRONG;
+               }
+       }
+       if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
+               return WRONG;
+       if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
+               saved_seconds = 0;
+       else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
+               /*
+               ** We can't set tm_sec to 0, because that might push the
+               ** time below the minimum representable time.
+               ** Set tm_sec to 59 instead.
+               ** This assumes that the minimum representable time is
+               ** not in the same minute that a leap second was deleted from,
+               ** which is a safer assumption than using 58 would be.
+               */
+               if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
+                       return WRONG;
+               saved_seconds = yourtm.tm_sec;
+               yourtm.tm_sec = SECSPERMIN - 1;
+       } else {
+               saved_seconds = yourtm.tm_sec;
+               yourtm.tm_sec = 0;
+       }
+       /*
+       ** Divide the search space in half
+       ** (this works whether time_t is signed or unsigned).
+       */
+       bits = TYPE_BIT(time_t) - 1;
+       /*
+       ** If time_t is signed, then 0 is just above the median,
+       ** assuming two's complement arithmetic.
+       ** If time_t is unsigned, then (1 << bits) is just above the median.
+       */
+       t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
+       for ( ; ; ) {
+               (*funcp)(&t, offset, &mytm);
+               dir = tmcomp(&mytm, &yourtm);
+               if (dir != 0) {
+                       if (bits-- < 0)
+                               return WRONG;
+                       if (bits < 0)
+                               --t; /* may be needed if new t is minimal */
+                       else if (dir > 0)
+                               t -= ((time_t) 1) << bits;
+                       else    t += ((time_t) 1) << bits;
+                       continue;
+               }
+               if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
+                       break;
+               /*
+               ** Right time, wrong type.
+               ** Hunt for right time, right type.
+               ** It's okay to guess wrong since the guess
+               ** gets checked.
+               */
+               /*
+               ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
+               */
+               sp = (const struct state *)
+                       (((void *) funcp == (void *) localsub) ?
+                       lclptr : gmtptr);
+#ifdef ALL_STATE
+               if (sp == NULL)
+                       return WRONG;
+#endif /* defined ALL_STATE */
+               for (i = sp->typecnt - 1; i >= 0; --i) {
+                       if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
+                               continue;
+                       for (j = sp->typecnt - 1; j >= 0; --j) {
+                               if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
+                                       continue;
+                               newt = t + sp->ttis[j].tt_gmtoff -
+                                       sp->ttis[i].tt_gmtoff;
+                               (*funcp)(&newt, offset, &mytm);
+                               if (tmcomp(&mytm, &yourtm) != 0)
+                                       continue;
+                               if (mytm.tm_isdst != yourtm.tm_isdst)
+                                       continue;
+                               /*
+                               ** We have a match.
+                               */
+                               t = newt;
+                               goto label;
+                       }
+               }
+               return WRONG;
+       }
+label:
+       newt = t + saved_seconds;
+       if ((newt < t) != (saved_seconds < 0))
+               return WRONG;
+       t = newt;
+       (*funcp)(&t, offset, tmp);
+       *okayp = TRUE;
+       return t;
+}
+
+static time_t
+time2(tmp, funcp, offset, okayp)
+struct tm * const      tmp;
+void (* const          funcp) P((const time_t*, long, struct tm*));
+const long             offset;
+int * const            okayp;
+{
+       time_t  t;
+
+       /*
+       ** First try without normalization of seconds
+       ** (in case tm_sec contains a value associated with a leap second).
+       ** If that fails, try with normalization of seconds.
+       */
+       t = time2sub(tmp, funcp, offset, okayp, FALSE);
+       return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
+}
+
+static time_t
+time1(tmp, funcp, offset)
+struct tm * const      tmp;
+void (* const          funcp) P((const time_t *, long, struct tm *));
+const long             offset;
+{
+       register time_t                 t;
+       register const struct state *   sp;
+       register int                    samei, otheri;
+       register int                    sameind, otherind;
+       register int                    i;
+       register int                    nseen;
+       int                             seen[TZ_MAX_TYPES];
+       int                             types[TZ_MAX_TYPES];
+       int                             okay;
+
+       if (tmp->tm_isdst > 1)
+               tmp->tm_isdst = 1;
+       t = time2(tmp, funcp, offset, &okay);
+#ifdef PCTS
+       /*
+       ** PCTS code courtesy Grant Sullivan (grant@osf.org).
+       */
+       if (okay)
+               return t;
+       if (tmp->tm_isdst < 0)
+               tmp->tm_isdst = 0;      /* reset to std and try again */
+#endif /* defined PCTS */
+#ifndef PCTS
+       if (okay || tmp->tm_isdst < 0)
+               return t;
+#endif /* !defined PCTS */
+       /*
+       ** We're supposed to assume that somebody took a time of one type
+       ** and did some math on it that yielded a "struct tm" that's bad.
+       ** We try to divine the type they started from and adjust to the
+       ** type they need.
+       */
+       /*
+       ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
+       */
+       sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
+               lclptr : gmtptr);
+#ifdef ALL_STATE
+       if (sp == NULL)
+               return WRONG;
+#endif /* defined ALL_STATE */
+       for (i = 0; i < sp->typecnt; ++i)
+               seen[i] = FALSE;
+       nseen = 0;
+       for (i = sp->timecnt - 1; i >= 0; --i)
+               if (!seen[sp->types[i]]) {
+                       seen[sp->types[i]] = TRUE;
+                       types[nseen++] = sp->types[i];
+               }
+       for (sameind = 0; sameind < nseen; ++sameind) {
+               samei = types[sameind];
+               if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
+                       continue;
+               for (otherind = 0; otherind < nseen; ++otherind) {
+                       otheri = types[otherind];
+                       if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
+                               continue;
+                       tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
+                                       sp->ttis[samei].tt_gmtoff;
+                       tmp->tm_isdst = !tmp->tm_isdst;
+                       t = time2(tmp, funcp, offset, &okay);
+                       if (okay)
+                               return t;
+                       tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
+                                       sp->ttis[samei].tt_gmtoff;
+                       tmp->tm_isdst = !tmp->tm_isdst;
+               }
+       }
+       return WRONG;
+}
+
+time_t
+mktime(tmp)
+struct tm * const      tmp;
+{
+       tzset();
+       return time1(tmp, localsub, 0L);
+}
+
+#ifdef STD_INSPIRED
+
+time_t
+timelocal(tmp)
+struct tm * const      tmp;
+{
+       tmp->tm_isdst = -1;     /* in case it wasn't initialized */
+       return mktime(tmp);
+}
+
+time_t
+timegm(tmp)
+struct tm * const      tmp;
+{
+       tmp->tm_isdst = 0;
+       return time1(tmp, gmtsub, 0L);
+}
+
+time_t
+timeoff(tmp, offset)
+struct tm * const      tmp;
+const long             offset;
+{
+       tmp->tm_isdst = 0;
+       return time1(tmp, gmtsub, offset);
+}
+
+#endif /* defined STD_INSPIRED */
+
+#ifdef CMUCS
+
+/*
+** The following is supplied for compatibility with
+** previous versions of the CMUCS runtime library.
+*/
+
+long
+gtime(tmp)
+struct tm * const      tmp;
+{
+       const time_t    t = mktime(tmp);
+
+       if (t == WRONG)
+               return -1;
+       return t;
+}
+
+#endif /* defined CMUCS */
+
+/*
+** XXX--is the below the right way to conditionalize??
+*/
+
+#ifdef STD_INSPIRED
+
+/*
+** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
+** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
+** is not the case if we are accounting for leap seconds.
+** So, we provide the following conversion routines for use
+** when exchanging timestamps with POSIX conforming systems.
+*/
+
+static long
+leapcorr(timep)
+time_t *       timep;
+{
+       register struct state *         sp;
+       register struct lsinfo *        lp;
+       register int                    i;
+
+       sp = lclptr;
+       i = sp->leapcnt;
+       while (--i >= 0) {
+               lp = &sp->lsis[i];
+               if (*timep >= lp->ls_trans)
+                       return lp->ls_corr;
+       }
+       return 0;
+}
+
+time_t
+time2posix(t)
+time_t t;
+{
+       tzset();
+       return t - leapcorr(&t);
+}
+
+time_t
+posix2time(t)
+time_t t;
+{
+       time_t  x;
+       time_t  y;
+
+       tzset();
+       /*
+       ** For a positive leap second hit, the result
+       ** is not unique.  For a negative leap second
+       ** hit, the corresponding time doesn't exist,
+       ** so we return an adjacent second.
+       */
+       x = t + leapcorr(&t);
+       y = x - leapcorr(&x);
+       if (y < t) {
+               do {
+                       x++;
+                       y = x - leapcorr(&x);
+               } while (y < t);
+               if (t != y)
+                       return x - 1;
+       } else if (y > t) {
+               do {
+                       --x;
+                       y = x - leapcorr(&x);
+               } while (y > t);
+               if (t != y)
+                       return x + 1;
+       }
+       return x;
+}
+
+#endif /* defined STD_INSPIRED */
index 17df71cbec9a84f3ef429d17ddf223ccad46f060..d30ac7aac3aece12180c0d2ad736941612866688 100644 (file)
@@ -1,8 +1,6 @@
 #include "postgres.h"
 
 #define NOID
-#define HAVE_SYMLINK 0
-#define HAVE_SYS_WAIT_H 0
 #define TZDIR pgwin32_TZDIR()
 
 char *pgwin32_TZDIR(void);
index 9333529bcc4445699604cb87aa5d3189f2c06845..c8f45486837f754d14f5974033afbca4d3a4a82a 100644 (file)
-#ifndef PRIVATE_H\r
-\r
-#define PRIVATE_H\r
-\r
-/*\r
-** This file is in the public domain, so clarified as of\r
-** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).\r
-*/\r
-\r
-/*\r
-** This header is for use ONLY with the time conversion code.\r
-** There is no guarantee that it will remain unchanged,\r
-** or that it will remain at all.\r
-** Do NOT copy it to any system include directory.\r
-** Thank you!\r
-*/\r
-\r
-/*\r
-** ID\r
-*/\r
-\r
-#ifndef lint\r
-#ifndef NOID\r
-static char    privatehid[] = "@(#)private.h   7.53";\r
-#endif /* !defined NOID */\r
-#endif /* !defined lint */\r
-\r
-/*\r
-** Defaults for preprocessor symbols.\r
-** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.\r
-*/\r
-\r
-#ifndef HAVE_ADJTIME\r
-#define HAVE_ADJTIME           1\r
-#endif /* !defined HAVE_ADJTIME */\r
-\r
-#ifndef HAVE_GETTEXT\r
-#define HAVE_GETTEXT           0\r
-#endif /* !defined HAVE_GETTEXT */\r
-\r
-#ifndef HAVE_INCOMPATIBLE_CTIME_R\r
-#define HAVE_INCOMPATIBLE_CTIME_R      0\r
-#endif /* !defined INCOMPATIBLE_CTIME_R */\r
-\r
-#ifndef HAVE_SETTIMEOFDAY\r
-#define HAVE_SETTIMEOFDAY      3\r
-#endif /* !defined HAVE_SETTIMEOFDAY */\r
-\r
-#ifndef HAVE_STRERROR\r
-#define HAVE_STRERROR          1\r
-#endif /* !defined HAVE_STRERROR */\r
-\r
-#ifndef HAVE_SYMLINK\r
-#define HAVE_SYMLINK           1\r
-#endif /* !defined HAVE_SYMLINK */\r
-\r
-#ifndef HAVE_SYS_STAT_H\r
-#define HAVE_SYS_STAT_H                1\r
-#endif /* !defined HAVE_SYS_STAT_H */\r
-\r
-#ifndef HAVE_SYS_WAIT_H\r
-#define HAVE_SYS_WAIT_H                1\r
-#endif /* !defined HAVE_SYS_WAIT_H */\r
-\r
-#ifndef HAVE_UNISTD_H\r
-#define HAVE_UNISTD_H          1\r
-#endif /* !defined HAVE_UNISTD_H */\r
-\r
-#ifndef HAVE_UTMPX_H\r
-#define HAVE_UTMPX_H           0\r
-#endif /* !defined HAVE_UTMPX_H */\r
-\r
-#ifndef LOCALE_HOME\r
-#define LOCALE_HOME            "/usr/lib/locale"\r
-#endif /* !defined LOCALE_HOME */\r
-\r
-#if HAVE_INCOMPATIBLE_CTIME_R\r
-#define asctime_r _incompatible_asctime_r\r
-#define ctime_r _incompatible_ctime_r\r
-#endif /* HAVE_INCOMPATIBLE_CTIME_R */\r
-\r
-/*\r
-** Nested includes\r
-*/\r
-\r
-#include "sys/types.h" /* for time_t */\r
-#include "stdio.h"\r
-#include "errno.h"\r
-#include "string.h"\r
-#include "limits.h"    /* for CHAR_BIT */\r
-#include "time.h"\r
-#include "stdlib.h"\r
-\r
-#if HAVE_GETTEXT - 0\r
-#include "libintl.h"\r
-#endif /* HAVE_GETTEXT - 0 */\r
-\r
-#if HAVE_SYS_WAIT_H - 0\r
-#include <sys/wait.h>  /* for WIFEXITED and WEXITSTATUS */\r
-#endif /* HAVE_SYS_WAIT_H - 0 */\r
-\r
-#ifndef WIFEXITED\r
-#define WIFEXITED(status)      (((status) & 0xff) == 0)\r
-#endif /* !defined WIFEXITED */\r
-#ifndef WEXITSTATUS\r
-#define WEXITSTATUS(status)    (((status) >> 8) & 0xff)\r
-#endif /* !defined WEXITSTATUS */\r
-\r
-#if HAVE_UNISTD_H - 0\r
-#include "unistd.h"    /* for F_OK and R_OK */\r
-#endif /* HAVE_UNISTD_H - 0 */\r
-\r
-#if !(HAVE_UNISTD_H - 0)\r
-#ifndef F_OK\r
-#define F_OK   0\r
-#endif /* !defined F_OK */\r
-#ifndef R_OK\r
-#define R_OK   4\r
-#endif /* !defined R_OK */\r
-#endif /* !(HAVE_UNISTD_H - 0) */\r
-\r
-/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX.  */\r
-#define is_digit(c) ((unsigned)(c) - '0' <= 9)\r
-\r
-/*\r
-** Workarounds for compilers/systems.\r
-*/\r
-\r
-/*\r
-** SunOS 4.1.1 cc lacks prototypes.\r
-*/\r
-\r
-#ifndef P\r
-#ifdef __STDC__\r
-#define P(x)   x\r
-#endif /* defined __STDC__ */\r
-#ifndef __STDC__\r
-#define P(x)   ()\r
-#endif /* !defined __STDC__ */\r
-#endif /* !defined P */\r
-\r
-/*\r
-** SunOS 4.1.1 headers lack EXIT_SUCCESS.\r
-*/\r
-\r
-#ifndef EXIT_SUCCESS\r
-#define EXIT_SUCCESS   0\r
-#endif /* !defined EXIT_SUCCESS */\r
-\r
-/*\r
-** SunOS 4.1.1 headers lack EXIT_FAILURE.\r
-*/\r
-\r
-#ifndef EXIT_FAILURE\r
-#define EXIT_FAILURE   1\r
-#endif /* !defined EXIT_FAILURE */\r
-\r
-/*\r
-** SunOS 4.1.1 headers lack FILENAME_MAX.\r
-*/\r
-\r
-#ifndef FILENAME_MAX\r
-\r
-#ifndef MAXPATHLEN\r
-#ifdef unix\r
-#include "sys/param.h"\r
-#endif /* defined unix */\r
-#endif /* !defined MAXPATHLEN */\r
-\r
-#ifdef MAXPATHLEN\r
-#define FILENAME_MAX   MAXPATHLEN\r
-#endif /* defined MAXPATHLEN */\r
-#ifndef MAXPATHLEN\r
-#define FILENAME_MAX   1024            /* Pure guesswork */\r
-#endif /* !defined MAXPATHLEN */\r
-\r
-#endif /* !defined FILENAME_MAX */\r
-\r
-/*\r
-** SunOS 4.1.1 libraries lack remove.\r
-*/\r
-\r
-#ifndef remove\r
-extern int     unlink P((const char * filename));\r
-#define remove unlink\r
-#endif /* !defined remove */\r
-\r
-/*\r
-** Some ancient errno.h implementations don't declare errno.\r
-** But some newer errno.h implementations define it as a macro.\r
-** Fix the former without affecting the latter.\r
-*/\r
-#ifndef errno\r
-extern int errno;\r
-#endif /* !defined errno */\r
-\r
-/*\r
-** Private function declarations.\r
-*/\r
-char * icalloc P((int nelem, int elsize));\r
-char * icatalloc P((char * old, const char * new));\r
-char * icpyalloc P((const char * string));\r
-char * imalloc P((int n));\r
-void * irealloc P((void * pointer, int size));\r
-void   icfree P((char * pointer));\r
-void   ifree P((char * pointer));\r
-char * scheck P((const char *string, const char *format));\r
-\r
-\r
-/*\r
-** Finally, some convenience items.\r
-*/\r
-\r
-#ifndef TRUE\r
-#define TRUE   1\r
-#endif /* !defined TRUE */\r
-\r
-#ifndef FALSE\r
-#define FALSE  0\r
-#endif /* !defined FALSE */\r
-\r
-#ifndef TYPE_BIT\r
-#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)\r
-#endif /* !defined TYPE_BIT */\r
-\r
-#ifndef TYPE_SIGNED\r
-#define TYPE_SIGNED(type) (((type) -1) < 0)\r
-#endif /* !defined TYPE_SIGNED */\r
-\r
-#ifndef INT_STRLEN_MAXIMUM\r
-/*\r
-** 302 / 1000 is log10(2.0) rounded up.\r
-** Subtract one for the sign bit if the type is signed;\r
-** add one for integer division truncation;\r
-** add one more for a minus sign if the type is signed.\r
-*/\r
-#define INT_STRLEN_MAXIMUM(type) \\r
-    ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))\r
-#endif /* !defined INT_STRLEN_MAXIMUM */\r
-\r
-/*\r
-** INITIALIZE(x)\r
-*/\r
-\r
-#ifndef GNUC_or_lint\r
-#ifdef lint\r
-#define GNUC_or_lint\r
-#endif /* defined lint */\r
-#ifndef lint\r
-#ifdef __GNUC__\r
-#define GNUC_or_lint\r
-#endif /* defined __GNUC__ */\r
-#endif /* !defined lint */\r
-#endif /* !defined GNUC_or_lint */\r
-\r
-#ifndef INITIALIZE\r
-#ifdef GNUC_or_lint\r
-#define INITIALIZE(x)  ((x) = 0)\r
-#endif /* defined GNUC_or_lint */\r
-#ifndef GNUC_or_lint\r
-#define INITIALIZE(x)\r
-#endif /* !defined GNUC_or_lint */\r
-#endif /* !defined INITIALIZE */\r
-\r
-/*\r
-** For the benefit of GNU folk...\r
-** `_(MSGID)' uses the current locale's message library string for MSGID.\r
-** The default is to use gettext if available, and use MSGID otherwise.\r
-*/\r
-\r
-#ifndef _\r
-#if HAVE_GETTEXT - 0\r
-#define _(msgid) gettext(msgid)\r
-#else /* !(HAVE_GETTEXT - 0) */\r
-#define _(msgid) msgid\r
-#endif /* !(HAVE_GETTEXT - 0) */\r
-#endif /* !defined _ */\r
-\r
-#ifndef TZ_DOMAIN\r
-#define TZ_DOMAIN "tz"\r
-#endif /* !defined TZ_DOMAIN */\r
-\r
-#if HAVE_INCOMPATIBLE_CTIME_R\r
-#undef asctime_r\r
-#undef ctime_r\r
-char *asctime_r P((struct tm const *, char *));\r
-char *ctime_r P((time_t const *, char *));\r
-#endif /* HAVE_INCOMPATIBLE_CTIME_R */\r
-\r
-/*\r
-** UNIX was a registered trademark of The Open Group in 2003.\r
-*/\r
-\r
-#endif /* !defined PRIVATE_H */\r
+#ifndef PRIVATE_H
+
+#define PRIVATE_H
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** ID
+*/
+
+#ifndef lint
+#ifndef NOID
+static char    privatehid[] = "@(#)private.h   7.53";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*
+** Defaults for preprocessor symbols.
+** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
+*/
+
+#ifndef HAVE_ADJTIME
+#define HAVE_ADJTIME           1
+#endif /* !defined HAVE_ADJTIME */
+
+#ifndef HAVE_GETTEXT
+#define HAVE_GETTEXT           0
+#endif /* !defined HAVE_GETTEXT */
+
+#ifndef HAVE_INCOMPATIBLE_CTIME_R
+#define HAVE_INCOMPATIBLE_CTIME_R      0
+#endif /* !defined INCOMPATIBLE_CTIME_R */
+
+#ifndef HAVE_SETTIMEOFDAY
+#define HAVE_SETTIMEOFDAY      3
+#endif /* !defined HAVE_SETTIMEOFDAY */
+
+#ifndef HAVE_STRERROR
+#define HAVE_STRERROR          1
+#endif /* !defined HAVE_STRERROR */
+
+#ifndef HAVE_SYMLINK
+#define HAVE_SYMLINK           1
+#endif /* !defined HAVE_SYMLINK */
+
+#ifndef HAVE_SYS_STAT_H
+#define HAVE_SYS_STAT_H                1
+#endif /* !defined HAVE_SYS_STAT_H */
+
+#ifndef HAVE_SYS_WAIT_H
+#define HAVE_SYS_WAIT_H                1
+#endif /* !defined HAVE_SYS_WAIT_H */
+
+#ifndef HAVE_UNISTD_H
+#define HAVE_UNISTD_H          1
+#endif /* !defined HAVE_UNISTD_H */
+
+#ifndef HAVE_UTMPX_H
+#define HAVE_UTMPX_H           0
+#endif /* !defined HAVE_UTMPX_H */
+
+#ifndef LOCALE_HOME
+#define LOCALE_HOME            "/usr/lib/locale"
+#endif /* !defined LOCALE_HOME */
+
+#if HAVE_INCOMPATIBLE_CTIME_R
+#define asctime_r _incompatible_asctime_r
+#define ctime_r _incompatible_ctime_r
+#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
+/*
+** Nested includes
+*/
+
+#include "sys/types.h" /* for time_t */
+#include "stdio.h"
+#include "errno.h"
+#include "string.h"
+#include "limits.h"    /* for CHAR_BIT */
+#include "time.h"
+#include "stdlib.h"
+
+#if HAVE_GETTEXT - 0
+#include "libintl.h"
+#endif /* HAVE_GETTEXT - 0 */
+
+#if HAVE_SYS_WAIT_H - 0
+#include <sys/wait.h>  /* for WIFEXITED and WEXITSTATUS */
+#endif /* HAVE_SYS_WAIT_H - 0 */
+
+#ifndef WIFEXITED
+#define WIFEXITED(status)      (((status) & 0xff) == 0)
+#endif /* !defined WIFEXITED */
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(status)    (((status) >> 8) & 0xff)
+#endif /* !defined WEXITSTATUS */
+
+#if HAVE_UNISTD_H - 0
+#include "unistd.h"    /* for F_OK and R_OK */
+#endif /* HAVE_UNISTD_H - 0 */
+
+#if !(HAVE_UNISTD_H - 0)
+#ifndef F_OK
+#define F_OK   0
+#endif /* !defined F_OK */
+#ifndef R_OK
+#define R_OK   4
+#endif /* !defined R_OK */
+#endif /* !(HAVE_UNISTD_H - 0) */
+
+/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX.  */
+#define is_digit(c) ((unsigned)(c) - '0' <= 9)
+
+/*
+** Workarounds for compilers/systems.
+*/
+
+/*
+** SunOS 4.1.1 cc lacks prototypes.
+*/
+
+#ifndef P
+#ifdef __STDC__
+#define P(x)   x
+#endif /* defined __STDC__ */
+#ifndef __STDC__
+#define P(x)   ()
+#endif /* !defined __STDC__ */
+#endif /* !defined P */
+
+/*
+** SunOS 4.1.1 headers lack EXIT_SUCCESS.
+*/
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS   0
+#endif /* !defined EXIT_SUCCESS */
+
+/*
+** SunOS 4.1.1 headers lack EXIT_FAILURE.
+*/
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE   1
+#endif /* !defined EXIT_FAILURE */
+
+/*
+** SunOS 4.1.1 headers lack FILENAME_MAX.
+*/
+
+#ifndef FILENAME_MAX
+
+#ifndef MAXPATHLEN
+#ifdef unix
+#include "sys/param.h"
+#endif /* defined unix */
+#endif /* !defined MAXPATHLEN */
+
+#ifdef MAXPATHLEN
+#define FILENAME_MAX   MAXPATHLEN
+#endif /* defined MAXPATHLEN */
+#ifndef MAXPATHLEN
+#define FILENAME_MAX   1024            /* Pure guesswork */
+#endif /* !defined MAXPATHLEN */
+
+#endif /* !defined FILENAME_MAX */
+
+/*
+** SunOS 4.1.1 libraries lack remove.
+*/
+
+#ifndef remove
+extern int     unlink P((const char * filename));
+#define remove unlink
+#endif /* !defined remove */
+
+/*
+** Some ancient errno.h implementations don't declare errno.
+** But some newer errno.h implementations define it as a macro.
+** Fix the former without affecting the latter.
+*/
+#ifndef errno
+extern int errno;
+#endif /* !defined errno */
+
+/*
+** Private function declarations.
+*/
+char * icalloc P((int nelem, int elsize));
+char * icatalloc P((char * old, const char * new));
+char * icpyalloc P((const char * string));
+char * imalloc P((int n));
+void * irealloc P((void * pointer, int size));
+void   icfree P((char * pointer));
+void   ifree P((char * pointer));
+char * scheck P((const char *string, const char *format));
+
+
+/*
+** Finally, some convenience items.
+*/
+
+#ifndef TRUE
+#define TRUE   1
+#endif /* !defined TRUE */
+
+#ifndef FALSE
+#define FALSE  0
+#endif /* !defined FALSE */
+
+#ifndef TYPE_BIT
+#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
+#endif /* !defined TYPE_BIT */
+
+#ifndef TYPE_SIGNED
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+#endif /* !defined TYPE_SIGNED */
+
+#ifndef INT_STRLEN_MAXIMUM
+/*
+** 302 / 1000 is log10(2.0) rounded up.
+** Subtract one for the sign bit if the type is signed;
+** add one for integer division truncation;
+** add one more for a minus sign if the type is signed.
+*/
+#define INT_STRLEN_MAXIMUM(type) \
+    ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
+#endif /* !defined INT_STRLEN_MAXIMUM */
+
+/*
+** INITIALIZE(x)
+*/
+
+#ifndef GNUC_or_lint
+#ifdef lint
+#define GNUC_or_lint
+#endif /* defined lint */
+#ifndef lint
+#ifdef __GNUC__
+#define GNUC_or_lint
+#endif /* defined __GNUC__ */
+#endif /* !defined lint */
+#endif /* !defined GNUC_or_lint */
+
+#ifndef INITIALIZE
+#ifdef GNUC_or_lint
+#define INITIALIZE(x)  ((x) = 0)
+#endif /* defined GNUC_or_lint */
+#ifndef GNUC_or_lint
+#define INITIALIZE(x)
+#endif /* !defined GNUC_or_lint */
+#endif /* !defined INITIALIZE */
+
+/*
+** For the benefit of GNU folk...
+** `_(MSGID)' uses the current locale's message library string for MSGID.
+** The default is to use gettext if available, and use MSGID otherwise.
+*/
+
+#ifndef _
+#if HAVE_GETTEXT - 0
+#define _(msgid) gettext(msgid)
+#else /* !(HAVE_GETTEXT - 0) */
+#define _(msgid) msgid
+#endif /* !(HAVE_GETTEXT - 0) */
+#endif /* !defined _ */
+
+#ifndef TZ_DOMAIN
+#define TZ_DOMAIN "tz"
+#endif /* !defined TZ_DOMAIN */
+
+#if HAVE_INCOMPATIBLE_CTIME_R
+#undef asctime_r
+#undef ctime_r
+char *asctime_r P((struct tm const *, char *));
+char *ctime_r P((time_t const *, char *));
+#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
+/*
+** UNIX was a registered trademark of The Open Group in 2003.
+*/
+
+#endif /* !defined PRIVATE_H */
index 6bcfe87950a3e2bced544da695fe7be64ed9a622..39feeba701171ca6def94627ecb04016866efb2c 100644 (file)
@@ -1,59 +1,59 @@
-#ifndef lint\r
-#ifndef NOID\r
-static char    elsieid[] = "@(#)scheck.c       8.15";\r
-#endif /* !defined lint */\r
-#endif /* !defined NOID */\r
-\r
-/*LINTLIBRARY*/\r
-\r
-#include "private.h"\r
-\r
-char *\r
-scheck(string, format)\r
-const char * const     string;\r
-const char * const     format;\r
-{\r
-       register char *         fbuf;\r
-       register const char *   fp;\r
-       register char *         tp;\r
-       register int            c;\r
-       register char *         result;\r
-       char                    dummy;\r
-       static char             nada;\r
-\r
-       result = &nada;\r
-       if (string == NULL || format == NULL)\r
-               return result;\r
-       fbuf = imalloc((int) (2 * strlen(format) + 4));\r
-       if (fbuf == NULL)\r
-               return result;\r
-       fp = format;\r
-       tp = fbuf;\r
-       while ((*tp++ = c = *fp++) != '\0') {\r
-               if (c != '%')\r
-                       continue;\r
-               if (*fp == '%') {\r
-                       *tp++ = *fp++;\r
-                       continue;\r
-               }\r
-               *tp++ = '*';\r
-               if (*fp == '*')\r
-                       ++fp;\r
-               while (is_digit(*fp))\r
-                       *tp++ = *fp++;\r
-               if (*fp == 'l' || *fp == 'h')\r
-                       *tp++ = *fp++;\r
-               else if (*fp == '[')\r
-                       do *tp++ = *fp++;\r
-                               while (*fp != '\0' && *fp != ']');\r
-               if ((*tp++ = *fp++) == '\0')\r
-                       break;\r
-       }\r
-       *(tp - 1) = '%';\r
-       *tp++ = 'c';\r
-       *tp = '\0';\r
-       if (sscanf(string, fbuf, &dummy) != 1)\r
-               result = (char *) format;\r
-       ifree(fbuf);\r
-       return result;\r
-}\r
+#ifndef lint
+#ifndef NOID
+static char    elsieid[] = "@(#)scheck.c       8.15";
+#endif /* !defined lint */
+#endif /* !defined NOID */
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+
+char *
+scheck(string, format)
+const char * const     string;
+const char * const     format;
+{
+       register char *         fbuf;
+       register const char *   fp;
+       register char *         tp;
+       register int            c;
+       register char *         result;
+       char                    dummy;
+       static char             nada;
+
+       result = &nada;
+       if (string == NULL || format == NULL)
+               return result;
+       fbuf = imalloc((int) (2 * strlen(format) + 4));
+       if (fbuf == NULL)
+               return result;
+       fp = format;
+       tp = fbuf;
+       while ((*tp++ = c = *fp++) != '\0') {
+               if (c != '%')
+                       continue;
+               if (*fp == '%') {
+                       *tp++ = *fp++;
+                       continue;
+               }
+               *tp++ = '*';
+               if (*fp == '*')
+                       ++fp;
+               while (is_digit(*fp))
+                       *tp++ = *fp++;
+               if (*fp == 'l' || *fp == 'h')
+                       *tp++ = *fp++;
+               else if (*fp == '[')
+                       do *tp++ = *fp++;
+                               while (*fp != '\0' && *fp != ']');
+               if ((*tp++ = *fp++) == '\0')
+                       break;
+       }
+       *(tp - 1) = '%';
+       *tp++ = 'c';
+       *tp = '\0';
+       if (sscanf(string, fbuf, &dummy) != 1)
+               result = (char *) format;
+       ifree(fbuf);
+       return result;
+}
index 2d07a867e2f014fe1d0fd8d3108a803225240e2b..0921c3c3396e8116ff749f3c8116011d09e00202 100644 (file)
-#ifndef TZFILE_H\r
-\r
-#define TZFILE_H\r
-\r
-/*\r
-** This file is in the public domain, so clarified as of\r
-** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).\r
-*/\r
-\r
-/*\r
-** This header is for use ONLY with the time conversion code.\r
-** There is no guarantee that it will remain unchanged,\r
-** or that it will remain at all.\r
-** Do NOT copy it to any system include directory.\r
-** Thank you!\r
-*/\r
-\r
-/*\r
-** ID\r
-*/\r
-\r
-#ifndef lint\r
-#ifndef NOID\r
-static char    tzfilehid[] = "@(#)tzfile.h     7.14";\r
-#endif /* !defined NOID */\r
-#endif /* !defined lint */\r
-\r
-/*\r
-** Information about time zone files.\r
-*/\r
-\r
-#ifndef TZDIR\r
-#define TZDIR  "/usr/local/etc/zoneinfo" /* Time zone object file directory */\r
-#endif /* !defined TZDIR */\r
-\r
-#ifndef TZDEFAULT\r
-#define TZDEFAULT      "localtime"\r
-#endif /* !defined TZDEFAULT */\r
-\r
-#ifndef TZDEFRULES\r
-#define TZDEFRULES     "posixrules"\r
-#endif /* !defined TZDEFRULES */\r
-\r
-/*\r
-** Each file begins with. . .\r
-*/\r
-\r
-#define        TZ_MAGIC        "TZif"\r
-\r
-struct tzhead {\r
-       char    tzh_magic[4];           /* TZ_MAGIC */\r
-       char    tzh_reserved[16];       /* reserved for future use */\r
-       char    tzh_ttisgmtcnt[4];      /* coded number of trans. time flags */\r
-       char    tzh_ttisstdcnt[4];      /* coded number of trans. time flags */\r
-       char    tzh_leapcnt[4];         /* coded number of leap seconds */\r
-       char    tzh_timecnt[4];         /* coded number of transition times */\r
-       char    tzh_typecnt[4];         /* coded number of local time types */\r
-       char    tzh_charcnt[4];         /* coded number of abbr. chars */\r
-};\r
-\r
-/*\r
-** . . .followed by. . .\r
-**\r
-**     tzh_timecnt (char [4])s         coded transition times a la time(2)\r
-**     tzh_timecnt (unsigned char)s    types of local time starting at above\r
-**     tzh_typecnt repetitions of\r
-**             one (char [4])          coded UTC offset in seconds\r
-**             one (unsigned char)     used to set tm_isdst\r
-**             one (unsigned char)     that's an abbreviation list index\r
-**     tzh_charcnt (char)s             '\0'-terminated zone abbreviations\r
-**     tzh_leapcnt repetitions of\r
-**             one (char [4])          coded leap second transition times\r
-**             one (char [4])          total correction after above\r
-**     tzh_ttisstdcnt (char)s          indexed by type; if TRUE, transition\r
-**                                     time is standard time, if FALSE,\r
-**                                     transition time is wall clock time\r
-**                                     if absent, transition times are\r
-**                                     assumed to be wall clock time\r
-**     tzh_ttisgmtcnt (char)s          indexed by type; if TRUE, transition\r
-**                                     time is UTC, if FALSE,\r
-**                                     transition time is local time\r
-**                                     if absent, transition times are\r
-**                                     assumed to be local time\r
-*/\r
-\r
-/*\r
-** In the current implementation, "tzset()" refuses to deal with files that\r
-** exceed any of the limits below.\r
-*/\r
-\r
-#ifndef TZ_MAX_TIMES\r
-/*\r
-** The TZ_MAX_TIMES value below is enough to handle a bit more than a\r
-** year's worth of solar time (corrected daily to the nearest second) or\r
-** 138 years of Pacific Presidential Election time\r
-** (where there are three time zone transitions every fourth year).\r
-*/\r
-#define TZ_MAX_TIMES   370\r
-#endif /* !defined TZ_MAX_TIMES */\r
-\r
-#ifndef TZ_MAX_TYPES\r
-#ifndef NOSOLAR\r
-#define TZ_MAX_TYPES   256 /* Limited by what (unsigned char)'s can hold */\r
-#endif /* !defined NOSOLAR */\r
-#ifdef NOSOLAR\r
-/*\r
-** Must be at least 14 for Europe/Riga as of Jan 12 1995,\r
-** as noted by Earl Chew <earl@hpato.aus.hp.com>.\r
-*/\r
-#define TZ_MAX_TYPES   20      /* Maximum number of local time types */\r
-#endif /* !defined NOSOLAR */\r
-#endif /* !defined TZ_MAX_TYPES */\r
-\r
-#ifndef TZ_MAX_CHARS\r
-#define TZ_MAX_CHARS   50      /* Maximum number of abbreviation characters */\r
-                               /* (limited by what unsigned chars can hold) */\r
-#endif /* !defined TZ_MAX_CHARS */\r
-\r
-#ifndef TZ_MAX_LEAPS\r
-#define TZ_MAX_LEAPS   50      /* Maximum number of leap second corrections */\r
-#endif /* !defined TZ_MAX_LEAPS */\r
-\r
-#define SECSPERMIN     60\r
-#define MINSPERHOUR    60\r
-#define HOURSPERDAY    24\r
-#define DAYSPERWEEK    7\r
-#define DAYSPERNYEAR   365\r
-#define DAYSPERLYEAR   366\r
-#define SECSPERHOUR    (SECSPERMIN * MINSPERHOUR)\r
-#define SECSPERDAY     ((long) SECSPERHOUR * HOURSPERDAY)\r
-#define MONSPERYEAR    12\r
-\r
-#define TM_SUNDAY      0\r
-#define TM_MONDAY      1\r
-#define TM_TUESDAY     2\r
-#define TM_WEDNESDAY   3\r
-#define TM_THURSDAY    4\r
-#define TM_FRIDAY      5\r
-#define TM_SATURDAY    6\r
-\r
-#define TM_JANUARY     0\r
-#define TM_FEBRUARY    1\r
-#define TM_MARCH       2\r
-#define TM_APRIL       3\r
-#define TM_MAY         4\r
-#define TM_JUNE                5\r
-#define TM_JULY                6\r
-#define TM_AUGUST      7\r
-#define TM_SEPTEMBER   8\r
-#define TM_OCTOBER     9\r
-#define TM_NOVEMBER    10\r
-#define TM_DECEMBER    11\r
-\r
-#define TM_YEAR_BASE   1900\r
-\r
-#define EPOCH_YEAR     1970\r
-#define EPOCH_WDAY     TM_THURSDAY\r
-\r
-/*\r
-** Accurate only for the past couple of centuries;\r
-** that will probably do.\r
-*/\r
-\r
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))\r
-\r
-#ifndef USG\r
-\r
-/*\r
-** Use of the underscored variants may cause problems if you move your code to\r
-** certain System-V-based systems; for maximum portability, use the\r
-** underscore-free variants.  The underscored variants are provided for\r
-** backward compatibility only; they may disappear from future versions of\r
-** this file.\r
-*/\r
-\r
-#define SECS_PER_MIN   SECSPERMIN\r
-#define MINS_PER_HOUR  MINSPERHOUR\r
-#define HOURS_PER_DAY  HOURSPERDAY\r
-#define DAYS_PER_WEEK  DAYSPERWEEK\r
-#define DAYS_PER_NYEAR DAYSPERNYEAR\r
-#define DAYS_PER_LYEAR DAYSPERLYEAR\r
-#define SECS_PER_HOUR  SECSPERHOUR\r
-#define SECS_PER_DAY   SECSPERDAY\r
-#define MONS_PER_YEAR  MONSPERYEAR\r
-\r
-#endif /* !defined USG */\r
-\r
-#endif /* !defined TZFILE_H */\r
+#ifndef TZFILE_H
+
+#define TZFILE_H
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** ID
+*/
+
+#ifndef lint
+#ifndef NOID
+static char    tzfilehid[] = "@(#)tzfile.h     7.14";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+/*
+** Information about time zone files.
+*/
+
+#ifndef TZDIR
+#define TZDIR  "/usr/local/etc/zoneinfo" /* Time zone object file directory */
+#endif /* !defined TZDIR */
+
+#ifndef TZDEFAULT
+#define TZDEFAULT      "localtime"
+#endif /* !defined TZDEFAULT */
+
+#ifndef TZDEFRULES
+#define TZDEFRULES     "posixrules"
+#endif /* !defined TZDEFRULES */
+
+/*
+** Each file begins with. . .
+*/
+
+#define        TZ_MAGIC        "TZif"
+
+struct tzhead {
+       char    tzh_magic[4];           /* TZ_MAGIC */
+       char    tzh_reserved[16];       /* reserved for future use */
+       char    tzh_ttisgmtcnt[4];      /* coded number of trans. time flags */
+       char    tzh_ttisstdcnt[4];      /* coded number of trans. time flags */
+       char    tzh_leapcnt[4];         /* coded number of leap seconds */
+       char    tzh_timecnt[4];         /* coded number of transition times */
+       char    tzh_typecnt[4];         /* coded number of local time types */
+       char    tzh_charcnt[4];         /* coded number of abbr. chars */
+};
+
+/*
+** . . .followed by. . .
+**
+**     tzh_timecnt (char [4])s         coded transition times a la time(2)
+**     tzh_timecnt (unsigned char)s    types of local time starting at above
+**     tzh_typecnt repetitions of
+**             one (char [4])          coded UTC offset in seconds
+**             one (unsigned char)     used to set tm_isdst
+**             one (unsigned char)     that's an abbreviation list index
+**     tzh_charcnt (char)s             '\0'-terminated zone abbreviations
+**     tzh_leapcnt repetitions of
+**             one (char [4])          coded leap second transition times
+**             one (char [4])          total correction after above
+**     tzh_ttisstdcnt (char)s          indexed by type; if TRUE, transition
+**                                     time is standard time, if FALSE,
+**                                     transition time is wall clock time
+**                                     if absent, transition times are
+**                                     assumed to be wall clock time
+**     tzh_ttisgmtcnt (char)s          indexed by type; if TRUE, transition
+**                                     time is UTC, if FALSE,
+**                                     transition time is local time
+**                                     if absent, transition times are
+**                                     assumed to be local time
+*/
+
+/*
+** In the current implementation, "tzset()" refuses to deal with files that
+** exceed any of the limits below.
+*/
+
+#ifndef TZ_MAX_TIMES
+/*
+** The TZ_MAX_TIMES value below is enough to handle a bit more than a
+** year's worth of solar time (corrected daily to the nearest second) or
+** 138 years of Pacific Presidential Election time
+** (where there are three time zone transitions every fourth year).
+*/
+#define TZ_MAX_TIMES   370
+#endif /* !defined TZ_MAX_TIMES */
+
+#ifndef TZ_MAX_TYPES
+#ifndef NOSOLAR
+#define TZ_MAX_TYPES   256 /* Limited by what (unsigned char)'s can hold */
+#endif /* !defined NOSOLAR */
+#ifdef NOSOLAR
+/*
+** Must be at least 14 for Europe/Riga as of Jan 12 1995,
+** as noted by Earl Chew <earl@hpato.aus.hp.com>.
+*/
+#define TZ_MAX_TYPES   20      /* Maximum number of local time types */
+#endif /* !defined NOSOLAR */
+#endif /* !defined TZ_MAX_TYPES */
+
+#ifndef TZ_MAX_CHARS
+#define TZ_MAX_CHARS   50      /* Maximum number of abbreviation characters */
+                               /* (limited by what unsigned chars can hold) */
+#endif /* !defined TZ_MAX_CHARS */
+
+#ifndef TZ_MAX_LEAPS
+#define TZ_MAX_LEAPS   50      /* Maximum number of leap second corrections */
+#endif /* !defined TZ_MAX_LEAPS */
+
+#define SECSPERMIN     60
+#define MINSPERHOUR    60
+#define HOURSPERDAY    24
+#define DAYSPERWEEK    7
+#define DAYSPERNYEAR   365
+#define DAYSPERLYEAR   366
+#define SECSPERHOUR    (SECSPERMIN * MINSPERHOUR)
+#define SECSPERDAY     ((long) SECSPERHOUR * HOURSPERDAY)
+#define MONSPERYEAR    12
+
+#define TM_SUNDAY      0
+#define TM_MONDAY      1
+#define TM_TUESDAY     2
+#define TM_WEDNESDAY   3
+#define TM_THURSDAY    4
+#define TM_FRIDAY      5
+#define TM_SATURDAY    6
+
+#define TM_JANUARY     0
+#define TM_FEBRUARY    1
+#define TM_MARCH       2
+#define TM_APRIL       3
+#define TM_MAY         4
+#define TM_JUNE                5
+#define TM_JULY                6
+#define TM_AUGUST      7
+#define TM_SEPTEMBER   8
+#define TM_OCTOBER     9
+#define TM_NOVEMBER    10
+#define TM_DECEMBER    11
+
+#define TM_YEAR_BASE   1900
+
+#define EPOCH_YEAR     1970
+#define EPOCH_WDAY     TM_THURSDAY
+
+/*
+** Accurate only for the past couple of centuries;
+** that will probably do.
+*/
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
+#ifndef USG
+
+/*
+** Use of the underscored variants may cause problems if you move your code to
+** certain System-V-based systems; for maximum portability, use the
+** underscore-free variants.  The underscored variants are provided for
+** backward compatibility only; they may disappear from future versions of
+** this file.
+*/
+
+#define SECS_PER_MIN   SECSPERMIN
+#define MINS_PER_HOUR  MINSPERHOUR
+#define HOURS_PER_DAY  HOURSPERDAY
+#define DAYS_PER_WEEK  DAYSPERWEEK
+#define DAYS_PER_NYEAR DAYSPERNYEAR
+#define DAYS_PER_LYEAR DAYSPERLYEAR
+#define SECS_PER_HOUR  SECSPERHOUR
+#define SECS_PER_DAY   SECSPERDAY
+#define MONS_PER_YEAR  MONSPERYEAR
+
+#endif /* !defined USG */
+
+#endif /* !defined TZFILE_H */
index ec187addf3d061074646e76c319baf7366696f89..21d665c7150276d63666ae135463db6cd1bc6f7f 100644 (file)
-static char    elsieid[] = "@(#)zic.c  7.115";\r
-#include "pgtz.h"\r
-#undef unlink\r
-#undef TZDIR\r
-#define TZDIR "data"\r
-#ifdef WIN32\r
-#include <windows.h>\r
-#endif\r
-\r
-#include "private.h"\r
-#include "locale.h"\r
-#include "tzfile.h"\r
-\r
-#if HAVE_SYS_STAT_H\r
-#include "sys/stat.h"\r
-#endif\r
-#ifndef WIN32\r
-#ifdef S_IRUSR\r
-#define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)\r
-#else\r
-#define MKDIR_UMASK 0755\r
-#endif\r
-#endif\r
-\r
-/*\r
-** On some ancient hosts, predicates like `isspace(C)' are defined\r
-** only if isascii(C) || C == EOF.  Modern hosts obey the C Standard,\r
-** which says they are defined only if C == ((unsigned char) C) || C == EOF.\r
-** Neither the C Standard nor Posix require that `isascii' exist.\r
-** For portability, we check both ancient and modern requirements.\r
-** If isascii is not defined, the isascii check succeeds trivially.\r
-*/\r
-#include "ctype.h"\r
-#ifndef isascii\r
-#define isascii(x) 1\r
-#endif\r
-\r
-struct rule {\r
-       const char *    r_filename;\r
-       int             r_linenum;\r
-       const char *    r_name;\r
-\r
-       int             r_loyear;       /* for example, 1986 */\r
-       int             r_hiyear;       /* for example, 1986 */\r
-       const char *    r_yrtype;\r
-\r
-       int             r_month;        /* 0..11 */\r
-\r
-       int             r_dycode;       /* see below */\r
-       int             r_dayofmonth;\r
-       int             r_wday;\r
-\r
-       long            r_tod;          /* time from midnight */\r
-       int             r_todisstd;     /* above is standard time if TRUE */\r
-                                       /* or wall clock time if FALSE */\r
-       int             r_todisgmt;     /* above is GMT if TRUE */\r
-                                       /* or local time if FALSE */\r
-       long            r_stdoff;       /* offset from standard time */\r
-       const char *    r_abbrvar;      /* variable part of abbreviation */\r
-\r
-       int             r_todo;         /* a rule to do (used in outzone) */\r
-       time_t          r_temp;         /* used in outzone */\r
-};\r
-\r
-/*\r
-**     r_dycode                r_dayofmonth    r_wday\r
-*/\r
-\r
-#define DC_DOM         0       /* 1..31 */     /* unused */\r
-#define DC_DOWGEQ      1       /* 1..31 */     /* 0..6 (Sun..Sat) */\r
-#define DC_DOWLEQ      2       /* 1..31 */     /* 0..6 (Sun..Sat) */\r
-\r
-struct zone {\r
-       const char *    z_filename;\r
-       int             z_linenum;\r
-\r
-       const char *    z_name;\r
-       long            z_gmtoff;\r
-       const char *    z_rule;\r
-       const char *    z_format;\r
-\r
-       long            z_stdoff;\r
-\r
-       struct rule *   z_rules;\r
-       int             z_nrules;\r
-\r
-       struct rule     z_untilrule;\r
-       time_t          z_untiltime;\r
-};\r
-\r
-extern int     getopt P((int argc, char * const argv[],\r
-                       const char * options));\r
-extern int     link P((const char * fromname, const char * toname));\r
-extern char *  optarg;\r
-extern int     optind;\r
-\r
-static void    addtt P((time_t starttime, int type));\r
-static int     addtype P((long gmtoff, const char * abbr, int isdst,\r
-                               int ttisstd, int ttisgmt));\r
-static void    leapadd P((time_t t, int positive, int rolling, int count));\r
-static void    adjleap P((void));\r
-static void    associate P((void));\r
-static int     ciequal P((const char * ap, const char * bp));\r
-static void    convert P((long val, char * buf));\r
-static void    dolink P((const char * fromfile, const char * tofile));\r
-static void    doabbr P((char * abbr, const char * format,\r
-                       const char * letters, int isdst));\r
-static void    eat P((const char * name, int num));\r
-static void    eats P((const char * name, int num,\r
-                       const char * rname, int rnum));\r
-static long    eitol P((int i));\r
-static void    error P((const char * message));\r
-static char ** getfields P((char * buf));\r
-static long    gethms P((const char * string, const char * errstrng,\r
-                       int signable));\r
-static void    infile P((const char * filename));\r
-static void    inleap P((char ** fields, int nfields));\r
-static void    inlink P((char ** fields, int nfields));\r
-static void    inrule P((char ** fields, int nfields));\r
-static int     inzcont P((char ** fields, int nfields));\r
-static int     inzone P((char ** fields, int nfields));\r
-static int     inzsub P((char ** fields, int nfields, int iscont));\r
-static int     itsabbr P((const char * abbr, const char * word));\r
-static int     itsdir P((const char * name));\r
-static int     lowerit P((int c));\r
-static char *  memcheck P((char * tocheck));\r
-static int     mkdirs P((char * filename));\r
-static void    newabbr P((const char * abbr));\r
-static long    oadd P((long t1, long t2));\r
-static void    outzone P((const struct zone * zp, int ntzones));\r
-static void    puttzcode P((long code, FILE * fp));\r
-static int     rcomp P((const void * leftp, const void * rightp));\r
-static time_t  rpytime P((const struct rule * rp, int wantedy));\r
-static void    rulesub P((struct rule * rp,\r
-                       const char * loyearp, const char * hiyearp,\r
-                       const char * typep, const char * monthp,\r
-                       const char * dayp, const char * timep));\r
-static void    setboundaries P((void));\r
-static time_t  tadd P((time_t t1, long t2));\r
-static void    usage P((void));\r
-static void    writezone P((const char * name));\r
-static int     yearistype P((int year, const char * type));\r
-\r
-#if !(HAVE_STRERROR - 0)\r
-static char *  strerror P((int));\r
-#endif /* !(HAVE_STRERROR - 0) */\r
-\r
-static int             charcnt;\r
-static int             errors;\r
-static const char *    filename;\r
-static int             leapcnt;\r
-static int             linenum;\r
-static time_t          max_time;\r
-static int             max_year;\r
-static int             max_year_representable;\r
-static time_t          min_time;\r
-static int             min_year;\r
-static int             min_year_representable;\r
-static int             noise;\r
-static const char *    rfilename;\r
-static int             rlinenum;\r
-static const char *    progname;\r
-static int             timecnt;\r
-static int             typecnt;\r
-\r
-/*\r
-** Line codes.\r
-*/\r
-\r
-#define LC_RULE                0\r
-#define LC_ZONE                1\r
-#define LC_LINK                2\r
-#define LC_LEAP                3\r
-\r
-/*\r
-** Which fields are which on a Zone line.\r
-*/\r
-\r
-#define ZF_NAME                1\r
-#define ZF_GMTOFF      2\r
-#define ZF_RULE                3\r
-#define ZF_FORMAT      4\r
-#define ZF_TILYEAR     5\r
-#define ZF_TILMONTH    6\r
-#define ZF_TILDAY      7\r
-#define ZF_TILTIME     8\r
-#define ZONE_MINFIELDS 5\r
-#define ZONE_MAXFIELDS 9\r
-\r
-/*\r
-** Which fields are which on a Zone continuation line.\r
-*/\r
-\r
-#define ZFC_GMTOFF     0\r
-#define ZFC_RULE       1\r
-#define ZFC_FORMAT     2\r
-#define ZFC_TILYEAR    3\r
-#define ZFC_TILMONTH   4\r
-#define ZFC_TILDAY     5\r
-#define ZFC_TILTIME    6\r
-#define ZONEC_MINFIELDS        3\r
-#define ZONEC_MAXFIELDS        7\r
-\r
-/*\r
-** Which files are which on a Rule line.\r
-*/\r
-\r
-#define RF_NAME                1\r
-#define RF_LOYEAR      2\r
-#define RF_HIYEAR      3\r
-#define RF_COMMAND     4\r
-#define RF_MONTH       5\r
-#define RF_DAY         6\r
-#define RF_TOD         7\r
-#define RF_STDOFF      8\r
-#define RF_ABBRVAR     9\r
-#define RULE_FIELDS    10\r
-\r
-/*\r
-** Which fields are which on a Link line.\r
-*/\r
-\r
-#define LF_FROM                1\r
-#define LF_TO          2\r
-#define LINK_FIELDS    3\r
-\r
-/*\r
-** Which fields are which on a Leap line.\r
-*/\r
-\r
-#define LP_YEAR                1\r
-#define LP_MONTH       2\r
-#define LP_DAY         3\r
-#define LP_TIME                4\r
-#define LP_CORR                5\r
-#define LP_ROLL                6\r
-#define LEAP_FIELDS    7\r
-\r
-/*\r
-** Year synonyms.\r
-*/\r
-\r
-#define YR_MINIMUM     0\r
-#define YR_MAXIMUM     1\r
-#define YR_ONLY                2\r
-\r
-static struct rule *   rules;\r
-static int             nrules; /* number of rules */\r
-\r
-static struct zone *   zones;\r
-static int             nzones; /* number of zones */\r
-\r
-struct link {\r
-       const char *    l_filename;\r
-       int             l_linenum;\r
-       const char *    l_from;\r
-       const char *    l_to;\r
-};\r
-\r
-static struct link *   links;\r
-static int             nlinks;\r
-\r
-struct lookup {\r
-       const char *    l_word;\r
-       const int       l_value;\r
-};\r
-\r
-static struct lookup const *   byword P((const char * string,\r
-                                       const struct lookup * lp));\r
-\r
-static struct lookup const     line_codes[] = {\r
-       { "Rule",       LC_RULE },\r
-       { "Zone",       LC_ZONE },\r
-       { "Link",       LC_LINK },\r
-       { "Leap",       LC_LEAP },\r
-       { NULL,         0}\r
-};\r
-\r
-static struct lookup const     mon_names[] = {\r
-       { "January",    TM_JANUARY },\r
-       { "February",   TM_FEBRUARY },\r
-       { "March",      TM_MARCH },\r
-       { "April",      TM_APRIL },\r
-       { "May",        TM_MAY },\r
-       { "June",       TM_JUNE },\r
-       { "July",       TM_JULY },\r
-       { "August",     TM_AUGUST },\r
-       { "September",  TM_SEPTEMBER },\r
-       { "October",    TM_OCTOBER },\r
-       { "November",   TM_NOVEMBER },\r
-       { "December",   TM_DECEMBER },\r
-       { NULL,         0 }\r
-};\r
-\r
-static struct lookup const     wday_names[] = {\r
-       { "Sunday",     TM_SUNDAY },\r
-       { "Monday",     TM_MONDAY },\r
-       { "Tuesday",    TM_TUESDAY },\r
-       { "Wednesday",  TM_WEDNESDAY },\r
-       { "Thursday",   TM_THURSDAY },\r
-       { "Friday",     TM_FRIDAY },\r
-       { "Saturday",   TM_SATURDAY },\r
-       { NULL,         0 }\r
-};\r
-\r
-static struct lookup const     lasts[] = {\r
-       { "last-Sunday",        TM_SUNDAY },\r
-       { "last-Monday",        TM_MONDAY },\r
-       { "last-Tuesday",       TM_TUESDAY },\r
-       { "last-Wednesday",     TM_WEDNESDAY },\r
-       { "last-Thursday",      TM_THURSDAY },\r
-       { "last-Friday",        TM_FRIDAY },\r
-       { "last-Saturday",      TM_SATURDAY },\r
-       { NULL,                 0 }\r
-};\r
-\r
-static struct lookup const     begin_years[] = {\r
-       { "minimum",    YR_MINIMUM },\r
-       { "maximum",    YR_MAXIMUM },\r
-       { NULL,         0 }\r
-};\r
-\r
-static struct lookup const     end_years[] = {\r
-       { "minimum",    YR_MINIMUM },\r
-       { "maximum",    YR_MAXIMUM },\r
-       { "only",       YR_ONLY },\r
-       { NULL,         0 }\r
-};\r
-\r
-static struct lookup const     leap_types[] = {\r
-       { "Rolling",    TRUE },\r
-       { "Stationary", FALSE },\r
-       { NULL,         0 }\r
-};\r
-\r
-static const int       len_months[2][MONSPERYEAR] = {\r
-       { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },\r
-       { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }\r
-};\r
-\r
-static const int       len_years[2] = {\r
-       DAYSPERNYEAR, DAYSPERLYEAR\r
-};\r
-\r
-static struct attype {\r
-       time_t          at;\r
-       unsigned char   type;\r
-}                      attypes[TZ_MAX_TIMES];\r
-static long            gmtoffs[TZ_MAX_TYPES];\r
-static char            isdsts[TZ_MAX_TYPES];\r
-static unsigned char   abbrinds[TZ_MAX_TYPES];\r
-static char            ttisstds[TZ_MAX_TYPES];\r
-static char            ttisgmts[TZ_MAX_TYPES];\r
-static char            chars[TZ_MAX_CHARS];\r
-static time_t          trans[TZ_MAX_LEAPS];\r
-static long            corr[TZ_MAX_LEAPS];\r
-static char            roll[TZ_MAX_LEAPS];\r
-\r
-/*\r
-** Memory allocation.\r
-*/\r
-\r
-static char *\r
-memcheck(ptr)\r
-char * const   ptr;\r
-{\r
-       if (ptr == NULL) {\r
-               const char *e = strerror(errno);\r
-\r
-               (void) fprintf(stderr, _("%s: Memory exhausted: %s\n"),\r
-                       progname, e);\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       return ptr;\r
-}\r
-\r
-#define emalloc(size)          memcheck(imalloc(size))\r
-#define erealloc(ptr, size)    memcheck(irealloc((ptr), (size)))\r
-#define ecpyalloc(ptr)         memcheck(icpyalloc(ptr))\r
-#define ecatalloc(oldp, newp)  memcheck(icatalloc((oldp), (newp)))\r
-\r
-/*\r
-** Error handling.\r
-*/\r
-\r
-#if !(HAVE_STRERROR - 0)\r
-static char *\r
-strerror(errnum)\r
-int    errnum;\r
-{\r
-       extern char *   sys_errlist[];\r
-       extern int      sys_nerr;\r
-\r
-       return (errnum > 0 && errnum <= sys_nerr) ?\r
-               sys_errlist[errnum] : _("Unknown system error");\r
-}\r
-#endif /* !(HAVE_STRERROR - 0) */\r
-\r
-static void\r
-eats(name, num, rname, rnum)\r
-const char * const     name;\r
-const int              num;\r
-const char * const     rname;\r
-const int              rnum;\r
-{\r
-       filename = name;\r
-       linenum = num;\r
-       rfilename = rname;\r
-       rlinenum = rnum;\r
-}\r
-\r
-static void\r
-eat(name, num)\r
-const char * const     name;\r
-const int              num;\r
-{\r
-       eats(name, num, (char *) NULL, -1);\r
-}\r
-\r
-static void\r
-error(string)\r
-const char * const     string;\r
-{\r
-       /*\r
-       ** Match the format of "cc" to allow sh users to\r
-       **      zic ... 2>&1 | error -t "*" -v\r
-       ** on BSD systems.\r
-       */\r
-       (void) fprintf(stderr, _("\"%s\", line %d: %s"),\r
-               filename, linenum, string);\r
-       if (rfilename != NULL)\r
-               (void) fprintf(stderr, _(" (rule from \"%s\", line %d)"),\r
-                       rfilename, rlinenum);\r
-       (void) fprintf(stderr, "\n");\r
-       ++errors;\r
-}\r
-\r
-static void\r
-warning(string)\r
-const char * const     string;\r
-{\r
-       char *  cp;\r
-\r
-       cp = ecpyalloc(_("warning: "));\r
-       cp = ecatalloc(cp, string);\r
-       error(cp);\r
-       ifree(cp);\r
-       --errors;\r
-}\r
-\r
-static void\r
-usage P((void))\r
-{\r
-       (void) fprintf(stderr, _("%s: usage is %s [ --version ] [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),\r
-               progname, progname);\r
-       (void) exit(EXIT_FAILURE);\r
-}\r
-\r
-static const char *    psxrules;\r
-static const char *    lcltime;\r
-static const char *    directory;\r
-static const char *    leapsec;\r
-static const char *    yitcommand;\r
-static int             sflag = FALSE;\r
-\r
-int\r
-main(argc, argv)\r
-int    argc;\r
-char * argv[];\r
-{\r
-       register int    i;\r
-       register int    j;\r
-       register int    c;\r
-\r
-#ifdef unix\r
-       (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));\r
-#endif /* defined unix */\r
-#if HAVE_GETTEXT - 0\r
-       (void) setlocale(LC_MESSAGES, "");\r
-#ifdef TZ_DOMAINDIR\r
-       (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);\r
-#endif /* defined TEXTDOMAINDIR */\r
-       (void) textdomain(TZ_DOMAIN);\r
-#endif /* HAVE_GETTEXT - 0 */\r
-       progname = argv[0];\r
-       for (i = 1; i < argc; ++i)\r
-               if (strcmp(argv[i], "--version") == 0) {\r
-                       (void) printf("%s\n", elsieid);\r
-                       (void) exit(EXIT_SUCCESS);\r
-               }\r
-       while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)\r
-               switch (c) {\r
-                       default:\r
-                               usage();\r
-                       case 'd':\r
-                               if (directory == NULL)\r
-                                       directory = optarg;\r
-                               else {\r
-                                       (void) fprintf(stderr,\r
-_("%s: More than one -d option specified\n"),\r
-                                               progname);\r
-                                       (void) exit(EXIT_FAILURE);\r
-                               }\r
-                               break;\r
-                       case 'l':\r
-                               if (lcltime == NULL)\r
-                                       lcltime = optarg;\r
-                               else {\r
-                                       (void) fprintf(stderr,\r
-_("%s: More than one -l option specified\n"),\r
-                                               progname);\r
-                                       (void) exit(EXIT_FAILURE);\r
-                               }\r
-                               break;\r
-                       case 'p':\r
-                               if (psxrules == NULL)\r
-                                       psxrules = optarg;\r
-                               else {\r
-                                       (void) fprintf(stderr,\r
-_("%s: More than one -p option specified\n"),\r
-                                               progname);\r
-                                       (void) exit(EXIT_FAILURE);\r
-                               }\r
-                               break;\r
-                       case 'y':\r
-                               if (yitcommand == NULL)\r
-                                       yitcommand = optarg;\r
-                               else {\r
-                                       (void) fprintf(stderr,\r
-_("%s: More than one -y option specified\n"),\r
-                                               progname);\r
-                                       (void) exit(EXIT_FAILURE);\r
-                               }\r
-                               break;\r
-                       case 'L':\r
-                               if (leapsec == NULL)\r
-                                       leapsec = optarg;\r
-                               else {\r
-                                       (void) fprintf(stderr,\r
-_("%s: More than one -L option specified\n"),\r
-                                               progname);\r
-                                       (void) exit(EXIT_FAILURE);\r
-                               }\r
-                               break;\r
-                       case 'v':\r
-                               noise = TRUE;\r
-                               break;\r
-                       case 's':\r
-                               sflag = TRUE;\r
-                               break;\r
-               }\r
-       if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)\r
-               usage();        /* usage message by request */\r
-       if (directory == NULL)\r
-               directory = TZDIR;\r
-       if (yitcommand == NULL)\r
-               yitcommand = "yearistype";\r
-\r
-       setboundaries();\r
-\r
-       if (optind < argc && leapsec != NULL) {\r
-               infile(leapsec);\r
-               adjleap();\r
-       }\r
-\r
-       for (i = optind; i < argc; ++i)\r
-               infile(argv[i]);\r
-       if (errors)\r
-               (void) exit(EXIT_FAILURE);\r
-       associate();\r
-       for (i = 0; i < nzones; i = j) {\r
-               /*\r
-               ** Find the next non-continuation zone entry.\r
-               */\r
-               for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)\r
-                       continue;\r
-               outzone(&zones[i], j - i);\r
-       }\r
-       /*\r
-       ** Make links.\r
-       */\r
-       for (i = 0; i < nlinks; ++i) {\r
-               eat(links[i].l_filename, links[i].l_linenum);\r
-               dolink(links[i].l_from, links[i].l_to);\r
-       }\r
-       if (lcltime != NULL) {\r
-               eat("command line", 1);\r
-               dolink(lcltime, TZDEFAULT);\r
-       }\r
-       if (psxrules != NULL) {\r
-               eat("command line", 1);\r
-               dolink(psxrules, TZDEFRULES);\r
-       }\r
-       return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;\r
-}\r
-\r
-static void\r
-dolink(fromfile, tofile)\r
-const char * const     fromfile;\r
-const char * const     tofile;\r
-{\r
-       register char * fromname;\r
-       register char * toname;\r
-\r
-       if (fromfile[0] == '/')\r
-               fromname = ecpyalloc(fromfile);\r
-       else {\r
-               fromname = ecpyalloc(directory);\r
-               fromname = ecatalloc(fromname, "/");\r
-               fromname = ecatalloc(fromname, fromfile);\r
-       }\r
-       if (tofile[0] == '/')\r
-               toname = ecpyalloc(tofile);\r
-       else {\r
-               toname = ecpyalloc(directory);\r
-               toname = ecatalloc(toname, "/");\r
-               toname = ecatalloc(toname, tofile);\r
-       }\r
-       /*\r
-       ** We get to be careful here since\r
-       ** there's a fair chance of root running us.\r
-       */\r
-       if (!itsdir(toname))\r
-               (void) remove(toname);\r
-       if (link(fromname, toname) != 0) {\r
-               int     result;\r
-\r
-               if (mkdirs(toname) != 0)\r
-                       (void) exit(EXIT_FAILURE);\r
-\r
-               result = link(fromname, toname);\r
-#if (HAVE_SYMLINK - 0)\r
-               if (result != 0 &&\r
-                   access(fromname, F_OK) == 0 &&\r
-                   !itsdir(fromname)) {\r
-                       const char *s = tofile;\r
-                       register char * symlinkcontents = NULL;\r
-                       while ((s = strchr(s+1, '/')) != NULL)\r
-                               symlinkcontents = ecatalloc(symlinkcontents, "../");\r
-                       symlinkcontents = ecatalloc(symlinkcontents, fromfile);\r
-\r
-                       result = symlink(symlinkcontents, toname);\r
-                       if (result == 0)\r
-warning(_("hard link failed, symbolic link used"));\r
-                       ifree(symlinkcontents);\r
-               }\r
-#endif\r
-               if (result != 0) {\r
-                       const char *e = strerror(errno);\r
-\r
-                       (void) fprintf(stderr,\r
-                               _("%s: Can't link from %s to %s: %s\n"),\r
-                               progname, fromname, toname, e);\r
-                       (void) exit(EXIT_FAILURE);\r
-               }\r
-       }\r
-       ifree(fromname);\r
-       ifree(toname);\r
-}\r
-\r
-#ifndef INT_MAX\r
-#define INT_MAX        ((int) (((unsigned)~0)>>1))\r
-#endif /* !defined INT_MAX */\r
-\r
-#ifndef INT_MIN\r
-#define INT_MIN        ((int) ~(((unsigned)~0)>>1))\r
-#endif /* !defined INT_MIN */\r
-\r
-/*\r
-** The tz file format currently allows at most 32-bit quantities.\r
-** This restriction should be removed before signed 32-bit values\r
-** wrap around in 2038, but unfortunately this will require a\r
-** change to the tz file format.\r
-*/\r
-\r
-#define MAX_BITS_IN_FILE       32\r
-#define TIME_T_BITS_IN_FILE    ((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE)\r
-\r
-static void\r
-setboundaries P((void))\r
-{\r
-       if (TYPE_SIGNED(time_t)) {\r
-               min_time = ~ (time_t) 0;\r
-               min_time <<= TIME_T_BITS_IN_FILE - 1;\r
-               max_time = ~ (time_t) 0 - min_time;\r
-               if (sflag)\r
-                       min_time = 0;\r
-       } else {\r
-               min_time = 0;\r
-               max_time = 2 - sflag;\r
-               max_time <<= TIME_T_BITS_IN_FILE - 1;\r
-               --max_time;\r
-       }\r
-       min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;\r
-       max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;\r
-       min_year_representable = min_year;\r
-       max_year_representable = max_year;\r
-}\r
-\r
-static int\r
-itsdir(name)\r
-const char * const     name;\r
-{\r
-       register char * myname;\r
-       register int    accres;\r
-\r
-       myname = ecpyalloc(name);\r
-       myname = ecatalloc(myname, "/.");\r
-       accres = access(myname, F_OK);\r
-       ifree(myname);\r
-       return accres == 0;\r
-}\r
-\r
-/*\r
-** Associate sets of rules with zones.\r
-*/\r
-\r
-/*\r
-** Sort by rule name.\r
-*/\r
-\r
-static int\r
-rcomp(cp1, cp2)\r
-const void *   cp1;\r
-const void *   cp2;\r
-{\r
-       return strcmp(((const struct rule *) cp1)->r_name,\r
-               ((const struct rule *) cp2)->r_name);\r
-}\r
-\r
-static void\r
-associate P((void))\r
-{\r
-       register struct zone *  zp;\r
-       register struct rule *  rp;\r
-       register int            base, out;\r
-       register int            i, j;\r
-\r
-       if (nrules != 0) {\r
-               (void) qsort((void *) rules, (size_t) nrules,\r
-                       (size_t) sizeof *rules, rcomp);\r
-               for (i = 0; i < nrules - 1; ++i) {\r
-                       if (strcmp(rules[i].r_name,\r
-                               rules[i + 1].r_name) != 0)\r
-                                       continue;\r
-                       if (strcmp(rules[i].r_filename,\r
-                               rules[i + 1].r_filename) == 0)\r
-                                       continue;\r
-                       eat(rules[i].r_filename, rules[i].r_linenum);\r
-                       warning(_("same rule name in multiple files"));\r
-                       eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);\r
-                       warning(_("same rule name in multiple files"));\r
-                       for (j = i + 2; j < nrules; ++j) {\r
-                               if (strcmp(rules[i].r_name,\r
-                                       rules[j].r_name) != 0)\r
-                                               break;\r
-                               if (strcmp(rules[i].r_filename,\r
-                                       rules[j].r_filename) == 0)\r
-                                               continue;\r
-                               if (strcmp(rules[i + 1].r_filename,\r
-                                       rules[j].r_filename) == 0)\r
-                                               continue;\r
-                               break;\r
-                       }\r
-                       i = j - 1;\r
-               }\r
-       }\r
-       for (i = 0; i < nzones; ++i) {\r
-               zp = &zones[i];\r
-               zp->z_rules = NULL;\r
-               zp->z_nrules = 0;\r
-       }\r
-       for (base = 0; base < nrules; base = out) {\r
-               rp = &rules[base];\r
-               for (out = base + 1; out < nrules; ++out)\r
-                       if (strcmp(rp->r_name, rules[out].r_name) != 0)\r
-                               break;\r
-               for (i = 0; i < nzones; ++i) {\r
-                       zp = &zones[i];\r
-                       if (strcmp(zp->z_rule, rp->r_name) != 0)\r
-                               continue;\r
-                       zp->z_rules = rp;\r
-                       zp->z_nrules = out - base;\r
-               }\r
-       }\r
-       for (i = 0; i < nzones; ++i) {\r
-               zp = &zones[i];\r
-               if (zp->z_nrules == 0) {\r
-                       /*\r
-                       ** Maybe we have a local standard time offset.\r
-                       */\r
-                       eat(zp->z_filename, zp->z_linenum);\r
-                       zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"),\r
-                                             TRUE);\r
-                       /*\r
-                       ** Note, though, that if there's no rule,\r
-                       ** a '%s' in the format is a bad thing.\r
-                       */\r
-                       if (strchr(zp->z_format, '%') != 0)\r
-                               error(_("%s in ruleless zone"));\r
-               }\r
-       }\r
-       if (errors)\r
-               (void) exit(EXIT_FAILURE);\r
-}\r
-\r
-static void\r
-infile(name)\r
-const char *   name;\r
-{\r
-       register FILE *                 fp;\r
-       register char **                fields;\r
-       register char *                 cp;\r
-       register const struct lookup *  lp;\r
-       register int                    nfields;\r
-       register int                    wantcont;\r
-       register int                    num;\r
-       char                            buf[BUFSIZ];\r
-\r
-       if (strcmp(name, "-") == 0) {\r
-               name = _("standard input");\r
-               fp = stdin;\r
-       } else if ((fp = fopen(name, "r")) == NULL) {\r
-               const char *e = strerror(errno);\r
-\r
-               (void) fprintf(stderr, _("%s: Can't open %s: %s\n"),\r
-                       progname, name, e);\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       wantcont = FALSE;\r
-       for (num = 1; ; ++num) {\r
-               eat(name, num);\r
-               if (fgets(buf, (int) sizeof buf, fp) != buf)\r
-                       break;\r
-               cp = strchr(buf, '\n');\r
-               if (cp == NULL) {\r
-                       error(_("line too long"));\r
-                       (void) exit(EXIT_FAILURE);\r
-               }\r
-               *cp = '\0';\r
-               fields = getfields(buf);\r
-               nfields = 0;\r
-               while (fields[nfields] != NULL) {\r
-                       static char     nada;\r
-\r
-                       if (strcmp(fields[nfields], "-") == 0)\r
-                               fields[nfields] = &nada;\r
-                       ++nfields;\r
-               }\r
-               if (nfields == 0) {\r
-                       /* nothing to do */\r
-               } else if (wantcont) {\r
-                       wantcont = inzcont(fields, nfields);\r
-               } else {\r
-                       lp = byword(fields[0], line_codes);\r
-                       if (lp == NULL)\r
-                               error(_("input line of unknown type"));\r
-                       else switch ((int) (lp->l_value)) {\r
-                               case LC_RULE:\r
-                                       inrule(fields, nfields);\r
-                                       wantcont = FALSE;\r
-                                       break;\r
-                               case LC_ZONE:\r
-                                       wantcont = inzone(fields, nfields);\r
-                                       break;\r
-                               case LC_LINK:\r
-                                       inlink(fields, nfields);\r
-                                       wantcont = FALSE;\r
-                                       break;\r
-                               case LC_LEAP:\r
-                                       if (name != leapsec)\r
-                                               (void) fprintf(stderr,\r
-_("%s: Leap line in non leap seconds file %s\n"),\r
-                                                       progname, name);\r
-                                       else    inleap(fields, nfields);\r
-                                       wantcont = FALSE;\r
-                                       break;\r
-                               default:        /* "cannot happen" */\r
-                                       (void) fprintf(stderr,\r
-_("%s: panic: Invalid l_value %d\n"),\r
-                                               progname, lp->l_value);\r
-                                       (void) exit(EXIT_FAILURE);\r
-                       }\r
-               }\r
-               ifree((char *) fields);\r
-       }\r
-       if (ferror(fp)) {\r
-               (void) fprintf(stderr, _("%s: Error reading %s\n"),\r
-                       progname, filename);\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       if (fp != stdin && fclose(fp)) {\r
-               const char *e = strerror(errno);\r
-\r
-               (void) fprintf(stderr, _("%s: Error closing %s: %s\n"),\r
-                       progname, filename, e);\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       if (wantcont)\r
-               error(_("expected continuation line not found"));\r
-}\r
-\r
-/*\r
-** Convert a string of one of the forms\r
-**     h       -h      hh:mm   -hh:mm  hh:mm:ss        -hh:mm:ss\r
-** into a number of seconds.\r
-** A null string maps to zero.\r
-** Call error with errstring and return zero on errors.\r
-*/\r
-\r
-static long\r
-gethms(string, errstring, signable)\r
-const char *           string;\r
-const char * const     errstring;\r
-const int              signable;\r
-{\r
-       int     hh, mm, ss, sign;\r
-\r
-       if (string == NULL || *string == '\0')\r
-               return 0;\r
-       if (!signable)\r
-               sign = 1;\r
-       else if (*string == '-') {\r
-               sign = -1;\r
-               ++string;\r
-       } else  sign = 1;\r
-       if (sscanf(string, scheck(string, "%d"), &hh) == 1)\r
-               mm = ss = 0;\r
-       else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)\r
-               ss = 0;\r
-       else if (sscanf(string, scheck(string, "%d:%d:%d"),\r
-               &hh, &mm, &ss) != 3) {\r
-                       error(errstring);\r
-                       return 0;\r
-       }\r
-       if ((hh < 0 || hh >= HOURSPERDAY ||\r
-               mm < 0 || mm >= MINSPERHOUR ||\r
-               ss < 0 || ss > SECSPERMIN) &&\r
-               !(hh == HOURSPERDAY && mm == 0 && ss == 0)) {\r
-                       error(errstring);\r
-                       return 0;\r
-       }\r
-       if (noise && hh == HOURSPERDAY)\r
-               warning(_("24:00 not handled by pre-1998 versions of zic"));\r
-       return eitol(sign) *\r
-               (eitol(hh * MINSPERHOUR + mm) *\r
-               eitol(SECSPERMIN) + eitol(ss));\r
-}\r
-\r
-static void\r
-inrule(fields, nfields)\r
-register char ** const fields;\r
-const int              nfields;\r
-{\r
-       static struct rule      r;\r
-\r
-       if (nfields != RULE_FIELDS) {\r
-               error(_("wrong number of fields on Rule line"));\r
-               return;\r
-       }\r
-       if (*fields[RF_NAME] == '\0') {\r
-               error(_("nameless rule"));\r
-               return;\r
-       }\r
-       r.r_filename = filename;\r
-       r.r_linenum = linenum;\r
-       r.r_stdoff = gethms(fields[RF_STDOFF], _("invalid saved time"), TRUE);\r
-       rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],\r
-               fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);\r
-       r.r_name = ecpyalloc(fields[RF_NAME]);\r
-       r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);\r
-       rules = (struct rule *) (void *) erealloc((char *) rules,\r
-               (int) ((nrules + 1) * sizeof *rules));\r
-       rules[nrules++] = r;\r
-}\r
-\r
-static int\r
-inzone(fields, nfields)\r
-register char ** const fields;\r
-const int              nfields;\r
-{\r
-       register int    i;\r
-       static char *   buf;\r
-\r
-       if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {\r
-               error(_("wrong number of fields on Zone line"));\r
-               return FALSE;\r
-       }\r
-       if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {\r
-               buf = erealloc(buf, (int) (132 + strlen(TZDEFAULT)));\r
-               (void) sprintf(buf,\r
-_("\"Zone %s\" line and -l option are mutually exclusive"),\r
-                       TZDEFAULT);\r
-               error(buf);\r
-               return FALSE;\r
-       }\r
-       if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {\r
-               buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES)));\r
-               (void) sprintf(buf,\r
-_("\"Zone %s\" line and -p option are mutually exclusive"),\r
-                       TZDEFRULES);\r
-               error(buf);\r
-               return FALSE;\r
-       }\r
-       for (i = 0; i < nzones; ++i)\r
-               if (zones[i].z_name != NULL &&\r
-                       strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {\r
-                               buf = erealloc(buf, (int) (132 +\r
-                                       strlen(fields[ZF_NAME]) +\r
-                                       strlen(zones[i].z_filename)));\r
-                               (void) sprintf(buf,\r
-_("duplicate zone name %s (file \"%s\", line %d)"),\r
-                                       fields[ZF_NAME],\r
-                                       zones[i].z_filename,\r
-                                       zones[i].z_linenum);\r
-                               error(buf);\r
-                               return FALSE;\r
-               }\r
-       return inzsub(fields, nfields, FALSE);\r
-}\r
-\r
-static int\r
-inzcont(fields, nfields)\r
-register char ** const fields;\r
-const int              nfields;\r
-{\r
-       if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {\r
-               error(_("wrong number of fields on Zone continuation line"));\r
-               return FALSE;\r
-       }\r
-       return inzsub(fields, nfields, TRUE);\r
-}\r
-\r
-static int\r
-inzsub(fields, nfields, iscont)\r
-register char ** const fields;\r
-const int              nfields;\r
-const int              iscont;\r
-{\r
-       register char *         cp;\r
-       static struct zone      z;\r
-       register int            i_gmtoff, i_rule, i_format;\r
-       register int            i_untilyear, i_untilmonth;\r
-       register int            i_untilday, i_untiltime;\r
-       register int            hasuntil;\r
-\r
-       if (iscont) {\r
-               i_gmtoff = ZFC_GMTOFF;\r
-               i_rule = ZFC_RULE;\r
-               i_format = ZFC_FORMAT;\r
-               i_untilyear = ZFC_TILYEAR;\r
-               i_untilmonth = ZFC_TILMONTH;\r
-               i_untilday = ZFC_TILDAY;\r
-               i_untiltime = ZFC_TILTIME;\r
-               z.z_name = NULL;\r
-       } else {\r
-               i_gmtoff = ZF_GMTOFF;\r
-               i_rule = ZF_RULE;\r
-               i_format = ZF_FORMAT;\r
-               i_untilyear = ZF_TILYEAR;\r
-               i_untilmonth = ZF_TILMONTH;\r
-               i_untilday = ZF_TILDAY;\r
-               i_untiltime = ZF_TILTIME;\r
-               z.z_name = ecpyalloc(fields[ZF_NAME]);\r
-       }\r
-       z.z_filename = filename;\r
-       z.z_linenum = linenum;\r
-       z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UTC offset"), TRUE);\r
-       if ((cp = strchr(fields[i_format], '%')) != 0) {\r
-               if (*++cp != 's' || strchr(cp, '%') != 0) {\r
-                       error(_("invalid abbreviation format"));\r
-                       return FALSE;\r
-               }\r
-       }\r
-       z.z_rule = ecpyalloc(fields[i_rule]);\r
-       z.z_format = ecpyalloc(fields[i_format]);\r
-       hasuntil = nfields > i_untilyear;\r
-       if (hasuntil) {\r
-               z.z_untilrule.r_filename = filename;\r
-               z.z_untilrule.r_linenum = linenum;\r
-               rulesub(&z.z_untilrule,\r
-                       fields[i_untilyear],\r
-                       "only",\r
-                       "",\r
-                       (nfields > i_untilmonth) ?\r
-                       fields[i_untilmonth] : "Jan",\r
-                       (nfields > i_untilday) ? fields[i_untilday] : "1",\r
-                       (nfields > i_untiltime) ? fields[i_untiltime] : "0");\r
-               z.z_untiltime = rpytime(&z.z_untilrule,\r
-                       z.z_untilrule.r_loyear);\r
-               if (iscont && nzones > 0 &&\r
-                       z.z_untiltime > min_time &&\r
-                       z.z_untiltime < max_time &&\r
-                       zones[nzones - 1].z_untiltime > min_time &&\r
-                       zones[nzones - 1].z_untiltime < max_time &&\r
-                       zones[nzones - 1].z_untiltime >= z.z_untiltime) {\r
-                               error(_("Zone continuation line end time is not after end time of previous line"));\r
-                               return FALSE;\r
-               }\r
-       }\r
-       zones = (struct zone *) (void *) erealloc((char *) zones,\r
-               (int) ((nzones + 1) * sizeof *zones));\r
-       zones[nzones++] = z;\r
-       /*\r
-       ** If there was an UNTIL field on this line,\r
-       ** there's more information about the zone on the next line.\r
-       */\r
-       return hasuntil;\r
-}\r
-\r
-static void\r
-inleap(fields, nfields)\r
-register char ** const fields;\r
-const int              nfields;\r
-{\r
-       register const char *           cp;\r
-       register const struct lookup *  lp;\r
-       register int                    i, j;\r
-       int                             year, month, day;\r
-       long                            dayoff, tod;\r
-       time_t                          t;\r
-\r
-       if (nfields != LEAP_FIELDS) {\r
-               error(_("wrong number of fields on Leap line"));\r
-               return;\r
-       }\r
-       dayoff = 0;\r
-       cp = fields[LP_YEAR];\r
-       if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {\r
-                       /*\r
-                        * Leapin' Lizards!\r
-                        */\r
-                       error(_("invalid leaping year"));\r
-                       return;\r
-       }\r
-       j = EPOCH_YEAR;\r
-       while (j != year) {\r
-               if (year > j) {\r
-                       i = len_years[isleap(j)];\r
-                       ++j;\r
-               } else {\r
-                       --j;\r
-                       i = -len_years[isleap(j)];\r
-               }\r
-               dayoff = oadd(dayoff, eitol(i));\r
-       }\r
-       if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {\r
-               error(_("invalid month name"));\r
-               return;\r
-       }\r
-       month = lp->l_value;\r
-       j = TM_JANUARY;\r
-       while (j != month) {\r
-               i = len_months[isleap(year)][j];\r
-               dayoff = oadd(dayoff, eitol(i));\r
-               ++j;\r
-       }\r
-       cp = fields[LP_DAY];\r
-       if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||\r
-               day <= 0 || day > len_months[isleap(year)][month]) {\r
-                       error(_("invalid day of month"));\r
-                       return;\r
-       }\r
-       dayoff = oadd(dayoff, eitol(day - 1));\r
-       if (dayoff < 0 && !TYPE_SIGNED(time_t)) {\r
-               error(_("time before zero"));\r
-               return;\r
-       }\r
-       if (dayoff < min_time / SECSPERDAY) {\r
-               error(_("time too small"));\r
-               return;\r
-       }\r
-       if (dayoff > max_time / SECSPERDAY) {\r
-               error(_("time too large"));\r
-               return;\r
-       }\r
-       t = (time_t) dayoff * SECSPERDAY;\r
-       tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);\r
-       cp = fields[LP_CORR];\r
-       {\r
-               register int    positive;\r
-               int             count;\r
-\r
-               if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */\r
-                       positive = FALSE;\r
-                       count = 1;\r
-               } else if (strcmp(cp, "--") == 0) {\r
-                       positive = FALSE;\r
-                       count = 2;\r
-               } else if (strcmp(cp, "+") == 0) {\r
-                       positive = TRUE;\r
-                       count = 1;\r
-               } else if (strcmp(cp, "++") == 0) {\r
-                       positive = TRUE;\r
-                       count = 2;\r
-               } else {\r
-                       error(_("illegal CORRECTION field on Leap line"));\r
-                       return;\r
-               }\r
-               if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {\r
-                       error(_("illegal Rolling/Stationary field on Leap line"));\r
-                       return;\r
-               }\r
-               leapadd(tadd(t, tod), positive, lp->l_value, count);\r
-       }\r
-}\r
-\r
-static void\r
-inlink(fields, nfields)\r
-register char ** const fields;\r
-const int              nfields;\r
-{\r
-       struct link     l;\r
-\r
-       if (nfields != LINK_FIELDS) {\r
-               error(_("wrong number of fields on Link line"));\r
-               return;\r
-       }\r
-       if (*fields[LF_FROM] == '\0') {\r
-               error(_("blank FROM field on Link line"));\r
-               return;\r
-       }\r
-       if (*fields[LF_TO] == '\0') {\r
-               error(_("blank TO field on Link line"));\r
-               return;\r
-       }\r
-       l.l_filename = filename;\r
-       l.l_linenum = linenum;\r
-       l.l_from = ecpyalloc(fields[LF_FROM]);\r
-       l.l_to = ecpyalloc(fields[LF_TO]);\r
-       links = (struct link *) (void *) erealloc((char *) links,\r
-               (int) ((nlinks + 1) * sizeof *links));\r
-       links[nlinks++] = l;\r
-}\r
-\r
-static void\r
-rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)\r
-register struct rule * const   rp;\r
-const char * const             loyearp;\r
-const char * const             hiyearp;\r
-const char * const             typep;\r
-const char * const             monthp;\r
-const char * const             dayp;\r
-const char * const             timep;\r
-{\r
-       register const struct lookup *  lp;\r
-       register const char *           cp;\r
-       register char *                 dp;\r
-       register char *                 ep;\r
-\r
-       if ((lp = byword(monthp, mon_names)) == NULL) {\r
-               error(_("invalid month name"));\r
-               return;\r
-       }\r
-       rp->r_month = lp->l_value;\r
-       rp->r_todisstd = FALSE;\r
-       rp->r_todisgmt = FALSE;\r
-       dp = ecpyalloc(timep);\r
-       if (*dp != '\0') {\r
-               ep = dp + strlen(dp) - 1;\r
-               switch (lowerit(*ep)) {\r
-                       case 's':       /* Standard */\r
-                               rp->r_todisstd = TRUE;\r
-                               rp->r_todisgmt = FALSE;\r
-                               *ep = '\0';\r
-                               break;\r
-                       case 'w':       /* Wall */\r
-                               rp->r_todisstd = FALSE;\r
-                               rp->r_todisgmt = FALSE;\r
-                               *ep = '\0';\r
-                               break;\r
-                       case 'g':       /* Greenwich */\r
-                       case 'u':       /* Universal */\r
-                       case 'z':       /* Zulu */\r
-                               rp->r_todisstd = TRUE;\r
-                               rp->r_todisgmt = TRUE;\r
-                               *ep = '\0';\r
-                               break;\r
-               }\r
-       }\r
-       rp->r_tod = gethms(dp, _("invalid time of day"), FALSE);\r
-       ifree(dp);\r
-       /*\r
-       ** Year work.\r
-       */\r
-       cp = loyearp;\r
-       lp = byword(cp, begin_years);\r
-       if (lp != NULL) switch ((int) lp->l_value) {\r
-               case YR_MINIMUM:\r
-                       rp->r_loyear = INT_MIN;\r
-                       break;\r
-               case YR_MAXIMUM:\r
-                       rp->r_loyear = INT_MAX;\r
-                       break;\r
-               default:        /* "cannot happen" */\r
-                       (void) fprintf(stderr,\r
-                               _("%s: panic: Invalid l_value %d\n"),\r
-                               progname, lp->l_value);\r
-                       (void) exit(EXIT_FAILURE);\r
-       } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {\r
-               error(_("invalid starting year"));\r
-               return;\r
-       } else if (noise) {\r
-               if (rp->r_loyear < min_year_representable)\r
-                       warning(_("starting year too low to be represented"));\r
-               else if (rp->r_loyear > max_year_representable)\r
-                       warning(_("starting year too high to be represented"));\r
-       }\r
-       cp = hiyearp;\r
-       if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {\r
-               case YR_MINIMUM:\r
-                       rp->r_hiyear = INT_MIN;\r
-                       break;\r
-               case YR_MAXIMUM:\r
-                       rp->r_hiyear = INT_MAX;\r
-                       break;\r
-               case YR_ONLY:\r
-                       rp->r_hiyear = rp->r_loyear;\r
-                       break;\r
-               default:        /* "cannot happen" */\r
-                       (void) fprintf(stderr,\r
-                               _("%s: panic: Invalid l_value %d\n"),\r
-                               progname, lp->l_value);\r
-                       (void) exit(EXIT_FAILURE);\r
-       } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {\r
-               error(_("invalid ending year"));\r
-               return;\r
-       } else if (noise) {\r
-               if (rp->r_loyear < min_year_representable)\r
-                       warning(_("ending year too low to be represented"));\r
-               else if (rp->r_loyear > max_year_representable)\r
-                       warning(_("ending year too high to be represented"));\r
-       }\r
-       if (rp->r_loyear > rp->r_hiyear) {\r
-               error(_("starting year greater than ending year"));\r
-               return;\r
-       }\r
-       if (*typep == '\0')\r
-               rp->r_yrtype = NULL;\r
-       else {\r
-               if (rp->r_loyear == rp->r_hiyear) {\r
-                       error(_("typed single year"));\r
-                       return;\r
-               }\r
-               rp->r_yrtype = ecpyalloc(typep);\r
-       }\r
-       if (rp->r_loyear < min_year && rp->r_loyear > 0)\r
-               min_year = rp->r_loyear;\r
-       /*\r
-       ** Day work.\r
-       ** Accept things such as:\r
-       **      1\r
-       **      last-Sunday\r
-       **      Sun<=20\r
-       **      Sun>=7\r
-       */\r
-       dp = ecpyalloc(dayp);\r
-       if ((lp = byword(dp, lasts)) != NULL) {\r
-               rp->r_dycode = DC_DOWLEQ;\r
-               rp->r_wday = lp->l_value;\r
-               rp->r_dayofmonth = len_months[1][rp->r_month];\r
-       } else {\r
-               if ((ep = strchr(dp, '<')) != 0)\r
-                       rp->r_dycode = DC_DOWLEQ;\r
-               else if ((ep = strchr(dp, '>')) != 0)\r
-                       rp->r_dycode = DC_DOWGEQ;\r
-               else {\r
-                       ep = dp;\r
-                       rp->r_dycode = DC_DOM;\r
-               }\r
-               if (rp->r_dycode != DC_DOM) {\r
-                       *ep++ = 0;\r
-                       if (*ep++ != '=') {\r
-                               error(_("invalid day of month"));\r
-                               ifree(dp);\r
-                               return;\r
-                       }\r
-                       if ((lp = byword(dp, wday_names)) == NULL) {\r
-                               error(_("invalid weekday name"));\r
-                               ifree(dp);\r
-                               return;\r
-                       }\r
-                       rp->r_wday = lp->l_value;\r
-               }\r
-               if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 ||\r
-                       rp->r_dayofmonth <= 0 ||\r
-                       (rp->r_dayofmonth > len_months[1][rp->r_month])) {\r
-                               error(_("invalid day of month"));\r
-                               ifree(dp);\r
-                               return;\r
-               }\r
-       }\r
-       ifree(dp);\r
-}\r
-\r
-static void\r
-convert(val, buf)\r
-const long     val;\r
-char * const   buf;\r
-{\r
-       register int    i;\r
-       register long   shift;\r
-\r
-       for (i = 0, shift = 24; i < 4; ++i, shift -= 8)\r
-               buf[i] = val >> shift;\r
-}\r
-\r
-static void\r
-puttzcode(val, fp)\r
-const long     val;\r
-FILE * const   fp;\r
-{\r
-       char    buf[4];\r
-\r
-       convert(val, buf);\r
-       (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);\r
-}\r
-\r
-static int\r
-atcomp(avp, bvp)\r
-void * avp;\r
-void * bvp;\r
-{\r
-       if (((struct attype *) avp)->at < ((struct attype *) bvp)->at)\r
-               return -1;\r
-       else if (((struct attype *) avp)->at > ((struct attype *) bvp)->at)\r
-               return 1;\r
-       else    return 0;\r
-}\r
-\r
-static void\r
-writezone(name)\r
-const char * const     name;\r
-{\r
-       register FILE *         fp;\r
-       register int            i, j;\r
-       static char *           fullname;\r
-       static struct tzhead    tzh;\r
-       time_t                  ats[TZ_MAX_TIMES];\r
-       unsigned char           types[TZ_MAX_TIMES];\r
-\r
-       /*\r
-       ** Sort.\r
-       */\r
-       if (timecnt > 1)\r
-               (void) qsort((void *) attypes, (size_t) timecnt,\r
-                       (size_t) sizeof *attypes, atcomp);\r
-       /*\r
-       ** Optimize.\r
-       */\r
-       {\r
-               int     fromi;\r
-               int     toi;\r
-\r
-               toi = 0;\r
-               fromi = 0;\r
-               while (fromi < timecnt && attypes[fromi].at < min_time)\r
-                       ++fromi;\r
-               if (isdsts[0] == 0)\r
-                       while (fromi < timecnt && attypes[fromi].type == 0)\r
-                               ++fromi;        /* handled by default rule */\r
-               for ( ; fromi < timecnt; ++fromi) {\r
-                       if (toi != 0\r
-                           && ((attypes[fromi].at\r
-                                + gmtoffs[attypes[toi - 1].type])\r
-                               <= (attypes[toi - 1].at\r
-                                   + gmtoffs[toi == 1 ? 0\r
-                                             : attypes[toi - 2].type]))) {\r
-                               attypes[toi - 1].type = attypes[fromi].type;\r
-                               continue;\r
-                       }\r
-                       if (toi == 0 ||\r
-                               attypes[toi - 1].type != attypes[fromi].type)\r
-                                       attypes[toi++] = attypes[fromi];\r
-               }\r
-               timecnt = toi;\r
-       }\r
-       /*\r
-       ** Transfer.\r
-       */\r
-       for (i = 0; i < timecnt; ++i) {\r
-               ats[i] = attypes[i].at;\r
-               types[i] = attypes[i].type;\r
-       }\r
-       fullname = erealloc(fullname,\r
-               (int) (strlen(directory) + 1 + strlen(name) + 1));\r
-       (void) sprintf(fullname, "%s/%s", directory, name);\r
-       /*\r
-       ** Remove old file, if any, to snap links.\r
-       */\r
-       if (!itsdir(fullname) && remove(fullname) != 0 && errno != ENOENT) {\r
-               const char *e = strerror(errno);\r
-\r
-               (void) fprintf(stderr, _("%s: Can't remove %s: %s\n"),\r
-                       progname, fullname, e);\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       if ((fp = fopen(fullname, "wb")) == NULL) {\r
-               if (mkdirs(fullname) != 0)\r
-                       (void) exit(EXIT_FAILURE);\r
-               if ((fp = fopen(fullname, "wb")) == NULL) {\r
-                       const char *e = strerror(errno);\r
-\r
-                       (void) fprintf(stderr, _("%s: Can't create %s: %s\n"),\r
-                               progname, fullname, e);\r
-                       (void) exit(EXIT_FAILURE);\r
-               }\r
-       }\r
-       convert(eitol(typecnt), tzh.tzh_ttisgmtcnt);\r
-       convert(eitol(typecnt), tzh.tzh_ttisstdcnt);\r
-       convert(eitol(leapcnt), tzh.tzh_leapcnt);\r
-       convert(eitol(timecnt), tzh.tzh_timecnt);\r
-       convert(eitol(typecnt), tzh.tzh_typecnt);\r
-       convert(eitol(charcnt), tzh.tzh_charcnt);\r
-       (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);\r
-#define DO(field)      (void) fwrite((void *) tzh.field, (size_t) sizeof tzh.field, (size_t) 1, fp)\r
-       DO(tzh_magic);\r
-       DO(tzh_reserved);\r
-       DO(tzh_ttisgmtcnt);\r
-       DO(tzh_ttisstdcnt);\r
-       DO(tzh_leapcnt);\r
-       DO(tzh_timecnt);\r
-       DO(tzh_typecnt);\r
-       DO(tzh_charcnt);\r
-#undef DO\r
-       for (i = 0; i < timecnt; ++i) {\r
-               j = leapcnt;\r
-               while (--j >= 0)\r
-                       if (ats[i] >= trans[j]) {\r
-                               ats[i] = tadd(ats[i], corr[j]);\r
-                               break;\r
-                       }\r
-               puttzcode((long) ats[i], fp);\r
-       }\r
-       if (timecnt > 0)\r
-               (void) fwrite((void *) types, (size_t) sizeof types[0],\r
-                       (size_t) timecnt, fp);\r
-       for (i = 0; i < typecnt; ++i) {\r
-               puttzcode((long) gmtoffs[i], fp);\r
-               (void) putc(isdsts[i], fp);\r
-               (void) putc(abbrinds[i], fp);\r
-       }\r
-       if (charcnt != 0)\r
-               (void) fwrite((void *) chars, (size_t) sizeof chars[0],\r
-                       (size_t) charcnt, fp);\r
-       for (i = 0; i < leapcnt; ++i) {\r
-               if (roll[i]) {\r
-                       if (timecnt == 0 || trans[i] < ats[0]) {\r
-                               j = 0;\r
-                               while (isdsts[j])\r
-                                       if (++j >= typecnt) {\r
-                                               j = 0;\r
-                                               break;\r
-                                       }\r
-                       } else {\r
-                               j = 1;\r
-                               while (j < timecnt && trans[i] >= ats[j])\r
-                                       ++j;\r
-                               j = types[j - 1];\r
-                       }\r
-                       puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);\r
-               } else  puttzcode((long) trans[i], fp);\r
-               puttzcode((long) corr[i], fp);\r
-       }\r
-       for (i = 0; i < typecnt; ++i)\r
-               (void) putc(ttisstds[i], fp);\r
-       for (i = 0; i < typecnt; ++i)\r
-               (void) putc(ttisgmts[i], fp);\r
-       if (ferror(fp) || fclose(fp)) {\r
-               (void) fprintf(stderr, _("%s: Error writing %s\n"),\r
-                       progname, fullname);\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-}\r
-\r
-static void\r
-doabbr(abbr, format, letters, isdst)\r
-char * const           abbr;\r
-const char * const     format;\r
-const char * const     letters;\r
-const int              isdst;\r
-{\r
-       if (strchr(format, '/') == NULL) {\r
-               if (letters == NULL)\r
-                       (void) strcpy(abbr, format);\r
-               else    (void) sprintf(abbr, format, letters);\r
-       } else if (isdst)\r
-               (void) strcpy(abbr, strchr(format, '/') + 1);\r
-       else {\r
-               (void) strcpy(abbr, format);\r
-               *strchr(abbr, '/') = '\0';\r
-       }\r
-}\r
-\r
-static void\r
-outzone(zpfirst, zonecount)\r
-const struct zone * const      zpfirst;\r
-const int                      zonecount;\r
-{\r
-       register const struct zone *    zp;\r
-       register struct rule *          rp;\r
-       register int                    i, j;\r
-       register int                    usestart, useuntil;\r
-       register time_t                 starttime, untiltime;\r
-       register long                   gmtoff;\r
-       register long                   stdoff;\r
-       register int                    year;\r
-       register long                   startoff;\r
-       register int                    startttisstd;\r
-       register int                    startttisgmt;\r
-       register int                    type;\r
-       char                            startbuf[BUFSIZ];\r
-\r
-       INITIALIZE(untiltime);\r
-       INITIALIZE(starttime);\r
-       /*\r
-       ** Now. . .finally. . .generate some useful data!\r
-       */\r
-       timecnt = 0;\r
-       typecnt = 0;\r
-       charcnt = 0;\r
-       /*\r
-       ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au)\r
-       ** for noting the need to unconditionally initialize startttisstd.\r
-       */\r
-       startttisstd = FALSE;\r
-       startttisgmt = FALSE;\r
-       for (i = 0; i < zonecount; ++i) {\r
-               /*\r
-               ** A guess that may well be corrected later.\r
-               */\r
-               stdoff = 0;\r
-               zp = &zpfirst[i];\r
-               usestart = i > 0 && (zp - 1)->z_untiltime > min_time;\r
-               useuntil = i < (zonecount - 1);\r
-               if (useuntil && zp->z_untiltime <= min_time)\r
-                       continue;\r
-               gmtoff = zp->z_gmtoff;\r
-               eat(zp->z_filename, zp->z_linenum);\r
-               *startbuf = '\0';\r
-               startoff = zp->z_gmtoff;\r
-               if (zp->z_nrules == 0) {\r
-                       stdoff = zp->z_stdoff;\r
-                       doabbr(startbuf, zp->z_format,\r
-                               (char *) NULL, stdoff != 0);\r
-                       type = addtype(oadd(zp->z_gmtoff, stdoff),\r
-                               startbuf, stdoff != 0, startttisstd,\r
-                               startttisgmt);\r
-                       if (usestart) {\r
-                               addtt(starttime, type);\r
-                               usestart = FALSE;\r
-                       } else if (stdoff != 0)\r
-                               addtt(min_time, type);\r
-               } else for (year = min_year; year <= max_year; ++year) {\r
-                       if (useuntil && year > zp->z_untilrule.r_hiyear)\r
-                               break;\r
-                       /*\r
-                       ** Mark which rules to do in the current year.\r
-                       ** For those to do, calculate rpytime(rp, year);\r
-                       */\r
-                       for (j = 0; j < zp->z_nrules; ++j) {\r
-                               rp = &zp->z_rules[j];\r
-                               eats(zp->z_filename, zp->z_linenum,\r
-                                       rp->r_filename, rp->r_linenum);\r
-                               rp->r_todo = year >= rp->r_loyear &&\r
-                                               year <= rp->r_hiyear &&\r
-                                               yearistype(year, rp->r_yrtype);\r
-                               if (rp->r_todo)\r
-                                       rp->r_temp = rpytime(rp, year);\r
-                       }\r
-                       for ( ; ; ) {\r
-                               register int    k;\r
-                               register time_t jtime, ktime;\r
-                               register long   offset;\r
-                               char            buf[BUFSIZ];\r
-\r
-                               INITIALIZE(ktime);\r
-                               if (useuntil) {\r
-                                       /*\r
-                                       ** Turn untiltime into UTC\r
-                                       ** assuming the current gmtoff and\r
-                                       ** stdoff values.\r
-                                       */\r
-                                       untiltime = zp->z_untiltime;\r
-                                       if (!zp->z_untilrule.r_todisgmt)\r
-                                               untiltime = tadd(untiltime,\r
-                                                       -gmtoff);\r
-                                       if (!zp->z_untilrule.r_todisstd)\r
-                                               untiltime = tadd(untiltime,\r
-                                                       -stdoff);\r
-                               }\r
-                               /*\r
-                               ** Find the rule (of those to do, if any)\r
-                               ** that takes effect earliest in the year.\r
-                               */\r
-                               k = -1;\r
-                               for (j = 0; j < zp->z_nrules; ++j) {\r
-                                       rp = &zp->z_rules[j];\r
-                                       if (!rp->r_todo)\r
-                                               continue;\r
-                                       eats(zp->z_filename, zp->z_linenum,\r
-                                               rp->r_filename, rp->r_linenum);\r
-                                       offset = rp->r_todisgmt ? 0 : gmtoff;\r
-                                       if (!rp->r_todisstd)\r
-                                               offset = oadd(offset, stdoff);\r
-                                       jtime = rp->r_temp;\r
-                                       if (jtime == min_time ||\r
-                                               jtime == max_time)\r
-                                                       continue;\r
-                                       jtime = tadd(jtime, -offset);\r
-                                       if (k < 0 || jtime < ktime) {\r
-                                               k = j;\r
-                                               ktime = jtime;\r
-                                       }\r
-                               }\r
-                               if (k < 0)\r
-                                       break;  /* go on to next year */\r
-                               rp = &zp->z_rules[k];\r
-                               rp->r_todo = FALSE;\r
-                               if (useuntil && ktime >= untiltime)\r
-                                       break;\r
-                               stdoff = rp->r_stdoff;\r
-                               if (usestart && ktime == starttime)\r
-                                       usestart = FALSE;\r
-                               if (usestart) {\r
-                                       if (ktime < starttime) {\r
-                                               startoff = oadd(zp->z_gmtoff,\r
-                                                       stdoff);\r
-                                               doabbr(startbuf, zp->z_format,\r
-                                                       rp->r_abbrvar,\r
-                                                       rp->r_stdoff != 0);\r
-                                               continue;\r
-                                       }\r
-                                       if (*startbuf == '\0' &&\r
-                                           startoff == oadd(zp->z_gmtoff,\r
-                                           stdoff)) {\r
-                                               doabbr(startbuf, zp->z_format,\r
-                                                       rp->r_abbrvar,\r
-                                                       rp->r_stdoff != 0);\r
-                                       }\r
-                               }\r
-                               eats(zp->z_filename, zp->z_linenum,\r
-                                       rp->r_filename, rp->r_linenum);\r
-                               doabbr(buf, zp->z_format, rp->r_abbrvar,\r
-                                       rp->r_stdoff != 0);\r
-                               offset = oadd(zp->z_gmtoff, rp->r_stdoff);\r
-                               type = addtype(offset, buf, rp->r_stdoff != 0,\r
-                                       rp->r_todisstd, rp->r_todisgmt);\r
-                               addtt(ktime, type);\r
-                       }\r
-               }\r
-               if (usestart) {\r
-                       if (*startbuf == '\0' &&\r
-                               zp->z_format != NULL &&\r
-                               strchr(zp->z_format, '%') == NULL &&\r
-                               strchr(zp->z_format, '/') == NULL)\r
-                                       (void) strcpy(startbuf, zp->z_format);\r
-                       eat(zp->z_filename, zp->z_linenum);\r
-                       if (*startbuf == '\0')\r
-error(_("can't determine time zone abbreviation to use just after until time"));\r
-                       else    addtt(starttime,\r
-                                       addtype(startoff, startbuf,\r
-                                               startoff != zp->z_gmtoff,\r
-                                               startttisstd,\r
-                                               startttisgmt));\r
-               }\r
-               /*\r
-               ** Now we may get to set starttime for the next zone line.\r
-               */\r
-               if (useuntil) {\r
-                       startttisstd = zp->z_untilrule.r_todisstd;\r
-                       startttisgmt = zp->z_untilrule.r_todisgmt;\r
-                       starttime = zp->z_untiltime;\r
-                       if (!startttisstd)\r
-                               starttime = tadd(starttime, -stdoff);\r
-                       if (!startttisgmt)\r
-                               starttime = tadd(starttime, -gmtoff);\r
-               }\r
-       }\r
-       writezone(zpfirst->z_name);\r
-}\r
-\r
-static void\r
-addtt(starttime, type)\r
-const time_t   starttime;\r
-int            type;\r
-{\r
-       if (starttime <= min_time ||\r
-               (timecnt == 1 && attypes[0].at < min_time)) {\r
-               gmtoffs[0] = gmtoffs[type];\r
-               isdsts[0] = isdsts[type];\r
-               ttisstds[0] = ttisstds[type];\r
-               ttisgmts[0] = ttisgmts[type];\r
-               if (abbrinds[type] != 0)\r
-                       (void) strcpy(chars, &chars[abbrinds[type]]);\r
-               abbrinds[0] = 0;\r
-               charcnt = strlen(chars) + 1;\r
-               typecnt = 1;\r
-               timecnt = 0;\r
-               type = 0;\r
-       }\r
-       if (timecnt >= TZ_MAX_TIMES) {\r
-               error(_("too many transitions?!"));\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       attypes[timecnt].at = starttime;\r
-       attypes[timecnt].type = type;\r
-       ++timecnt;\r
-}\r
-\r
-static int\r
-addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt)\r
-const long             gmtoff;\r
-const char * const     abbr;\r
-const int              isdst;\r
-const int              ttisstd;\r
-const int              ttisgmt;\r
-{\r
-       register int    i, j;\r
-\r
-       if (isdst != TRUE && isdst != FALSE) {\r
-               error(_("internal error - addtype called with bad isdst"));\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       if (ttisstd != TRUE && ttisstd != FALSE) {\r
-               error(_("internal error - addtype called with bad ttisstd"));\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       if (ttisgmt != TRUE && ttisgmt != FALSE) {\r
-               error(_("internal error - addtype called with bad ttisgmt"));\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       /*\r
-       ** See if there's already an entry for this zone type.\r
-       ** If so, just return its index.\r
-       */\r
-       for (i = 0; i < typecnt; ++i) {\r
-               if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&\r
-                       strcmp(abbr, &chars[abbrinds[i]]) == 0 &&\r
-                       ttisstd == ttisstds[i] &&\r
-                       ttisgmt == ttisgmts[i])\r
-                               return i;\r
-       }\r
-       /*\r
-       ** There isn't one; add a new one, unless there are already too\r
-       ** many.\r
-       */\r
-       if (typecnt >= TZ_MAX_TYPES) {\r
-               error(_("too many local time types"));\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       gmtoffs[i] = gmtoff;\r
-       isdsts[i] = isdst;\r
-       ttisstds[i] = ttisstd;\r
-       ttisgmts[i] = ttisgmt;\r
-\r
-       for (j = 0; j < charcnt; ++j)\r
-               if (strcmp(&chars[j], abbr) == 0)\r
-                       break;\r
-       if (j == charcnt)\r
-               newabbr(abbr);\r
-       abbrinds[i] = j;\r
-       ++typecnt;\r
-       return i;\r
-}\r
-\r
-static void\r
-leapadd(t, positive, rolling, count)\r
-const time_t   t;\r
-const int      positive;\r
-const int      rolling;\r
-int            count;\r
-{\r
-       register int    i, j;\r
-\r
-       if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {\r
-               error(_("too many leap seconds"));\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       for (i = 0; i < leapcnt; ++i)\r
-               if (t <= trans[i]) {\r
-                       if (t == trans[i]) {\r
-                               error(_("repeated leap second moment"));\r
-                               (void) exit(EXIT_FAILURE);\r
-                       }\r
-                       break;\r
-               }\r
-       do {\r
-               for (j = leapcnt; j > i; --j) {\r
-                       trans[j] = trans[j - 1];\r
-                       corr[j] = corr[j - 1];\r
-                       roll[j] = roll[j - 1];\r
-               }\r
-               trans[i] = t;\r
-               corr[i] = positive ? 1L : eitol(-count);\r
-               roll[i] = rolling;\r
-               ++leapcnt;\r
-       } while (positive && --count != 0);\r
-}\r
-\r
-static void\r
-adjleap P((void))\r
-{\r
-       register int    i;\r
-       register long   last = 0;\r
-\r
-       /*\r
-       ** propagate leap seconds forward\r
-       */\r
-       for (i = 0; i < leapcnt; ++i) {\r
-               trans[i] = tadd(trans[i], last);\r
-               last = corr[i] += last;\r
-       }\r
-}\r
-\r
-static int\r
-yearistype(year, type)\r
-const int              year;\r
-const char * const     type;\r
-{\r
-       static char *   buf;\r
-       int             result;\r
-\r
-       if (type == NULL || *type == '\0')\r
-               return TRUE;\r
-       buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type)));\r
-       (void) sprintf(buf, "%s %d %s", yitcommand, year, type);\r
-       result = system(buf);\r
-       if (WIFEXITED(result)) switch (WEXITSTATUS(result)) {\r
-               case 0:\r
-                       return TRUE;\r
-               case 1:\r
-                       return FALSE;\r
-       }\r
-       error(_("Wild result from command execution"));\r
-       (void) fprintf(stderr, _("%s: command was '%s', result was %d\n"),\r
-               progname, buf, result);\r
-       for ( ; ; )\r
-               (void) exit(EXIT_FAILURE);\r
-}\r
-\r
-static int\r
-lowerit(a)\r
-int    a;\r
-{\r
-       a = (unsigned char) a;\r
-       return (isascii(a) && isupper(a)) ? tolower(a) : a;\r
-}\r
-\r
-static int\r
-ciequal(ap, bp)                /* case-insensitive equality */\r
-register const char *  ap;\r
-register const char *  bp;\r
-{\r
-       while (lowerit(*ap) == lowerit(*bp++))\r
-               if (*ap++ == '\0')\r
-                       return TRUE;\r
-       return FALSE;\r
-}\r
-\r
-static int\r
-itsabbr(abbr, word)\r
-register const char *  abbr;\r
-register const char *  word;\r
-{\r
-       if (lowerit(*abbr) != lowerit(*word))\r
-               return FALSE;\r
-       ++word;\r
-       while (*++abbr != '\0')\r
-               do {\r
-                       if (*word == '\0')\r
-                               return FALSE;\r
-               } while (lowerit(*word++) != lowerit(*abbr));\r
-       return TRUE;\r
-}\r
-\r
-static const struct lookup *\r
-byword(word, table)\r
-register const char * const            word;\r
-register const struct lookup * const   table;\r
-{\r
-       register const struct lookup *  foundlp;\r
-       register const struct lookup *  lp;\r
-\r
-       if (word == NULL || table == NULL)\r
-               return NULL;\r
-       /*\r
-       ** Look for exact match.\r
-       */\r
-       for (lp = table; lp->l_word != NULL; ++lp)\r
-               if (ciequal(word, lp->l_word))\r
-                       return lp;\r
-       /*\r
-       ** Look for inexact match.\r
-       */\r
-       foundlp = NULL;\r
-       for (lp = table; lp->l_word != NULL; ++lp)\r
-               if (itsabbr(word, lp->l_word)) {\r
-                       if (foundlp == NULL)\r
-                               foundlp = lp;\r
-                       else    return NULL;    /* multiple inexact matches */\r
-               }\r
-       return foundlp;\r
-}\r
-\r
-static char **\r
-getfields(cp)\r
-register char *        cp;\r
-{\r
-       register char *         dp;\r
-       register char **        array;\r
-       register int            nsubs;\r
-\r
-       if (cp == NULL)\r
-               return NULL;\r
-       array = (char **) (void *)\r
-               emalloc((int) ((strlen(cp) + 1) * sizeof *array));\r
-       nsubs = 0;\r
-       for ( ; ; ) {\r
-               while (isascii(*cp) && isspace((unsigned char) *cp))\r
-                       ++cp;\r
-               if (*cp == '\0' || *cp == '#')\r
-                       break;\r
-               array[nsubs++] = dp = cp;\r
-               do {\r
-                       if ((*dp = *cp++) != '"')\r
-                               ++dp;\r
-                       else while ((*dp = *cp++) != '"')\r
-                               if (*dp != '\0')\r
-                                       ++dp;\r
-                               else    error(_("Odd number of quotation marks"));\r
-               } while (*cp != '\0' && *cp != '#' &&\r
-                       (!isascii(*cp) || !isspace((unsigned char) *cp)));\r
-               if (isascii(*cp) && isspace((unsigned char) *cp))\r
-                       ++cp;\r
-               *dp = '\0';\r
-       }\r
-       array[nsubs] = NULL;\r
-       return array;\r
-}\r
-\r
-static long\r
-oadd(t1, t2)\r
-const long     t1;\r
-const long     t2;\r
-{\r
-       register long   t;\r
-\r
-       t = t1 + t2;\r
-       if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {\r
-               error(_("time overflow"));\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       return t;\r
-}\r
-\r
-static time_t\r
-tadd(t1, t2)\r
-const time_t   t1;\r
-const long     t2;\r
-{\r
-       register time_t t;\r
-\r
-       if (t1 == max_time && t2 > 0)\r
-               return max_time;\r
-       if (t1 == min_time && t2 < 0)\r
-               return min_time;\r
-       t = t1 + t2;\r
-       if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {\r
-               error(_("time overflow"));\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       return t;\r
-}\r
-\r
-/*\r
-** Given a rule, and a year, compute the date - in seconds since January 1,\r
-** 1970, 00:00 LOCAL time - in that year that the rule refers to.\r
-*/\r
-\r
-static time_t\r
-rpytime(rp, wantedy)\r
-register const struct rule * const     rp;\r
-register const int                     wantedy;\r
-{\r
-       register int    y, m, i;\r
-       register long   dayoff;                 /* with a nod to Margaret O. */\r
-       register time_t t;\r
-\r
-       if (wantedy == INT_MIN)\r
-               return min_time;\r
-       if (wantedy == INT_MAX)\r
-               return max_time;\r
-       dayoff = 0;\r
-       m = TM_JANUARY;\r
-       y = EPOCH_YEAR;\r
-       while (wantedy != y) {\r
-               if (wantedy > y) {\r
-                       i = len_years[isleap(y)];\r
-                       ++y;\r
-               } else {\r
-                       --y;\r
-                       i = -len_years[isleap(y)];\r
-               }\r
-               dayoff = oadd(dayoff, eitol(i));\r
-       }\r
-       while (m != rp->r_month) {\r
-               i = len_months[isleap(y)][m];\r
-               dayoff = oadd(dayoff, eitol(i));\r
-               ++m;\r
-       }\r
-       i = rp->r_dayofmonth;\r
-       if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {\r
-               if (rp->r_dycode == DC_DOWLEQ)\r
-                       --i;\r
-               else {\r
-                       error(_("use of 2/29 in non leap-year"));\r
-                       (void) exit(EXIT_FAILURE);\r
-               }\r
-       }\r
-       --i;\r
-       dayoff = oadd(dayoff, eitol(i));\r
-       if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {\r
-               register long   wday;\r
-\r
-#define LDAYSPERWEEK   ((long) DAYSPERWEEK)\r
-               wday = eitol(EPOCH_WDAY);\r
-               /*\r
-               ** Don't trust mod of negative numbers.\r
-               */\r
-               if (dayoff >= 0)\r
-                       wday = (wday + dayoff) % LDAYSPERWEEK;\r
-               else {\r
-                       wday -= ((-dayoff) % LDAYSPERWEEK);\r
-                       if (wday < 0)\r
-                               wday += LDAYSPERWEEK;\r
-               }\r
-               while (wday != eitol(rp->r_wday))\r
-                       if (rp->r_dycode == DC_DOWGEQ) {\r
-                               dayoff = oadd(dayoff, (long) 1);\r
-                               if (++wday >= LDAYSPERWEEK)\r
-                                       wday = 0;\r
-                               ++i;\r
-                       } else {\r
-                               dayoff = oadd(dayoff, (long) -1);\r
-                               if (--wday < 0)\r
-                                       wday = LDAYSPERWEEK - 1;\r
-                               --i;\r
-                       }\r
-               if (i < 0 || i >= len_months[isleap(y)][m]) {\r
-                       error(_("no day in month matches rule"));\r
-                       (void) exit(EXIT_FAILURE);\r
-               }\r
-       }\r
-       if (dayoff < 0 && !TYPE_SIGNED(time_t))\r
-               return min_time;\r
-       if (dayoff < min_time / SECSPERDAY)\r
-               return min_time;\r
-       if (dayoff > max_time / SECSPERDAY)\r
-               return max_time;\r
-       t = (time_t) dayoff * SECSPERDAY;\r
-       return tadd(t, rp->r_tod);\r
-}\r
-\r
-static void\r
-newabbr(string)\r
-const char * const     string;\r
-{\r
-       register int    i;\r
-\r
-       i = strlen(string) + 1;\r
-       if (charcnt + i > TZ_MAX_CHARS) {\r
-               error(_("too many, or too long, time zone abbreviations"));\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       (void) strcpy(&chars[charcnt], string);\r
-       charcnt += eitol(i);\r
-}\r
-\r
-static int\r
-mkdirs(argname)\r
-char * const   argname;\r
-{\r
-       register char * name;\r
-       register char * cp;\r
-\r
-       if (argname == NULL || *argname == '\0')\r
-               return 0;\r
-       cp = name = ecpyalloc(argname);\r
-       while ((cp = strchr(cp + 1, '/')) != 0) {\r
-               *cp = '\0';\r
-#ifndef unix\r
-               /*\r
-               ** DOS drive specifier?\r
-               */\r
-               if (isalpha((unsigned char) name[0]) &&\r
-                       name[1] == ':' && name[2] == '\0') {\r
-                               *cp = '/';\r
-                               continue;\r
-               }\r
-#endif /* !defined unix */\r
-               if (!itsdir(name)) {\r
-                       /*\r
-                       ** It doesn't seem to exist, so we try to create it.\r
-                       ** Creation may fail because of the directory being\r
-                       ** created by some other multiprocessor, so we get\r
-                       ** to do extra checking.\r
-                       */\r
-                       if (mkdir(name, MKDIR_UMASK) != 0) {\r
-                               const char *e = strerror(errno);\r
-\r
-                               if (errno != EEXIST || !itsdir(name)) {\r
-                                       (void) fprintf(stderr,\r
-_("%s: Can't create directory %s: %s\n"),\r
-                                               progname, name, e);\r
-                                       ifree(name);\r
-                                       return -1;\r
-                               }\r
-                       }\r
-               }\r
-               *cp = '/';\r
-       }\r
-       ifree(name);\r
-       return 0;\r
-}\r
-\r
-static long\r
-eitol(i)\r
-const int      i;\r
-{\r
-       long    l;\r
-\r
-       l = i;\r
-       if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) {\r
-               (void) fprintf(stderr,\r
-                       _("%s: %d did not sign extend correctly\n"),\r
-                       progname, i);\r
-               (void) exit(EXIT_FAILURE);\r
-       }\r
-       return l;\r
-}\r
-\r
-/*\r
-** UNIX was a registered trademark of The Open Group in 2003.\r
-*/\r
-\r
-\r
-#ifdef WIN32\r
-/*\r
- * To run on win32 \r
- */\r
-int link(const char *oldpath, const char *newpath) {\r
-       if (!CopyFileEx(oldpath, newpath, NULL, NULL, FALSE, 0)) {\r
-               return -1;\r
-       }\r
-       return 0;\r
-}\r
-#endif\r
+static char    elsieid[] = "@(#)zic.c  7.115";
+#include "pgtz.h"
+#undef unlink
+#undef TZDIR
+#define TZDIR "data"
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include "private.h"
+#include "locale.h"
+#include "tzfile.h"
+
+#if HAVE_SYS_STAT_H
+#include "sys/stat.h"
+#endif
+#ifndef WIN32
+#ifdef S_IRUSR
+#define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
+#else
+#define MKDIR_UMASK 0755
+#endif
+#endif
+
+/*
+** On some ancient hosts, predicates like `isspace(C)' are defined
+** only if isascii(C) || C == EOF.  Modern hosts obey the C Standard,
+** which says they are defined only if C == ((unsigned char) C) || C == EOF.
+** Neither the C Standard nor Posix require that `isascii' exist.
+** For portability, we check both ancient and modern requirements.
+** If isascii is not defined, the isascii check succeeds trivially.
+*/
+#include "ctype.h"
+#ifndef isascii
+#define isascii(x) 1
+#endif
+
+struct rule {
+       const char *    r_filename;
+       int             r_linenum;
+       const char *    r_name;
+
+       int             r_loyear;       /* for example, 1986 */
+       int             r_hiyear;       /* for example, 1986 */
+       const char *    r_yrtype;
+
+       int             r_month;        /* 0..11 */
+
+       int             r_dycode;       /* see below */
+       int             r_dayofmonth;
+       int             r_wday;
+
+       long            r_tod;          /* time from midnight */
+       int             r_todisstd;     /* above is standard time if TRUE */
+                                       /* or wall clock time if FALSE */
+       int             r_todisgmt;     /* above is GMT if TRUE */
+                                       /* or local time if FALSE */
+       long            r_stdoff;       /* offset from standard time */
+       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 */
+};
+
+/*
+**     r_dycode                r_dayofmonth    r_wday
+*/
+
+#define DC_DOM         0       /* 1..31 */     /* unused */
+#define DC_DOWGEQ      1       /* 1..31 */     /* 0..6 (Sun..Sat) */
+#define DC_DOWLEQ      2       /* 1..31 */     /* 0..6 (Sun..Sat) */
+
+struct zone {
+       const char *    z_filename;
+       int             z_linenum;
+
+       const char *    z_name;
+       long            z_gmtoff;
+       const char *    z_rule;
+       const char *    z_format;
+
+       long            z_stdoff;
+
+       struct rule *   z_rules;
+       int             z_nrules;
+
+       struct rule     z_untilrule;
+       time_t          z_untiltime;
+};
+
+extern int     getopt P((int argc, char * const argv[],
+                       const char * options));
+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 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    adjleap P((void));
+static void    associate P((void));
+static int     ciequal P((const char * ap, const char * bp));
+static void    convert P((long val, char * buf));
+static void    dolink P((const char * fromfile, const char * tofile));
+static void    doabbr P((char * abbr, const char * format,
+                       const char * letters, int isdst));
+static void    eat P((const char * name, int num));
+static void    eats P((const char * name, int num,
+                       const char * rname, int rnum));
+static long    eitol P((int i));
+static void    error P((const char * message));
+static char ** getfields P((char * buf));
+static long    gethms P((const char * string, const char * errstrng,
+                       int signable));
+static void    infile P((const char * filename));
+static void    inleap P((char ** fields, int nfields));
+static void    inlink P((char ** fields, int nfields));
+static void    inrule P((char ** fields, int nfields));
+static int     inzcont P((char ** fields, int nfields));
+static int     inzone P((char ** fields, int nfields));
+static int     inzsub P((char ** fields, int nfields, int iscont));
+static int     itsabbr P((const char * abbr, const char * word));
+static int     itsdir P((const char * name));
+static int     lowerit P((int c));
+static char *  memcheck P((char * tocheck));
+static int     mkdirs P((char * filename));
+static void    newabbr P((const char * abbr));
+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 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 void    usage P((void));
+static void    writezone P((const char * name));
+static int     yearistype P((int year, const char * type));
+
+#if !(HAVE_STRERROR - 0)
+static char *  strerror P((int));
+#endif /* !(HAVE_STRERROR - 0) */
+
+static int             charcnt;
+static int             errors;
+static const char *    filename;
+static int             leapcnt;
+static int             linenum;
+static time_t          max_time;
+static int             max_year;
+static int             max_year_representable;
+static time_t          min_time;
+static int             min_year;
+static int             min_year_representable;
+static int             noise;
+static const char *    rfilename;
+static int             rlinenum;
+static const char *    progname;
+static int             timecnt;
+static int             typecnt;
+
+/*
+** Line codes.
+*/
+
+#define LC_RULE                0
+#define LC_ZONE                1
+#define LC_LINK                2
+#define LC_LEAP                3
+
+/*
+** Which fields are which on a Zone line.
+*/
+
+#define ZF_NAME                1
+#define ZF_GMTOFF      2
+#define ZF_RULE                3
+#define ZF_FORMAT      4
+#define ZF_TILYEAR     5
+#define ZF_TILMONTH    6
+#define ZF_TILDAY      7
+#define ZF_TILTIME     8
+#define ZONE_MINFIELDS 5
+#define ZONE_MAXFIELDS 9
+
+/*
+** Which fields are which on a Zone continuation line.
+*/
+
+#define ZFC_GMTOFF     0
+#define ZFC_RULE       1
+#define ZFC_FORMAT     2
+#define ZFC_TILYEAR    3
+#define ZFC_TILMONTH   4
+#define ZFC_TILDAY     5
+#define ZFC_TILTIME    6
+#define ZONEC_MINFIELDS        3
+#define ZONEC_MAXFIELDS        7
+
+/*
+** Which files are which on a Rule line.
+*/
+
+#define RF_NAME                1
+#define RF_LOYEAR      2
+#define RF_HIYEAR      3
+#define RF_COMMAND     4
+#define RF_MONTH       5
+#define RF_DAY         6
+#define RF_TOD         7
+#define RF_STDOFF      8
+#define RF_ABBRVAR     9
+#define RULE_FIELDS    10
+
+/*
+** Which fields are which on a Link line.
+*/
+
+#define LF_FROM                1
+#define LF_TO          2
+#define LINK_FIELDS    3
+
+/*
+** Which fields are which on a Leap line.
+*/
+
+#define LP_YEAR                1
+#define LP_MONTH       2
+#define LP_DAY         3
+#define LP_TIME                4
+#define LP_CORR                5
+#define LP_ROLL                6
+#define LEAP_FIELDS    7
+
+/*
+** Year synonyms.
+*/
+
+#define YR_MINIMUM     0
+#define YR_MAXIMUM     1
+#define YR_ONLY                2
+
+static struct rule *   rules;
+static int             nrules; /* number of rules */
+
+static struct zone *   zones;
+static int             nzones; /* number of zones */
+
+struct link {
+       const char *    l_filename;
+       int             l_linenum;
+       const char *    l_from;
+       const char *    l_to;
+};
+
+static struct link *   links;
+static int             nlinks;
+
+struct lookup {
+       const char *    l_word;
+       const int       l_value;
+};
+
+static struct lookup const *   byword P((const char * string,
+                                       const struct lookup * lp));
+
+static struct lookup const     line_codes[] = {
+       { "Rule",       LC_RULE },
+       { "Zone",       LC_ZONE },
+       { "Link",       LC_LINK },
+       { "Leap",       LC_LEAP },
+       { NULL,         0}
+};
+
+static struct lookup const     mon_names[] = {
+       { "January",    TM_JANUARY },
+       { "February",   TM_FEBRUARY },
+       { "March",      TM_MARCH },
+       { "April",      TM_APRIL },
+       { "May",        TM_MAY },
+       { "June",       TM_JUNE },
+       { "July",       TM_JULY },
+       { "August",     TM_AUGUST },
+       { "September",  TM_SEPTEMBER },
+       { "October",    TM_OCTOBER },
+       { "November",   TM_NOVEMBER },
+       { "December",   TM_DECEMBER },
+       { NULL,         0 }
+};
+
+static struct lookup const     wday_names[] = {
+       { "Sunday",     TM_SUNDAY },
+       { "Monday",     TM_MONDAY },
+       { "Tuesday",    TM_TUESDAY },
+       { "Wednesday",  TM_WEDNESDAY },
+       { "Thursday",   TM_THURSDAY },
+       { "Friday",     TM_FRIDAY },
+       { "Saturday",   TM_SATURDAY },
+       { NULL,         0 }
+};
+
+static struct lookup const     lasts[] = {
+       { "last-Sunday",        TM_SUNDAY },
+       { "last-Monday",        TM_MONDAY },
+       { "last-Tuesday",       TM_TUESDAY },
+       { "last-Wednesday",     TM_WEDNESDAY },
+       { "last-Thursday",      TM_THURSDAY },
+       { "last-Friday",        TM_FRIDAY },
+       { "last-Saturday",      TM_SATURDAY },
+       { NULL,                 0 }
+};
+
+static struct lookup const     begin_years[] = {
+       { "minimum",    YR_MINIMUM },
+       { "maximum",    YR_MAXIMUM },
+       { NULL,         0 }
+};
+
+static struct lookup const     end_years[] = {
+       { "minimum",    YR_MINIMUM },
+       { "maximum",    YR_MAXIMUM },
+       { "only",       YR_ONLY },
+       { NULL,         0 }
+};
+
+static struct lookup const     leap_types[] = {
+       { "Rolling",    TRUE },
+       { "Stationary", FALSE },
+       { NULL,         0 }
+};
+
+static const int       len_months[2][MONSPERYEAR] = {
+       { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+       { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static const int       len_years[2] = {
+       DAYSPERNYEAR, DAYSPERLYEAR
+};
+
+static struct attype {
+       time_t          at;
+       unsigned char   type;
+}                      attypes[TZ_MAX_TIMES];
+static long            gmtoffs[TZ_MAX_TYPES];
+static char            isdsts[TZ_MAX_TYPES];
+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 long            corr[TZ_MAX_LEAPS];
+static char            roll[TZ_MAX_LEAPS];
+
+/*
+** Memory allocation.
+*/
+
+static char *
+memcheck(ptr)
+char * const   ptr;
+{
+       if (ptr == NULL) {
+               const char *e = strerror(errno);
+
+               (void) fprintf(stderr, _("%s: Memory exhausted: %s\n"),
+                       progname, e);
+               (void) exit(EXIT_FAILURE);
+       }
+       return ptr;
+}
+
+#define emalloc(size)          memcheck(imalloc(size))
+#define erealloc(ptr, size)    memcheck(irealloc((ptr), (size)))
+#define ecpyalloc(ptr)         memcheck(icpyalloc(ptr))
+#define ecatalloc(oldp, newp)  memcheck(icatalloc((oldp), (newp)))
+
+/*
+** Error handling.
+*/
+
+#if !(HAVE_STRERROR - 0)
+static char *
+strerror(errnum)
+int    errnum;
+{
+       extern char *   sys_errlist[];
+       extern int      sys_nerr;
+
+       return (errnum > 0 && errnum <= sys_nerr) ?
+               sys_errlist[errnum] : _("Unknown system error");
+}
+#endif /* !(HAVE_STRERROR - 0) */
+
+static void
+eats(name, num, rname, rnum)
+const char * const     name;
+const int              num;
+const char * const     rname;
+const int              rnum;
+{
+       filename = name;
+       linenum = num;
+       rfilename = rname;
+       rlinenum = rnum;
+}
+
+static void
+eat(name, num)
+const char * const     name;
+const int              num;
+{
+       eats(name, num, (char *) NULL, -1);
+}
+
+static void
+error(string)
+const char * const     string;
+{
+       /*
+       ** Match the format of "cc" to allow sh users to
+       **      zic ... 2>&1 | error -t "*" -v
+       ** on BSD systems.
+       */
+       (void) fprintf(stderr, _("\"%s\", line %d: %s"),
+               filename, linenum, string);
+       if (rfilename != NULL)
+               (void) fprintf(stderr, _(" (rule from \"%s\", line %d)"),
+                       rfilename, rlinenum);
+       (void) fprintf(stderr, "\n");
+       ++errors;
+}
+
+static void
+warning(string)
+const char * const     string;
+{
+       char *  cp;
+
+       cp = ecpyalloc(_("warning: "));
+       cp = ecatalloc(cp, string);
+       error(cp);
+       ifree(cp);
+       --errors;
+}
+
+static void
+usage P((void))
+{
+       (void) fprintf(stderr, _("%s: usage is %s [ --version ] [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
+               progname, progname);
+       (void) exit(EXIT_FAILURE);
+}
+
+static const char *    psxrules;
+static const char *    lcltime;
+static const char *    directory;
+static const char *    leapsec;
+static const char *    yitcommand;
+static int             sflag = FALSE;
+
+int
+main(argc, argv)
+int    argc;
+char * argv[];
+{
+       register int    i;
+       register int    j;
+       register int    c;
+
+#ifdef unix
+       (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
+#endif /* defined unix */
+#if HAVE_GETTEXT - 0
+       (void) setlocale(LC_MESSAGES, "");
+#ifdef TZ_DOMAINDIR
+       (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
+#endif /* defined TEXTDOMAINDIR */
+       (void) textdomain(TZ_DOMAIN);
+#endif /* HAVE_GETTEXT - 0 */
+       progname = argv[0];
+       for (i = 1; i < argc; ++i)
+               if (strcmp(argv[i], "--version") == 0) {
+                       (void) printf("%s\n", elsieid);
+                       (void) exit(EXIT_SUCCESS);
+               }
+       while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
+               switch (c) {
+                       default:
+                               usage();
+                       case 'd':
+                               if (directory == NULL)
+                                       directory = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -d option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'l':
+                               if (lcltime == NULL)
+                                       lcltime = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -l option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'p':
+                               if (psxrules == NULL)
+                                       psxrules = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -p option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'y':
+                               if (yitcommand == NULL)
+                                       yitcommand = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -y option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'L':
+                               if (leapsec == NULL)
+                                       leapsec = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -L option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'v':
+                               noise = TRUE;
+                               break;
+                       case 's':
+                               sflag = TRUE;
+                               break;
+               }
+       if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
+               usage();        /* usage message by request */
+       if (directory == NULL)
+               directory = TZDIR;
+       if (yitcommand == NULL)
+               yitcommand = "yearistype";
+
+       setboundaries();
+
+       if (optind < argc && leapsec != NULL) {
+               infile(leapsec);
+               adjleap();
+       }
+
+       for (i = optind; i < argc; ++i)
+               infile(argv[i]);
+       if (errors)
+               (void) exit(EXIT_FAILURE);
+       associate();
+       for (i = 0; i < nzones; i = 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);
+       }
+       /*
+       ** Make links.
+       */
+       for (i = 0; i < nlinks; ++i) {
+               eat(links[i].l_filename, links[i].l_linenum);
+               dolink(links[i].l_from, links[i].l_to);
+       }
+       if (lcltime != NULL) {
+               eat("command line", 1);
+               dolink(lcltime, TZDEFAULT);
+       }
+       if (psxrules != NULL) {
+               eat("command line", 1);
+               dolink(psxrules, TZDEFRULES);
+       }
+       return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+static void
+dolink(fromfile, tofile)
+const char * const     fromfile;
+const char * const     tofile;
+{
+       register char * fromname;
+       register char * toname;
+
+       if (fromfile[0] == '/')
+               fromname = ecpyalloc(fromfile);
+       else {
+               fromname = ecpyalloc(directory);
+               fromname = ecatalloc(fromname, "/");
+               fromname = ecatalloc(fromname, fromfile);
+       }
+       if (tofile[0] == '/')
+               toname = ecpyalloc(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.
+       */
+       if (!itsdir(toname))
+               (void) remove(toname);
+       if (link(fromname, toname) != 0) {
+               int     result;
+
+               if (mkdirs(toname) != 0)
+                       (void) exit(EXIT_FAILURE);
+
+               result = link(fromname, toname);
+#if (HAVE_SYMLINK - 0)
+               if (result != 0 &&
+                   access(fromname, F_OK) == 0 &&
+                   !itsdir(fromname)) {
+                       const char *s = tofile;
+                       register char * symlinkcontents = NULL;
+                       while ((s = strchr(s+1, '/')) != NULL)
+                               symlinkcontents = ecatalloc(symlinkcontents, "../");
+                       symlinkcontents = ecatalloc(symlinkcontents, fromfile);
+
+                       result = symlink(symlinkcontents, toname);
+                       if (result == 0)
+warning(_("hard link failed, symbolic link used"));
+                       ifree(symlinkcontents);
+               }
+#endif
+               if (result != 0) {
+                       const char *e = strerror(errno);
+
+                       (void) fprintf(stderr,
+                               _("%s: Can't link from %s to %s: %s\n"),
+                               progname, fromname, toname, e);
+                       (void) exit(EXIT_FAILURE);
+               }
+       }
+       ifree(fromname);
+       ifree(toname);
+}
+
+#ifndef INT_MAX
+#define INT_MAX        ((int) (((unsigned)~0)>>1))
+#endif /* !defined INT_MAX */
+
+#ifndef INT_MIN
+#define INT_MIN        ((int) ~(((unsigned)~0)>>1))
+#endif /* !defined INT_MIN */
+
+/*
+** The tz file format currently allows at most 32-bit quantities.
+** This restriction should be removed before signed 32-bit values
+** wrap around in 2038, but unfortunately this will require a
+** change to the tz file format.
+*/
+
+#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)
+
+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;
+               if (sflag)
+                       min_time = 0;
+       } else {
+               min_time = 0;
+               max_time = 2 - sflag;
+               max_time <<= TIME_T_BITS_IN_FILE - 1;
+               --max_time;
+       }
+       min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
+       max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
+       min_year_representable = min_year;
+       max_year_representable = max_year;
+}
+
+static int
+itsdir(name)
+const char * const     name;
+{
+       register char * myname;
+       register int    accres;
+
+       myname = ecpyalloc(name);
+       myname = ecatalloc(myname, "/.");
+       accres = access(myname, F_OK);
+       ifree(myname);
+       return accres == 0;
+}
+
+/*
+** Associate sets of rules with zones.
+*/
+
+/*
+** Sort by rule name.
+*/
+
+static int
+rcomp(cp1, cp2)
+const void *   cp1;
+const void *   cp2;
+{
+       return strcmp(((const struct rule *) cp1)->r_name,
+               ((const struct rule *) cp2)->r_name);
+}
+
+static void
+associate P((void))
+{
+       register struct zone *  zp;
+       register struct rule *  rp;
+       register int            base, out;
+       register int            i, j;
+
+       if (nrules != 0) {
+               (void) qsort((void *) rules, (size_t) nrules,
+                       (size_t) sizeof *rules, rcomp);
+               for (i = 0; i < nrules - 1; ++i) {
+                       if (strcmp(rules[i].r_name,
+                               rules[i + 1].r_name) != 0)
+                                       continue;
+                       if (strcmp(rules[i].r_filename,
+                               rules[i + 1].r_filename) == 0)
+                                       continue;
+                       eat(rules[i].r_filename, rules[i].r_linenum);
+                       warning(_("same rule name in multiple files"));
+                       eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
+                       warning(_("same rule name in multiple files"));
+                       for (j = i + 2; j < nrules; ++j) {
+                               if (strcmp(rules[i].r_name,
+                                       rules[j].r_name) != 0)
+                                               break;
+                               if (strcmp(rules[i].r_filename,
+                                       rules[j].r_filename) == 0)
+                                               continue;
+                               if (strcmp(rules[i + 1].r_filename,
+                                       rules[j].r_filename) == 0)
+                                               continue;
+                               break;
+                       }
+                       i = j - 1;
+               }
+       }
+       for (i = 0; i < nzones; ++i) {
+               zp = &zones[i];
+               zp->z_rules = NULL;
+               zp->z_nrules = 0;
+       }
+       for (base = 0; base < nrules; base = out) {
+               rp = &rules[base];
+               for (out = base + 1; out < nrules; ++out)
+                       if (strcmp(rp->r_name, rules[out].r_name) != 0)
+                               break;
+               for (i = 0; i < nzones; ++i) {
+                       zp = &zones[i];
+                       if (strcmp(zp->z_rule, rp->r_name) != 0)
+                               continue;
+                       zp->z_rules = rp;
+                       zp->z_nrules = out - base;
+               }
+       }
+       for (i = 0; i < nzones; ++i) {
+               zp = &zones[i];
+               if (zp->z_nrules == 0) {
+                       /*
+                       ** Maybe we have a local standard time offset.
+                       */
+                       eat(zp->z_filename, zp->z_linenum);
+                       zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"),
+                                             TRUE);
+                       /*
+                       ** Note, though, that if there's no rule,
+                       ** a '%s' in the format is a bad thing.
+                       */
+                       if (strchr(zp->z_format, '%') != 0)
+                               error(_("%s in ruleless zone"));
+               }
+       }
+       if (errors)
+               (void) exit(EXIT_FAILURE);
+}
+
+static void
+infile(name)
+const char *   name;
+{
+       register FILE *                 fp;
+       register char **                fields;
+       register char *                 cp;
+       register const struct lookup *  lp;
+       register int                    nfields;
+       register int                    wantcont;
+       register int                    num;
+       char                            buf[BUFSIZ];
+
+       if (strcmp(name, "-") == 0) {
+               name = _("standard input");
+               fp = stdin;
+       } else if ((fp = fopen(name, "r")) == NULL) {
+               const char *e = strerror(errno);
+
+               (void) fprintf(stderr, _("%s: Can't open %s: %s\n"),
+                       progname, name, e);
+               (void) exit(EXIT_FAILURE);
+       }
+       wantcont = FALSE;
+       for (num = 1; ; ++num) {
+               eat(name, num);
+               if (fgets(buf, (int) sizeof buf, fp) != buf)
+                       break;
+               cp = strchr(buf, '\n');
+               if (cp == NULL) {
+                       error(_("line too long"));
+                       (void) exit(EXIT_FAILURE);
+               }
+               *cp = '\0';
+               fields = getfields(buf);
+               nfields = 0;
+               while (fields[nfields] != NULL) {
+                       static char     nada;
+
+                       if (strcmp(fields[nfields], "-") == 0)
+                               fields[nfields] = &nada;
+                       ++nfields;
+               }
+               if (nfields == 0) {
+                       /* nothing to do */
+               } else if (wantcont) {
+                       wantcont = inzcont(fields, nfields);
+               } else {
+                       lp = byword(fields[0], line_codes);
+                       if (lp == NULL)
+                               error(_("input line of unknown type"));
+                       else switch ((int) (lp->l_value)) {
+                               case LC_RULE:
+                                       inrule(fields, nfields);
+                                       wantcont = FALSE;
+                                       break;
+                               case LC_ZONE:
+                                       wantcont = inzone(fields, nfields);
+                                       break;
+                               case LC_LINK:
+                                       inlink(fields, nfields);
+                                       wantcont = FALSE;
+                                       break;
+                               case LC_LEAP:
+                                       if (name != leapsec)
+                                               (void) fprintf(stderr,
+_("%s: Leap line in non leap seconds file %s\n"),
+                                                       progname, name);
+                                       else    inleap(fields, nfields);
+                                       wantcont = FALSE;
+                                       break;
+                               default:        /* "cannot happen" */
+                                       (void) fprintf(stderr,
+_("%s: panic: Invalid l_value %d\n"),
+                                               progname, lp->l_value);
+                                       (void) exit(EXIT_FAILURE);
+                       }
+               }
+               ifree((char *) fields);
+       }
+       if (ferror(fp)) {
+               (void) fprintf(stderr, _("%s: Error reading %s\n"),
+                       progname, filename);
+               (void) exit(EXIT_FAILURE);
+       }
+       if (fp != stdin && fclose(fp)) {
+               const char *e = strerror(errno);
+
+               (void) fprintf(stderr, _("%s: Error closing %s: %s\n"),
+                       progname, filename, e);
+               (void) exit(EXIT_FAILURE);
+       }
+       if (wantcont)
+               error(_("expected continuation line not found"));
+}
+
+/*
+** Convert a string of one of the forms
+**     h       -h      hh:mm   -hh:mm  hh:mm:ss        -hh:mm:ss
+** into a number of seconds.
+** A null string maps to zero.
+** Call error with errstring and return zero on errors.
+*/
+
+static long
+gethms(string, errstring, signable)
+const char *           string;
+const char * const     errstring;
+const int              signable;
+{
+       int     hh, mm, ss, sign;
+
+       if (string == NULL || *string == '\0')
+               return 0;
+       if (!signable)
+               sign = 1;
+       else if (*string == '-') {
+               sign = -1;
+               ++string;
+       } else  sign = 1;
+       if (sscanf(string, scheck(string, "%d"), &hh) == 1)
+               mm = ss = 0;
+       else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)
+               ss = 0;
+       else if (sscanf(string, scheck(string, "%d:%d:%d"),
+               &hh, &mm, &ss) != 3) {
+                       error(errstring);
+                       return 0;
+       }
+       if ((hh < 0 || hh >= HOURSPERDAY ||
+               mm < 0 || mm >= MINSPERHOUR ||
+               ss < 0 || ss > SECSPERMIN) &&
+               !(hh == HOURSPERDAY && mm == 0 && ss == 0)) {
+                       error(errstring);
+                       return 0;
+       }
+       if (noise && hh == HOURSPERDAY)
+               warning(_("24:00 not handled by pre-1998 versions of zic"));
+       return eitol(sign) *
+               (eitol(hh * MINSPERHOUR + mm) *
+               eitol(SECSPERMIN) + eitol(ss));
+}
+
+static void
+inrule(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       static struct rule      r;
+
+       if (nfields != RULE_FIELDS) {
+               error(_("wrong number of fields on Rule line"));
+               return;
+       }
+       if (*fields[RF_NAME] == '\0') {
+               error(_("nameless rule"));
+               return;
+       }
+       r.r_filename = filename;
+       r.r_linenum = linenum;
+       r.r_stdoff = gethms(fields[RF_STDOFF], _("invalid saved time"), TRUE);
+       rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
+               fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
+       r.r_name = ecpyalloc(fields[RF_NAME]);
+       r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
+       rules = (struct rule *) (void *) erealloc((char *) rules,
+               (int) ((nrules + 1) * sizeof *rules));
+       rules[nrules++] = r;
+}
+
+static int
+inzone(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       register int    i;
+       static char *   buf;
+
+       if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
+               error(_("wrong number of fields on Zone line"));
+               return FALSE;
+       }
+       if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
+               buf = erealloc(buf, (int) (132 + strlen(TZDEFAULT)));
+               (void) sprintf(buf,
+_("\"Zone %s\" line and -l option are mutually exclusive"),
+                       TZDEFAULT);
+               error(buf);
+               return FALSE;
+       }
+       if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
+               buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES)));
+               (void) sprintf(buf,
+_("\"Zone %s\" line and -p option are mutually exclusive"),
+                       TZDEFRULES);
+               error(buf);
+               return FALSE;
+       }
+       for (i = 0; i < nzones; ++i)
+               if (zones[i].z_name != NULL &&
+                       strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
+                               buf = erealloc(buf, (int) (132 +
+                                       strlen(fields[ZF_NAME]) +
+                                       strlen(zones[i].z_filename)));
+                               (void) sprintf(buf,
+_("duplicate zone name %s (file \"%s\", line %d)"),
+                                       fields[ZF_NAME],
+                                       zones[i].z_filename,
+                                       zones[i].z_linenum);
+                               error(buf);
+                               return FALSE;
+               }
+       return inzsub(fields, nfields, FALSE);
+}
+
+static int
+inzcont(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
+               error(_("wrong number of fields on Zone continuation line"));
+               return FALSE;
+       }
+       return inzsub(fields, nfields, TRUE);
+}
+
+static int
+inzsub(fields, nfields, iscont)
+register char ** const fields;
+const int              nfields;
+const int              iscont;
+{
+       register char *         cp;
+       static struct zone      z;
+       register int            i_gmtoff, i_rule, i_format;
+       register int            i_untilyear, i_untilmonth;
+       register int            i_untilday, i_untiltime;
+       register int            hasuntil;
+
+       if (iscont) {
+               i_gmtoff = ZFC_GMTOFF;
+               i_rule = ZFC_RULE;
+               i_format = ZFC_FORMAT;
+               i_untilyear = ZFC_TILYEAR;
+               i_untilmonth = ZFC_TILMONTH;
+               i_untilday = ZFC_TILDAY;
+               i_untiltime = ZFC_TILTIME;
+               z.z_name = NULL;
+       } else {
+               i_gmtoff = ZF_GMTOFF;
+               i_rule = ZF_RULE;
+               i_format = ZF_FORMAT;
+               i_untilyear = ZF_TILYEAR;
+               i_untilmonth = ZF_TILMONTH;
+               i_untilday = ZF_TILDAY;
+               i_untiltime = ZF_TILTIME;
+               z.z_name = ecpyalloc(fields[ZF_NAME]);
+       }
+       z.z_filename = filename;
+       z.z_linenum = linenum;
+       z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UTC offset"), TRUE);
+       if ((cp = strchr(fields[i_format], '%')) != 0) {
+               if (*++cp != 's' || strchr(cp, '%') != 0) {
+                       error(_("invalid abbreviation format"));
+                       return FALSE;
+               }
+       }
+       z.z_rule = ecpyalloc(fields[i_rule]);
+       z.z_format = ecpyalloc(fields[i_format]);
+       hasuntil = nfields > i_untilyear;
+       if (hasuntil) {
+               z.z_untilrule.r_filename = filename;
+               z.z_untilrule.r_linenum = linenum;
+               rulesub(&z.z_untilrule,
+                       fields[i_untilyear],
+                       "only",
+                       "",
+                       (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 > 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;
+               }
+       }
+       zones = (struct zone *) (void *) erealloc((char *) zones,
+               (int) ((nzones + 1) * sizeof *zones));
+       zones[nzones++] = z;
+       /*
+       ** If there was an UNTIL field on this line,
+       ** there's more information about the zone on the next line.
+       */
+       return hasuntil;
+}
+
+static void
+inleap(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       register const char *           cp;
+       register const struct lookup *  lp;
+       register int                    i, j;
+       int                             year, month, day;
+       long                            dayoff, tod;
+       time_t                          t;
+
+       if (nfields != LEAP_FIELDS) {
+               error(_("wrong number of fields on Leap line"));
+               return;
+       }
+       dayoff = 0;
+       cp = fields[LP_YEAR];
+       if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {
+                       /*
+                        * Leapin' Lizards!
+                        */
+                       error(_("invalid leaping year"));
+                       return;
+       }
+       j = EPOCH_YEAR;
+       while (j != year) {
+               if (year > j) {
+                       i = len_years[isleap(j)];
+                       ++j;
+               } else {
+                       --j;
+                       i = -len_years[isleap(j)];
+               }
+               dayoff = oadd(dayoff, eitol(i));
+       }
+       if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
+               error(_("invalid month name"));
+               return;
+       }
+       month = lp->l_value;
+       j = TM_JANUARY;
+       while (j != month) {
+               i = len_months[isleap(year)][j];
+               dayoff = oadd(dayoff, eitol(i));
+               ++j;
+       }
+       cp = fields[LP_DAY];
+       if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
+               day <= 0 || day > len_months[isleap(year)][month]) {
+                       error(_("invalid day of month"));
+                       return;
+       }
+       dayoff = oadd(dayoff, eitol(day - 1));
+       if (dayoff < 0 && !TYPE_SIGNED(time_t)) {
+               error(_("time before zero"));
+               return;
+       }
+       if (dayoff < min_time / SECSPERDAY) {
+               error(_("time too small"));
+               return;
+       }
+       if (dayoff > max_time / SECSPERDAY) {
+               error(_("time too large"));
+               return;
+       }
+       t = (time_t) dayoff * SECSPERDAY;
+       tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
+       cp = fields[LP_CORR];
+       {
+               register int    positive;
+               int             count;
+
+               if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
+                       positive = FALSE;
+                       count = 1;
+               } else if (strcmp(cp, "--") == 0) {
+                       positive = FALSE;
+                       count = 2;
+               } else if (strcmp(cp, "+") == 0) {
+                       positive = TRUE;
+                       count = 1;
+               } else if (strcmp(cp, "++") == 0) {
+                       positive = TRUE;
+                       count = 2;
+               } else {
+                       error(_("illegal CORRECTION field on Leap line"));
+                       return;
+               }
+               if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
+                       error(_("illegal Rolling/Stationary field on Leap line"));
+                       return;
+               }
+               leapadd(tadd(t, tod), positive, lp->l_value, count);
+       }
+}
+
+static void
+inlink(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       struct link     l;
+
+       if (nfields != LINK_FIELDS) {
+               error(_("wrong number of fields on Link line"));
+               return;
+       }
+       if (*fields[LF_FROM] == '\0') {
+               error(_("blank FROM field on Link line"));
+               return;
+       }
+       if (*fields[LF_TO] == '\0') {
+               error(_("blank TO field on Link line"));
+               return;
+       }
+       l.l_filename = filename;
+       l.l_linenum = linenum;
+       l.l_from = ecpyalloc(fields[LF_FROM]);
+       l.l_to = ecpyalloc(fields[LF_TO]);
+       links = (struct link *) (void *) erealloc((char *) links,
+               (int) ((nlinks + 1) * sizeof *links));
+       links[nlinks++] = l;
+}
+
+static void
+rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
+register struct rule * const   rp;
+const char * const             loyearp;
+const char * const             hiyearp;
+const char * const             typep;
+const char * const             monthp;
+const char * const             dayp;
+const char * const             timep;
+{
+       register const struct lookup *  lp;
+       register const char *           cp;
+       register char *                 dp;
+       register char *                 ep;
+
+       if ((lp = byword(monthp, mon_names)) == NULL) {
+               error(_("invalid month name"));
+               return;
+       }
+       rp->r_month = lp->l_value;
+       rp->r_todisstd = FALSE;
+       rp->r_todisgmt = FALSE;
+       dp = ecpyalloc(timep);
+       if (*dp != '\0') {
+               ep = dp + strlen(dp) - 1;
+               switch (lowerit(*ep)) {
+                       case 's':       /* Standard */
+                               rp->r_todisstd = TRUE;
+                               rp->r_todisgmt = FALSE;
+                               *ep = '\0';
+                               break;
+                       case 'w':       /* Wall */
+                               rp->r_todisstd = FALSE;
+                               rp->r_todisgmt = FALSE;
+                               *ep = '\0';
+                               break;
+                       case 'g':       /* Greenwich */
+                       case 'u':       /* Universal */
+                       case 'z':       /* Zulu */
+                               rp->r_todisstd = TRUE;
+                               rp->r_todisgmt = TRUE;
+                               *ep = '\0';
+                               break;
+               }
+       }
+       rp->r_tod = gethms(dp, _("invalid time of day"), FALSE);
+       ifree(dp);
+       /*
+       ** Year work.
+       */
+       cp = loyearp;
+       lp = byword(cp, begin_years);
+       if (lp != NULL) switch ((int) lp->l_value) {
+               case YR_MINIMUM:
+                       rp->r_loyear = INT_MIN;
+                       break;
+               case YR_MAXIMUM:
+                       rp->r_loyear = INT_MAX;
+                       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) {
+               error(_("invalid starting year"));
+               return;
+       } else if (noise) {
+               if (rp->r_loyear < min_year_representable)
+                       warning(_("starting year too low to be represented"));
+               else if (rp->r_loyear > max_year_representable)
+                       warning(_("starting year too high to be represented"));
+       }
+       cp = hiyearp;
+       if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
+               case YR_MINIMUM:
+                       rp->r_hiyear = INT_MIN;
+                       break;
+               case YR_MAXIMUM:
+                       rp->r_hiyear = INT_MAX;
+                       break;
+               case YR_ONLY:
+                       rp->r_hiyear = rp->r_loyear;
+                       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_hiyear) != 1) {
+               error(_("invalid ending year"));
+               return;
+       } else if (noise) {
+               if (rp->r_loyear < min_year_representable)
+                       warning(_("ending year too low to be represented"));
+               else if (rp->r_loyear > max_year_representable)
+                       warning(_("ending year too high to be represented"));
+       }
+       if (rp->r_loyear > rp->r_hiyear) {
+               error(_("starting year greater than ending year"));
+               return;
+       }
+       if (*typep == '\0')
+               rp->r_yrtype = NULL;
+       else {
+               if (rp->r_loyear == rp->r_hiyear) {
+                       error(_("typed single year"));
+                       return;
+               }
+               rp->r_yrtype = ecpyalloc(typep);
+       }
+       if (rp->r_loyear < min_year && rp->r_loyear > 0)
+               min_year = rp->r_loyear;
+       /*
+       ** Day work.
+       ** Accept things such as:
+       **      1
+       **      last-Sunday
+       **      Sun<=20
+       **      Sun>=7
+       */
+       dp = ecpyalloc(dayp);
+       if ((lp = byword(dp, lasts)) != NULL) {
+               rp->r_dycode = DC_DOWLEQ;
+               rp->r_wday = lp->l_value;
+               rp->r_dayofmonth = len_months[1][rp->r_month];
+       } else {
+               if ((ep = strchr(dp, '<')) != 0)
+                       rp->r_dycode = DC_DOWLEQ;
+               else if ((ep = strchr(dp, '>')) != 0)
+                       rp->r_dycode = DC_DOWGEQ;
+               else {
+                       ep = dp;
+                       rp->r_dycode = DC_DOM;
+               }
+               if (rp->r_dycode != DC_DOM) {
+                       *ep++ = 0;
+                       if (*ep++ != '=') {
+                               error(_("invalid day of month"));
+                               ifree(dp);
+                               return;
+                       }
+                       if ((lp = byword(dp, wday_names)) == NULL) {
+                               error(_("invalid weekday name"));
+                               ifree(dp);
+                               return;
+                       }
+                       rp->r_wday = lp->l_value;
+               }
+               if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 ||
+                       rp->r_dayofmonth <= 0 ||
+                       (rp->r_dayofmonth > len_months[1][rp->r_month])) {
+                               error(_("invalid day of month"));
+                               ifree(dp);
+                               return;
+               }
+       }
+       ifree(dp);
+}
+
+static void
+convert(val, buf)
+const long     val;
+char * const   buf;
+{
+       register int    i;
+       register long   shift;
+
+       for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
+               buf[i] = val >> shift;
+}
+
+static void
+puttzcode(val, fp)
+const long     val;
+FILE * const   fp;
+{
+       char    buf[4];
+
+       convert(val, buf);
+       (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
+}
+
+static int
+atcomp(avp, bvp)
+void * avp;
+void * bvp;
+{
+       if (((struct attype *) avp)->at < ((struct attype *) bvp)->at)
+               return -1;
+       else if (((struct attype *) avp)->at > ((struct attype *) bvp)->at)
+               return 1;
+       else    return 0;
+}
+
+static void
+writezone(name)
+const char * const     name;
+{
+       register FILE *         fp;
+       register int            i, j;
+       static char *           fullname;
+       static struct tzhead    tzh;
+       time_t                  ats[TZ_MAX_TIMES];
+       unsigned char           types[TZ_MAX_TIMES];
+
+       /*
+       ** Sort.
+       */
+       if (timecnt > 1)
+               (void) qsort((void *) attypes, (size_t) timecnt,
+                       (size_t) sizeof *attypes, atcomp);
+       /*
+       ** Optimize.
+       */
+       {
+               int     fromi;
+               int     toi;
+
+               toi = 0;
+               fromi = 0;
+               while (fromi < timecnt && attypes[fromi].at < min_time)
+                       ++fromi;
+               if (isdsts[0] == 0)
+                       while (fromi < timecnt && attypes[fromi].type == 0)
+                               ++fromi;        /* handled by default rule */
+               for ( ; fromi < timecnt; ++fromi) {
+                       if (toi != 0
+                           && ((attypes[fromi].at
+                                + gmtoffs[attypes[toi - 1].type])
+                               <= (attypes[toi - 1].at
+                                   + gmtoffs[toi == 1 ? 0
+                                             : attypes[toi - 2].type]))) {
+                               attypes[toi - 1].type = attypes[fromi].type;
+                               continue;
+                       }
+                       if (toi == 0 ||
+                               attypes[toi - 1].type != attypes[fromi].type)
+                                       attypes[toi++] = attypes[fromi];
+               }
+               timecnt = toi;
+       }
+       /*
+       ** Transfer.
+       */
+       for (i = 0; i < timecnt; ++i) {
+               ats[i] = attypes[i].at;
+               types[i] = attypes[i].type;
+       }
+       fullname = erealloc(fullname,
+               (int) (strlen(directory) + 1 + strlen(name) + 1));
+       (void) sprintf(fullname, "%s/%s", directory, name);
+       /*
+       ** Remove old file, if any, to snap links.
+       */
+       if (!itsdir(fullname) && remove(fullname) != 0 && errno != ENOENT) {
+               const char *e = strerror(errno);
+
+               (void) fprintf(stderr, _("%s: Can't remove %s: %s\n"),
+                       progname, fullname, e);
+               (void) exit(EXIT_FAILURE);
+       }
+       if ((fp = fopen(fullname, "wb")) == NULL) {
+               if (mkdirs(fullname) != 0)
+                       (void) exit(EXIT_FAILURE);
+               if ((fp = fopen(fullname, "wb")) == NULL) {
+                       const char *e = strerror(errno);
+
+                       (void) fprintf(stderr, _("%s: Can't create %s: %s\n"),
+                               progname, fullname, e);
+                       (void) exit(EXIT_FAILURE);
+               }
+       }
+       convert(eitol(typecnt), tzh.tzh_ttisgmtcnt);
+       convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
+       convert(eitol(leapcnt), tzh.tzh_leapcnt);
+       convert(eitol(timecnt), tzh.tzh_timecnt);
+       convert(eitol(typecnt), tzh.tzh_typecnt);
+       convert(eitol(charcnt), tzh.tzh_charcnt);
+       (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
+#define DO(field)      (void) fwrite((void *) tzh.field, (size_t) sizeof tzh.field, (size_t) 1, fp)
+       DO(tzh_magic);
+       DO(tzh_reserved);
+       DO(tzh_ttisgmtcnt);
+       DO(tzh_ttisstdcnt);
+       DO(tzh_leapcnt);
+       DO(tzh_timecnt);
+       DO(tzh_typecnt);
+       DO(tzh_charcnt);
+#undef DO
+       for (i = 0; i < timecnt; ++i) {
+               j = leapcnt;
+               while (--j >= 0)
+                       if (ats[i] >= trans[j]) {
+                               ats[i] = tadd(ats[i], corr[j]);
+                               break;
+                       }
+               puttzcode((long) ats[i], fp);
+       }
+       if (timecnt > 0)
+               (void) fwrite((void *) types, (size_t) sizeof types[0],
+                       (size_t) timecnt, fp);
+       for (i = 0; i < typecnt; ++i) {
+               puttzcode((long) gmtoffs[i], fp);
+               (void) putc(isdsts[i], fp);
+               (void) putc(abbrinds[i], fp);
+       }
+       if (charcnt != 0)
+               (void) fwrite((void *) chars, (size_t) sizeof chars[0],
+                       (size_t) charcnt, fp);
+       for (i = 0; i < leapcnt; ++i) {
+               if (roll[i]) {
+                       if (timecnt == 0 || trans[i] < ats[0]) {
+                               j = 0;
+                               while (isdsts[j])
+                                       if (++j >= typecnt) {
+                                               j = 0;
+                                               break;
+                                       }
+                       } else {
+                               j = 1;
+                               while (j < timecnt && trans[i] >= ats[j])
+                                       ++j;
+                               j = types[j - 1];
+                       }
+                       puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
+               } else  puttzcode((long) trans[i], fp);
+               puttzcode((long) corr[i], fp);
+       }
+       for (i = 0; i < typecnt; ++i)
+               (void) putc(ttisstds[i], fp);
+       for (i = 0; i < typecnt; ++i)
+               (void) putc(ttisgmts[i], fp);
+       if (ferror(fp) || fclose(fp)) {
+               (void) fprintf(stderr, _("%s: Error writing %s\n"),
+                       progname, fullname);
+               (void) exit(EXIT_FAILURE);
+       }
+}
+
+static void
+doabbr(abbr, format, letters, isdst)
+char * const           abbr;
+const char * const     format;
+const char * const     letters;
+const int              isdst;
+{
+       if (strchr(format, '/') == NULL) {
+               if (letters == NULL)
+                       (void) strcpy(abbr, format);
+               else    (void) sprintf(abbr, format, letters);
+       } else if (isdst)
+               (void) strcpy(abbr, strchr(format, '/') + 1);
+       else {
+               (void) strcpy(abbr, format);
+               *strchr(abbr, '/') = '\0';
+       }
+}
+
+static void
+outzone(zpfirst, zonecount)
+const struct zone * const      zpfirst;
+const int                      zonecount;
+{
+       register const struct zone *    zp;
+       register struct rule *          rp;
+       register int                    i, j;
+       register int                    usestart, useuntil;
+       register time_t                 starttime, untiltime;
+       register long                   gmtoff;
+       register long                   stdoff;
+       register int                    year;
+       register long                   startoff;
+       register int                    startttisstd;
+       register int                    startttisgmt;
+       register int                    type;
+       char                            startbuf[BUFSIZ];
+
+       INITIALIZE(untiltime);
+       INITIALIZE(starttime);
+       /*
+       ** Now. . .finally. . .generate some useful data!
+       */
+       timecnt = 0;
+       typecnt = 0;
+       charcnt = 0;
+       /*
+       ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au)
+       ** for noting the need to unconditionally initialize startttisstd.
+       */
+       startttisstd = FALSE;
+       startttisgmt = FALSE;
+       for (i = 0; i < zonecount; ++i) {
+               /*
+               ** A guess that may well be corrected later.
+               */
+               stdoff = 0;
+               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);
+               *startbuf = '\0';
+               startoff = zp->z_gmtoff;
+               if (zp->z_nrules == 0) {
+                       stdoff = zp->z_stdoff;
+                       doabbr(startbuf, zp->z_format,
+                               (char *) NULL, stdoff != 0);
+                       type = addtype(oadd(zp->z_gmtoff, stdoff),
+                               startbuf, stdoff != 0, startttisstd,
+                               startttisgmt);
+                       if (usestart) {
+                               addtt(starttime, type);
+                               usestart = FALSE;
+                       } 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;
+                       /*
+                       ** Mark which rules to do in the current year.
+                       ** For those to do, calculate rpytime(rp, year);
+                       */
+                       for (j = 0; j < zp->z_nrules; ++j) {
+                               rp = &zp->z_rules[j];
+                               eats(zp->z_filename, zp->z_linenum,
+                                       rp->r_filename, rp->r_linenum);
+                               rp->r_todo = year >= rp->r_loyear &&
+                                               year <= rp->r_hiyear &&
+                                               yearistype(year, rp->r_yrtype);
+                               if (rp->r_todo)
+                                       rp->r_temp = rpytime(rp, year);
+                       }
+                       for ( ; ; ) {
+                               register int    k;
+                               register time_t jtime, ktime;
+                               register long   offset;
+                               char            buf[BUFSIZ];
+
+                               INITIALIZE(ktime);
+                               if (useuntil) {
+                                       /*
+                                       ** Turn untiltime into UTC
+                                       ** assuming the current gmtoff and
+                                       ** stdoff values.
+                                       */
+                                       untiltime = zp->z_untiltime;
+                                       if (!zp->z_untilrule.r_todisgmt)
+                                               untiltime = tadd(untiltime,
+                                                       -gmtoff);
+                                       if (!zp->z_untilrule.r_todisstd)
+                                               untiltime = tadd(untiltime,
+                                                       -stdoff);
+                               }
+                               /*
+                               ** Find the rule (of those to do, if any)
+                               ** that takes effect earliest in the year.
+                               */
+                               k = -1;
+                               for (j = 0; j < zp->z_nrules; ++j) {
+                                       rp = &zp->z_rules[j];
+                                       if (!rp->r_todo)
+                                               continue;
+                                       eats(zp->z_filename, zp->z_linenum,
+                                               rp->r_filename, rp->r_linenum);
+                                       offset = rp->r_todisgmt ? 0 : gmtoff;
+                                       if (!rp->r_todisstd)
+                                               offset = oadd(offset, stdoff);
+                                       jtime = rp->r_temp;
+                                       if (jtime == min_time ||
+                                               jtime == max_time)
+                                                       continue;
+                                       jtime = tadd(jtime, -offset);
+                                       if (k < 0 || jtime < ktime) {
+                                               k = j;
+                                               ktime = jtime;
+                                       }
+                               }
+                               if (k < 0)
+                                       break;  /* go on to next year */
+                               rp = &zp->z_rules[k];
+                               rp->r_todo = FALSE;
+                               if (useuntil && ktime >= untiltime)
+                                       break;
+                               stdoff = rp->r_stdoff;
+                               if (usestart && ktime == starttime)
+                                       usestart = FALSE;
+                               if (usestart) {
+                                       if (ktime < starttime) {
+                                               startoff = oadd(zp->z_gmtoff,
+                                                       stdoff);
+                                               doabbr(startbuf, zp->z_format,
+                                                       rp->r_abbrvar,
+                                                       rp->r_stdoff != 0);
+                                               continue;
+                                       }
+                                       if (*startbuf == '\0' &&
+                                           startoff == oadd(zp->z_gmtoff,
+                                           stdoff)) {
+                                               doabbr(startbuf, zp->z_format,
+                                                       rp->r_abbrvar,
+                                                       rp->r_stdoff != 0);
+                                       }
+                               }
+                               eats(zp->z_filename, zp->z_linenum,
+                                       rp->r_filename, rp->r_linenum);
+                               doabbr(buf, zp->z_format, rp->r_abbrvar,
+                                       rp->r_stdoff != 0);
+                               offset = oadd(zp->z_gmtoff, rp->r_stdoff);
+                               type = addtype(offset, buf, rp->r_stdoff != 0,
+                                       rp->r_todisstd, rp->r_todisgmt);
+                               addtt(ktime, type);
+                       }
+               }
+               if (usestart) {
+                       if (*startbuf == '\0' &&
+                               zp->z_format != NULL &&
+                               strchr(zp->z_format, '%') == NULL &&
+                               strchr(zp->z_format, '/') == NULL)
+                                       (void) strcpy(startbuf, zp->z_format);
+                       eat(zp->z_filename, zp->z_linenum);
+                       if (*startbuf == '\0')
+error(_("can't determine time zone abbreviation to use just after until time"));
+                       else    addtt(starttime,
+                                       addtype(startoff, startbuf,
+                                               startoff != zp->z_gmtoff,
+                                               startttisstd,
+                                               startttisgmt));
+               }
+               /*
+               ** Now we may get to set starttime for the next zone line.
+               */
+               if (useuntil) {
+                       startttisstd = zp->z_untilrule.r_todisstd;
+                       startttisgmt = zp->z_untilrule.r_todisgmt;
+                       starttime = zp->z_untiltime;
+                       if (!startttisstd)
+                               starttime = tadd(starttime, -stdoff);
+                       if (!startttisgmt)
+                               starttime = tadd(starttime, -gmtoff);
+               }
+       }
+       writezone(zpfirst->z_name);
+}
+
+static void
+addtt(starttime, type)
+const time_t   starttime;
+int            type;
+{
+       if (starttime <= min_time ||
+               (timecnt == 1 && attypes[0].at < min_time)) {
+               gmtoffs[0] = gmtoffs[type];
+               isdsts[0] = isdsts[type];
+               ttisstds[0] = ttisstds[type];
+               ttisgmts[0] = ttisgmts[type];
+               if (abbrinds[type] != 0)
+                       (void) strcpy(chars, &chars[abbrinds[type]]);
+               abbrinds[0] = 0;
+               charcnt = strlen(chars) + 1;
+               typecnt = 1;
+               timecnt = 0;
+               type = 0;
+       }
+       if (timecnt >= TZ_MAX_TIMES) {
+               error(_("too many transitions?!"));
+               (void) exit(EXIT_FAILURE);
+       }
+       attypes[timecnt].at = starttime;
+       attypes[timecnt].type = type;
+       ++timecnt;
+}
+
+static int
+addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt)
+const long             gmtoff;
+const char * const     abbr;
+const int              isdst;
+const int              ttisstd;
+const int              ttisgmt;
+{
+       register int    i, j;
+
+       if (isdst != TRUE && isdst != FALSE) {
+               error(_("internal error - addtype called with bad isdst"));
+               (void) exit(EXIT_FAILURE);
+       }
+       if (ttisstd != TRUE && ttisstd != FALSE) {
+               error(_("internal error - addtype called with bad ttisstd"));
+               (void) exit(EXIT_FAILURE);
+       }
+       if (ttisgmt != TRUE && ttisgmt != FALSE) {
+               error(_("internal error - addtype called with bad ttisgmt"));
+               (void) exit(EXIT_FAILURE);
+       }
+       /*
+       ** See if there's already an entry for this zone type.
+       ** If so, just return its index.
+       */
+       for (i = 0; i < typecnt; ++i) {
+               if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
+                       strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
+                       ttisstd == ttisstds[i] &&
+                       ttisgmt == ttisgmts[i])
+                               return i;
+       }
+       /*
+       ** There isn't one; add a new one, unless there are already too
+       ** many.
+       */
+       if (typecnt >= TZ_MAX_TYPES) {
+               error(_("too many local time types"));
+               (void) exit(EXIT_FAILURE);
+       }
+       gmtoffs[i] = gmtoff;
+       isdsts[i] = isdst;
+       ttisstds[i] = ttisstd;
+       ttisgmts[i] = ttisgmt;
+
+       for (j = 0; j < charcnt; ++j)
+               if (strcmp(&chars[j], abbr) == 0)
+                       break;
+       if (j == charcnt)
+               newabbr(abbr);
+       abbrinds[i] = j;
+       ++typecnt;
+       return i;
+}
+
+static void
+leapadd(t, positive, rolling, count)
+const time_t   t;
+const int      positive;
+const int      rolling;
+int            count;
+{
+       register int    i, j;
+
+       if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {
+               error(_("too many leap seconds"));
+               (void) exit(EXIT_FAILURE);
+       }
+       for (i = 0; i < leapcnt; ++i)
+               if (t <= trans[i]) {
+                       if (t == trans[i]) {
+                               error(_("repeated leap second moment"));
+                               (void) exit(EXIT_FAILURE);
+                       }
+                       break;
+               }
+       do {
+               for (j = leapcnt; j > i; --j) {
+                       trans[j] = trans[j - 1];
+                       corr[j] = corr[j - 1];
+                       roll[j] = roll[j - 1];
+               }
+               trans[i] = t;
+               corr[i] = positive ? 1L : eitol(-count);
+               roll[i] = rolling;
+               ++leapcnt;
+       } while (positive && --count != 0);
+}
+
+static void
+adjleap P((void))
+{
+       register int    i;
+       register long   last = 0;
+
+       /*
+       ** propagate leap seconds forward
+       */
+       for (i = 0; i < leapcnt; ++i) {
+               trans[i] = tadd(trans[i], last);
+               last = corr[i] += last;
+       }
+}
+
+static int
+yearistype(year, type)
+const int              year;
+const char * const     type;
+{
+       static char *   buf;
+       int             result;
+
+       if (type == NULL || *type == '\0')
+               return TRUE;
+       buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type)));
+       (void) sprintf(buf, "%s %d %s", yitcommand, year, type);
+       result = system(buf);
+       if (WIFEXITED(result)) switch (WEXITSTATUS(result)) {
+               case 0:
+                       return TRUE;
+               case 1:
+                       return FALSE;
+       }
+       error(_("Wild result from command execution"));
+       (void) fprintf(stderr, _("%s: command was '%s', result was %d\n"),
+               progname, buf, result);
+       for ( ; ; )
+               (void) exit(EXIT_FAILURE);
+}
+
+static int
+lowerit(a)
+int    a;
+{
+       a = (unsigned char) a;
+       return (isascii(a) && isupper(a)) ? tolower(a) : a;
+}
+
+static int
+ciequal(ap, bp)                /* case-insensitive equality */
+register const char *  ap;
+register const char *  bp;
+{
+       while (lowerit(*ap) == lowerit(*bp++))
+               if (*ap++ == '\0')
+                       return TRUE;
+       return FALSE;
+}
+
+static int
+itsabbr(abbr, word)
+register const char *  abbr;
+register const char *  word;
+{
+       if (lowerit(*abbr) != lowerit(*word))
+               return FALSE;
+       ++word;
+       while (*++abbr != '\0')
+               do {
+                       if (*word == '\0')
+                               return FALSE;
+               } while (lowerit(*word++) != lowerit(*abbr));
+       return TRUE;
+}
+
+static const struct lookup *
+byword(word, table)
+register const char * const            word;
+register const struct lookup * const   table;
+{
+       register const struct lookup *  foundlp;
+       register const struct lookup *  lp;
+
+       if (word == NULL || table == NULL)
+               return NULL;
+       /*
+       ** Look for exact match.
+       */
+       for (lp = table; lp->l_word != NULL; ++lp)
+               if (ciequal(word, lp->l_word))
+                       return lp;
+       /*
+       ** Look for inexact match.
+       */
+       foundlp = NULL;
+       for (lp = table; lp->l_word != NULL; ++lp)
+               if (itsabbr(word, lp->l_word)) {
+                       if (foundlp == NULL)
+                               foundlp = lp;
+                       else    return NULL;    /* multiple inexact matches */
+               }
+       return foundlp;
+}
+
+static char **
+getfields(cp)
+register char *        cp;
+{
+       register char *         dp;
+       register char **        array;
+       register int            nsubs;
+
+       if (cp == NULL)
+               return NULL;
+       array = (char **) (void *)
+               emalloc((int) ((strlen(cp) + 1) * sizeof *array));
+       nsubs = 0;
+       for ( ; ; ) {
+               while (isascii(*cp) && isspace((unsigned char) *cp))
+                       ++cp;
+               if (*cp == '\0' || *cp == '#')
+                       break;
+               array[nsubs++] = dp = cp;
+               do {
+                       if ((*dp = *cp++) != '"')
+                               ++dp;
+                       else while ((*dp = *cp++) != '"')
+                               if (*dp != '\0')
+                                       ++dp;
+                               else    error(_("Odd number of quotation marks"));
+               } while (*cp != '\0' && *cp != '#' &&
+                       (!isascii(*cp) || !isspace((unsigned char) *cp)));
+               if (isascii(*cp) && isspace((unsigned char) *cp))
+                       ++cp;
+               *dp = '\0';
+       }
+       array[nsubs] = NULL;
+       return array;
+}
+
+static long
+oadd(t1, t2)
+const long     t1;
+const long     t2;
+{
+       register long   t;
+
+       t = t1 + t2;
+       if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
+               error(_("time overflow"));
+               (void) exit(EXIT_FAILURE);
+       }
+       return t;
+}
+
+static time_t
+tadd(t1, t2)
+const time_t   t1;
+const long     t2;
+{
+       register time_t t;
+
+       if (t1 == max_time && t2 > 0)
+               return max_time;
+       if (t1 == min_time && t2 < 0)
+               return min_time;
+       t = t1 + t2;
+       if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
+               error(_("time overflow"));
+               (void) exit(EXIT_FAILURE);
+       }
+       return t;
+}
+
+/*
+** Given a rule, and a year, compute the date - in seconds since January 1,
+** 1970, 00:00 LOCAL time - in that year that the rule refers to.
+*/
+
+static time_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;
+
+       if (wantedy == INT_MIN)
+               return min_time;
+       if (wantedy == INT_MAX)
+               return max_time;
+       dayoff = 0;
+       m = TM_JANUARY;
+       y = EPOCH_YEAR;
+       while (wantedy != y) {
+               if (wantedy > y) {
+                       i = len_years[isleap(y)];
+                       ++y;
+               } else {
+                       --y;
+                       i = -len_years[isleap(y)];
+               }
+               dayoff = oadd(dayoff, eitol(i));
+       }
+       while (m != rp->r_month) {
+               i = len_months[isleap(y)][m];
+               dayoff = oadd(dayoff, eitol(i));
+               ++m;
+       }
+       i = rp->r_dayofmonth;
+       if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
+               if (rp->r_dycode == DC_DOWLEQ)
+                       --i;
+               else {
+                       error(_("use of 2/29 in non leap-year"));
+                       (void) exit(EXIT_FAILURE);
+               }
+       }
+       --i;
+       dayoff = oadd(dayoff, eitol(i));
+       if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
+               register long   wday;
+
+#define LDAYSPERWEEK   ((long) DAYSPERWEEK)
+               wday = eitol(EPOCH_WDAY);
+               /*
+               ** Don't trust mod of negative numbers.
+               */
+               if (dayoff >= 0)
+                       wday = (wday + dayoff) % LDAYSPERWEEK;
+               else {
+                       wday -= ((-dayoff) % LDAYSPERWEEK);
+                       if (wday < 0)
+                               wday += LDAYSPERWEEK;
+               }
+               while (wday != eitol(rp->r_wday))
+                       if (rp->r_dycode == DC_DOWGEQ) {
+                               dayoff = oadd(dayoff, (long) 1);
+                               if (++wday >= LDAYSPERWEEK)
+                                       wday = 0;
+                               ++i;
+                       } else {
+                               dayoff = oadd(dayoff, (long) -1);
+                               if (--wday < 0)
+                                       wday = LDAYSPERWEEK - 1;
+                               --i;
+                       }
+               if (i < 0 || i >= len_months[isleap(y)][m]) {
+                       error(_("no day in month matches rule"));
+                       (void) exit(EXIT_FAILURE);
+               }
+       }
+       if (dayoff < 0 && !TYPE_SIGNED(time_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;
+       return tadd(t, rp->r_tod);
+}
+
+static void
+newabbr(string)
+const char * const     string;
+{
+       register int    i;
+
+       i = strlen(string) + 1;
+       if (charcnt + i > TZ_MAX_CHARS) {
+               error(_("too many, or too long, time zone abbreviations"));
+               (void) exit(EXIT_FAILURE);
+       }
+       (void) strcpy(&chars[charcnt], string);
+       charcnt += eitol(i);
+}
+
+static int
+mkdirs(argname)
+char * const   argname;
+{
+       register char * name;
+       register char * cp;
+
+       if (argname == NULL || *argname == '\0')
+               return 0;
+       cp = name = ecpyalloc(argname);
+       while ((cp = strchr(cp + 1, '/')) != 0) {
+               *cp = '\0';
+#ifndef unix
+               /*
+               ** DOS drive specifier?
+               */
+               if (isalpha((unsigned char) name[0]) &&
+                       name[1] == ':' && name[2] == '\0') {
+                               *cp = '/';
+                               continue;
+               }
+#endif /* !defined unix */
+               if (!itsdir(name)) {
+                       /*
+                       ** It doesn't seem to exist, so we try to create it.
+                       ** Creation may fail because of the directory being
+                       ** created by some other multiprocessor, so we get
+                       ** to do extra checking.
+                       */
+                       if (mkdir(name, MKDIR_UMASK) != 0) {
+                               const char *e = strerror(errno);
+
+                               if (errno != EEXIST || !itsdir(name)) {
+                                       (void) fprintf(stderr,
+_("%s: Can't create directory %s: %s\n"),
+                                               progname, name, e);
+                                       ifree(name);
+                                       return -1;
+                               }
+                       }
+               }
+               *cp = '/';
+       }
+       ifree(name);
+       return 0;
+}
+
+static long
+eitol(i)
+const int      i;
+{
+       long    l;
+
+       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"),
+                       progname, i);
+               (void) exit(EXIT_FAILURE);
+       }
+       return l;
+}
+
+/*
+** UNIX was a registered trademark of The Open Group in 2003.
+*/
+
+
+#ifdef WIN32
+/*
+ * To run on win32 
+ */
+int link(const char *oldpath, const char *newpath) {
+       if (!CopyFileEx(oldpath, newpath, NULL, NULL, FALSE, 0)) {
+               return -1;
+       }
+       return 0;
+}
+#endif