home *** CD-ROM | disk | FTP | other *** search
/ Chip 1995 March / CHIP3.mdf / slackwar / a / util / util-lin.2 / util-lin / util-linux-2.2 / time / zic.c < prev   
Encoding:
C/C++ Source or Header  |  1995-02-22  |  43.5 KB  |  1,957 lines

  1. #ifndef lint
  2. #ifndef NOID
  3. static char    elsieid[] = "@(#)zic.c    7.28";
  4. #endif /* !defined NOID */
  5. #endif /* !defined lint */
  6.  
  7. #include "private.h"
  8. #include "tzfile.h"
  9.  
  10. struct rule {
  11.     const char *    r_filename;
  12.     int        r_linenum;
  13.     const char *    r_name;
  14.  
  15.     int        r_loyear;    /* for example, 1986 */
  16.     int        r_hiyear;    /* for example, 1986 */
  17.     const char *    r_yrtype;
  18.  
  19.     int        r_month;    /* 0..11 */
  20.  
  21.     int        r_dycode;    /* see below */
  22.     int        r_dayofmonth;
  23.     int        r_wday;
  24.  
  25.     long        r_tod;        /* time from midnight */
  26.     int        r_todisstd;    /* above is standard time if TRUE */
  27.                     /* or wall clock time if FALSE */
  28.     int        r_todisuniv;    /* above is universal time if TRUE */
  29.                     /* or local time if FALSE */
  30.     long        r_stdoff;    /* offset from standard time */
  31.     const char *    r_abbrvar;    /* variable part of abbreviation */
  32.  
  33.     int        r_todo;        /* a rule to do (used in outzone) */
  34.     time_t        r_temp;        /* used in outzone */
  35. };
  36.  
  37. /*
  38. **    r_dycode        r_dayofmonth    r_wday
  39. */
  40.  
  41. #define DC_DOM        0    /* 1..31 */    /* unused */
  42. #define DC_DOWGEQ    1    /* 1..31 */    /* 0..6 (Sun..Sat) */
  43. #define DC_DOWLEQ    2    /* 1..31 */    /* 0..6 (Sun..Sat) */
  44.  
  45. struct zone {
  46.     const char *    z_filename;
  47.     int        z_linenum;
  48.  
  49.     const char *    z_name;
  50.     long        z_gmtoff;
  51.     const char *    z_rule;
  52.     const char *    z_format;
  53.  
  54.     long        z_stdoff;
  55.  
  56.     struct rule *    z_rules;
  57.     int        z_nrules;
  58.  
  59.     struct rule    z_untilrule;
  60.     time_t        z_untiltime;
  61. };
  62.  
  63. extern int    emkdir P((const char * name, int mode));
  64. extern int    getopt P((int argc, char * argv[], const char * options));
  65. extern char *    icatalloc P((char * old, const char * new));
  66. extern char *    icpyalloc P((const char * string));
  67. extern void    ifree P((char * p));
  68. extern char *    imalloc P((int n));
  69. extern void *    irealloc P((void * old, int n));
  70. extern int    link P((const char * fromname, const char * toname));
  71. extern char *    optarg;
  72. extern int    optind;
  73. extern char *    scheck P((const char * string, const char * format));
  74.  
  75. static void    addtt P((time_t starttime, int type));
  76. static int    addtype P((long gmtoff, const char * abbr, int isdst,
  77.                 int ttisstd));
  78. static void    leapadd P((time_t t, int positive, int rolling, int count));
  79. static void    adjleap P((void));
  80. static void    associate P((void));
  81. static int    ciequal P((const char * ap, const char * bp));
  82. static void    convert P((long val, char * buf));
  83. static void    dolink P((const char * fromfile, const char * tofile));
  84. static void    eat P((const char * name, int num));
  85. static void    eats P((const char * name, int num,
  86.             const char * rname, int rnum));
  87. static long    eitol P((int i));
  88. static void    error P((const char * message));
  89. static char **    getfields P((char * buf));
  90. static long    gethms P((const char * string, const char * errstrng,
  91.             int signable));
  92. static void    infile P((const char * filename));
  93. static void    inleap P((char ** fields, int nfields));
  94. static void    inlink P((char ** fields, int nfields));
  95. static void    inrule P((char ** fields, int nfields));
  96. static int    inzcont P((char ** fields, int nfields));
  97. static int    inzone P((char ** fields, int nfields));
  98. static int    inzsub P((char ** fields, int nfields, int iscont));
  99. static int    itsabbr P((const char * abbr, const char * word));
  100. static int    itsdir P((const char * name));
  101. static int    lowerit P((int c));
  102. static char *    memcheck P((char * tocheck));
  103. static int    mkdirs P((char * filename));
  104. static void    newabbr P((const char * abbr));
  105. static long    oadd P((long t1, long t2));
  106. static void    outzone P((const struct zone * zp, int ntzones));
  107. static void    puttzcode P((long code, FILE * fp));
  108. static int    rcomp P((const genericptr_T leftp, const genericptr_T rightp));
  109. static time_t    rpytime P((const struct rule * rp, int wantedy));
  110. static void    rulesub P((struct rule * rp,
  111.             const char * loyearp, const char * hiyearp,
  112.             const char * typep, const char * monthp,
  113.             const char * dayp, const char * timep));
  114. static void    setboundaries P((void));
  115. static time_t    tadd P((time_t t1, long t2));
  116. static void    usage P((void));
  117. static void    writezone P((const char * name));
  118. static int    yearistype P((int year, const char * type));
  119.  
  120. static int        charcnt;
  121. static int        errors;
  122. static const char *    filename;
  123. static int        leapcnt;
  124. static int        linenum;
  125. static int        max_int;
  126. static time_t        max_time;
  127. static int        max_year;
  128. static int        min_int;
  129. static time_t        min_time;
  130. static int        min_year;
  131. static int        noise;
  132. static const char *    rfilename;
  133. static int        rlinenum;
  134. static const char *    progname;
  135. static int        timecnt;
  136. static int        typecnt;
  137. static int        tt_signed;
  138.  
  139. /*
  140. ** Line codes.
  141. */
  142.  
  143. #define LC_RULE        0
  144. #define LC_ZONE        1
  145. #define LC_LINK        2
  146. #define LC_LEAP        3
  147.  
  148. /*
  149. ** Which fields are which on a Zone line.
  150. */
  151.  
  152. #define ZF_NAME        1
  153. #define ZF_GMTOFF    2
  154. #define ZF_RULE        3
  155. #define ZF_FORMAT    4
  156. #define ZF_TILYEAR    5
  157. #define ZF_TILMONTH    6
  158. #define ZF_TILDAY    7
  159. #define ZF_TILTIME    8
  160. #define ZONE_MINFIELDS    5
  161. #define ZONE_MAXFIELDS    9
  162.  
  163. /*
  164. ** Which fields are which on a Zone continuation line.
  165. */
  166.  
  167. #define ZFC_GMTOFF    0
  168. #define ZFC_RULE    1
  169. #define ZFC_FORMAT    2
  170. #define ZFC_TILYEAR    3
  171. #define ZFC_TILMONTH    4
  172. #define ZFC_TILDAY    5
  173. #define ZFC_TILTIME    6
  174. #define ZONEC_MINFIELDS    3
  175. #define ZONEC_MAXFIELDS    7
  176.  
  177. /*
  178. ** Which files are which on a Rule line.
  179. */
  180.  
  181. #define RF_NAME        1
  182. #define RF_LOYEAR    2
  183. #define RF_HIYEAR    3
  184. #define RF_COMMAND    4
  185. #define RF_MONTH    5
  186. #define RF_DAY        6
  187. #define RF_TOD        7
  188. #define RF_STDOFF    8
  189. #define RF_ABBRVAR    9
  190. #define RULE_FIELDS    10
  191.  
  192. /*
  193. ** Which fields are which on a Link line.
  194. */
  195.  
  196. #define LF_FROM        1
  197. #define LF_TO        2
  198. #define LINK_FIELDS    3
  199.  
  200. /*
  201. ** Which fields are which on a Leap line.
  202. */
  203.  
  204. #define LP_YEAR        1
  205. #define LP_MONTH    2
  206. #define LP_DAY        3
  207. #define LP_TIME        4
  208. #define LP_CORR        5
  209. #define LP_ROLL        6
  210. #define LEAP_FIELDS    7
  211.  
  212. /*
  213. ** Year synonyms.
  214. */
  215.  
  216. #define YR_MINIMUM    0
  217. #define YR_MAXIMUM    1
  218. #define YR_ONLY        2
  219.  
  220. static struct rule *    rules;
  221. static int        nrules;    /* number of rules */
  222.  
  223. static struct zone *    zones;
  224. static int        nzones;    /* number of zones */
  225.  
  226. struct link {
  227.     const char *    l_filename;
  228.     int        l_linenum;
  229.     const char *    l_from;
  230.     const char *    l_to;
  231. };
  232.  
  233. static struct link *    links;
  234. static int        nlinks;
  235.  
  236. struct lookup {
  237.     const char *    l_word;
  238.     const int    l_value;
  239. };
  240.  
  241. static struct lookup const *    byword P((const char * string,
  242.                     const struct lookup * lp));
  243.  
  244. static struct lookup const    line_codes[] = {
  245.     { "Rule",    LC_RULE },
  246.     { "Zone",    LC_ZONE },
  247.     { "Link",    LC_LINK },
  248.     { "Leap",    LC_LEAP },
  249.     { NULL,        0}
  250. };
  251.  
  252. static struct lookup const    mon_names[] = {
  253.     { "January",    TM_JANUARY },
  254.     { "February",    TM_FEBRUARY },
  255.     { "March",    TM_MARCH },
  256.     { "April",    TM_APRIL },
  257.     { "May",    TM_MAY },
  258.     { "June",    TM_JUNE },
  259.     { "July",    TM_JULY },
  260.     { "August",    TM_AUGUST },
  261.     { "September",    TM_SEPTEMBER },
  262.     { "October",    TM_OCTOBER },
  263.     { "November",    TM_NOVEMBER },
  264.     { "December",    TM_DECEMBER },
  265.     { NULL,        0 }
  266. };
  267.  
  268. static struct lookup const    wday_names[] = {
  269.     { "Sunday",    TM_SUNDAY },
  270.     { "Monday",    TM_MONDAY },
  271.     { "Tuesday",    TM_TUESDAY },
  272.     { "Wednesday",    TM_WEDNESDAY },
  273.     { "Thursday",    TM_THURSDAY },
  274.     { "Friday",    TM_FRIDAY },
  275.     { "Saturday",    TM_SATURDAY },
  276.     { NULL,        0 }
  277. };
  278.  
  279. static struct lookup const    lasts[] = {
  280.     { "last-Sunday",    TM_SUNDAY },
  281.     { "last-Monday",    TM_MONDAY },
  282.     { "last-Tuesday",    TM_TUESDAY },
  283.     { "last-Wednesday",    TM_WEDNESDAY },
  284.     { "last-Thursday",    TM_THURSDAY },
  285.     { "last-Friday",    TM_FRIDAY },
  286.     { "last-Saturday",    TM_SATURDAY },
  287.     { NULL,            0 }
  288. };
  289.  
  290. static struct lookup const    begin_years[] = {
  291.     { "minimum",    YR_MINIMUM },
  292.     { "maximum",    YR_MAXIMUM },
  293.     { NULL,        0 }
  294. };
  295.  
  296. static struct lookup const    end_years[] = {
  297.     { "minimum",    YR_MINIMUM },
  298.     { "maximum",    YR_MAXIMUM },
  299.     { "only",    YR_ONLY },
  300.     { NULL,        0 }
  301. };
  302.  
  303. static struct lookup const    leap_types[] = {
  304.     { "Rolling",    TRUE },
  305.     { "Stationary",    FALSE },
  306.     { NULL,        0 }
  307. };
  308.  
  309. static const int    len_months[2][MONSPERYEAR] = {
  310.     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  311.     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  312. };
  313.  
  314. static const int    len_years[2] = {
  315.     DAYSPERNYEAR, DAYSPERLYEAR
  316. };
  317.  
  318. static time_t        ats[TZ_MAX_TIMES];
  319. static unsigned char    types[TZ_MAX_TIMES];
  320. static long        gmtoffs[TZ_MAX_TYPES];
  321. static char        isdsts[TZ_MAX_TYPES];
  322. static unsigned char    abbrinds[TZ_MAX_TYPES];
  323. static char        ttisstds[TZ_MAX_TYPES];
  324. static char        chars[TZ_MAX_CHARS];
  325. static time_t        trans[TZ_MAX_LEAPS];
  326. static long        corr[TZ_MAX_LEAPS];
  327. static char        roll[TZ_MAX_LEAPS];
  328.  
  329. /*
  330. ** Memory allocation.
  331. */
  332.  
  333. static char *
  334. memcheck(ptr)
  335. char * const    ptr;
  336. {
  337.     if (ptr == NULL) {
  338.         (void) perror(progname);
  339.         (void) exit(EXIT_FAILURE);
  340.     }
  341.     return ptr;
  342. }
  343.  
  344. #define emalloc(size)        memcheck(imalloc(size))
  345. #define erealloc(ptr, size)    memcheck(irealloc((ptr), (size)))
  346. #define ecpyalloc(ptr)        memcheck(icpyalloc(ptr))
  347. #define ecatalloc(oldp, newp)    memcheck(icatalloc((oldp), (newp)))
  348.  
  349. /*
  350. ** Error handling.
  351. */
  352.  
  353. static void
  354. eats(name, num, rname, rnum)
  355. const char * const    name;
  356. const int        num;
  357. const char * const    rname;
  358. const int        rnum;
  359. {
  360.     filename = name;
  361.     linenum = num;
  362.     rfilename = rname;
  363.     rlinenum = rnum;
  364. }
  365.  
  366. static void
  367. eat(name, num)
  368. const char * const    name;
  369. const int        num;
  370. {
  371.     eats(name, num, (char *) NULL, -1);
  372. }
  373.  
  374. static void
  375. error(string)
  376. const char * const    string;
  377. {
  378.     /*
  379.     ** Match the format of "cc" to allow sh users to
  380.     **     zic ... 2>&1 | error -t "*" -v
  381.     ** on BSD systems.
  382.     */
  383.     (void) fprintf(stderr, "\"%s\", line %d: %s",
  384.         filename, linenum, string);
  385.     if (rfilename != NULL)
  386.         (void) fprintf(stderr, " (rule from \"%s\", line %d)",
  387.             rfilename, rlinenum);
  388.     (void) fprintf(stderr, "\n");
  389.     ++errors;
  390. }
  391.  
  392. static void
  393. usage P((void))
  394. {
  395.     (void) fprintf(stderr,
  396. "%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ] \n\
  397. \t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n",
  398.         progname, progname);
  399.     (void) exit(EXIT_FAILURE);
  400. }
  401.  
  402. static const char *    psxrules;
  403. static const char *    lcltime;
  404. static const char *    directory;
  405. static const char *    leapsec;
  406. static const char *    yitcommand;
  407. static int        sflag = FALSE;
  408.  
  409. int
  410. main(argc, argv)
  411. int    argc;
  412. char *    argv[];
  413. {
  414.     register int    i, j;
  415.     register int    c;
  416.  
  417. #ifdef unix
  418.     (void) umask(umask(022) | 022);
  419. #endif /* defined unix */
  420.     progname = argv[0];
  421.     while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF)
  422.         switch (c) {
  423.             default:
  424.                 usage();
  425.             case 'd':
  426.                 if (directory == NULL)
  427.                     directory = optarg;
  428.                 else {
  429.                     (void) fprintf(stderr,
  430. "%s: More than one -d option specified\n",
  431.                         progname);
  432.                     (void) exit(EXIT_FAILURE);
  433.                 }
  434.                 break;
  435.             case 'l':
  436.                 if (lcltime == NULL)
  437.                     lcltime = optarg;
  438.                 else {
  439.                     (void) fprintf(stderr,
  440. "%s: More than one -l option specified\n",
  441.                         progname);
  442.                     (void) exit(EXIT_FAILURE);
  443.                 }
  444.                 break;
  445.             case 'p':
  446.                 if (psxrules == NULL)
  447.                     psxrules = optarg;
  448.                 else {
  449.                     (void) fprintf(stderr,
  450. "%s: More than one -p option specified\n",
  451.                         progname);
  452.                     (void) exit(EXIT_FAILURE);
  453.                 }
  454.                 break;
  455.             case 'y':
  456.                 if (yitcommand == NULL)
  457.                     yitcommand = optarg;
  458.                 else {
  459.                     (void) fprintf(stderr,
  460. "%s: More than one -y option specified\n",
  461.                         progname);
  462.                     (void) exit(EXIT_FAILURE);
  463.                 }
  464.                 break;
  465.             case 'L':
  466.                 if (leapsec == NULL)
  467.                     leapsec = optarg;
  468.                 else {
  469.                     (void) fprintf(stderr,
  470. "%s: More than one -L option specified\n",
  471.                         progname);
  472.                     (void) exit(EXIT_FAILURE);
  473.                 }
  474.                 break;
  475.             case 'v':
  476.                 noise = TRUE;
  477.                 break;
  478.             case 's':
  479.                 sflag = TRUE;
  480.                 break;
  481.         }
  482.     if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
  483.         usage();    /* usage message by request */
  484.     if (directory == NULL)
  485.         directory = TZDIR;
  486.     if (yitcommand == NULL)
  487.         yitcommand = "yearistype";
  488.  
  489.     setboundaries();
  490.  
  491.     if (optind < argc && leapsec != NULL) {
  492.         infile(leapsec);
  493.         adjleap();
  494.     }
  495.  
  496.     for (i = optind; i < argc; ++i)
  497.         infile(argv[i]);
  498.     if (errors)
  499.         (void) exit(EXIT_FAILURE);
  500.     associate();
  501.     for (i = 0; i < nzones; i = j) {
  502.         /*
  503.         ** Find the next non-continuation zone entry.
  504.         */
  505.         for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
  506.             continue;
  507.         outzone(&zones[i], j - i);
  508.     }
  509.     /*
  510.     ** Make links.
  511.     */
  512.     for (i = 0; i < nlinks; ++i)
  513.         dolink(links[i].l_from, links[i].l_to);
  514.     if (lcltime != NULL)
  515.         dolink(lcltime, TZDEFAULT);
  516.     if (psxrules != NULL)
  517.         dolink(psxrules, TZDEFRULES);
  518.     return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  519. }
  520.  
  521. static void
  522. dolink(fromfile, tofile)
  523. const char * const    fromfile;
  524. const char * const    tofile;
  525. {
  526.     register char *    fromname;
  527.     register char *    toname;
  528.  
  529.     if (fromfile[0] == '/')
  530.         fromname = ecpyalloc(fromfile);
  531.     else {
  532.         fromname = ecpyalloc(directory);
  533.         fromname = ecatalloc(fromname, "/");
  534.         fromname = ecatalloc(fromname, fromfile);
  535.     }
  536.     if (tofile[0] == '/')
  537.         toname = ecpyalloc(tofile);
  538.     else {
  539.         toname = ecpyalloc(directory);
  540.         toname = ecatalloc(toname, "/");
  541.         toname = ecatalloc(toname, tofile);
  542.     }
  543.     /*
  544.     ** We get to be careful here since
  545.     ** there's a fair chance of root running us.
  546.     */
  547.     if (!itsdir(toname))
  548.         (void) remove(toname);
  549.     if (link(fromname, toname) != 0) {
  550.         if (mkdirs(toname) != 0)
  551.             (void) exit(EXIT_FAILURE);
  552.         if (link(fromname, toname) != 0) {
  553.             (void) fprintf(stderr, "%s: Can't link from %s to ",
  554.                 progname, fromname);
  555.             (void) perror(toname);
  556.             (void) exit(EXIT_FAILURE);
  557.         }
  558.     }
  559.     ifree(fromname);
  560.     ifree(toname);
  561. }
  562.  
  563. static void
  564. setboundaries P((void))
  565. {
  566.     register time_t    bit;
  567.     register int bii;
  568.  
  569.     for (bit = 1; bit > 0; bit <<= 1)
  570.         continue;
  571.     if (bit == 0) {        /* time_t is an unsigned type */
  572.         tt_signed = FALSE;
  573.         min_time = 0;
  574.         max_time = ~(time_t) 0;
  575.         if (sflag)
  576.             max_time >>= 1;
  577.     } else {
  578.         tt_signed = TRUE;
  579.         min_time = bit;
  580.         max_time = bit;
  581.         ++max_time;
  582.         max_time = -max_time;
  583.         if (sflag)
  584.             min_time = 0;
  585.     }
  586.     min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
  587.     max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
  588.  
  589.     for (bii = 1; bii > 0; bii <<= 1)
  590.         continue;
  591.     min_int = bii;
  592.     max_int = -1 - bii;
  593. }
  594.  
  595. static int
  596. itsdir(name)
  597. const char * const    name;
  598. {
  599.     register char *    myname;
  600.     register int    accres;
  601.  
  602.     myname = ecpyalloc(name);
  603.     myname = ecatalloc(myname, "/.");
  604.     accres = access(myname, 0);
  605.     ifree(myname);
  606.     return accres == 0;
  607. }
  608.  
  609. /*
  610. ** Associate sets of rules with zones.
  611. */
  612.  
  613. /*
  614. ** Sort by rule name.
  615. */
  616.  
  617. static int
  618. rcomp(cp1, cp2)
  619. const genericptr_T    cp1;
  620. const genericptr_T    cp2;
  621. {
  622.     return strcmp(((struct rule *) cp1)->r_name,
  623.         ((struct rule *) cp2)->r_name);
  624. }
  625.  
  626. static void
  627. associate P((void))
  628. {
  629.     register struct zone *    zp;
  630.     register struct rule *    rp;
  631.     register int        base, out;
  632.     register int        i;
  633.  
  634.     if (nrules != 0)
  635.         (void) qsort((genericptr_T) rules,
  636.             (qsort_size_T) nrules,
  637.             (qsort_size_T) sizeof *rules, rcomp);
  638.     for (i = 0; i < nzones; ++i) {
  639.         zp = &zones[i];
  640.         zp->z_rules = NULL;
  641.         zp->z_nrules = 0;
  642.     }
  643.     for (base = 0; base < nrules; base = out) {
  644.         rp = &rules[base];
  645.         for (out = base + 1; out < nrules; ++out)
  646.             if (strcmp(rp->r_name, rules[out].r_name) != 0)
  647.                 break;
  648.         for (i = 0; i < nzones; ++i) {
  649.             zp = &zones[i];
  650.             if (strcmp(zp->z_rule, rp->r_name) != 0)
  651.                 continue;
  652.             zp->z_rules = rp;
  653.             zp->z_nrules = out - base;
  654.         }
  655.     }
  656.     for (i = 0; i < nzones; ++i) {
  657.         zp = &zones[i];
  658.         if (zp->z_nrules == 0) {
  659.             /*
  660.             ** Maybe we have a local standard time offset.
  661.             */
  662.             eat(zp->z_filename, zp->z_linenum);
  663.             zp->z_stdoff = gethms(zp->z_rule, "unruly zone", TRUE);
  664.             /*
  665.             ** Note, though, that if there's no rule,
  666.             ** a '%s' in the format is a bad thing.
  667.             */
  668.             if (strchr(zp->z_format, '%') != 0)
  669.                 error("%s in ruleless zone");
  670.         }
  671.     }
  672.     if (errors)
  673.         (void) exit(EXIT_FAILURE);
  674. }
  675.  
  676. static void
  677. infile(name)
  678. const char *    name;
  679. {
  680.     register FILE *            fp;
  681.     register char **        fields;
  682.     register char *            cp;
  683.     register const struct lookup *    lp;
  684.     register int            nfields;
  685.     register int            wantcont;
  686.     register int            num;
  687.     char                buf[BUFSIZ];
  688.  
  689.     if (strcmp(name, "-") == 0) {
  690.         name = "standard input";
  691.         fp = stdin;
  692.     } else if ((fp = fopen(name, "r")) == NULL) {
  693.         (void) fprintf(stderr, "%s: Can't open ", progname);
  694.         (void) perror(name);
  695.         (void) exit(EXIT_FAILURE);
  696.     }
  697.     wantcont = FALSE;
  698.     for (num = 1; ; ++num) {
  699.         eat(name, num);
  700.         if (fgets(buf, (int) sizeof buf, fp) != buf)
  701.             break;
  702.         cp = strchr(buf, '\n');
  703.         if (cp == NULL) {
  704.             error("line too long");
  705.             (void) exit(EXIT_FAILURE);
  706.         }
  707.         *cp = '\0';
  708.         fields = getfields(buf);
  709.         nfields = 0;
  710.         while (fields[nfields] != NULL) {
  711.             static char    nada;
  712.  
  713.             if (ciequal(fields[nfields], "-"))
  714.                 fields[nfields] = &nada;
  715.             ++nfields;
  716.         }
  717.         if (nfields == 0) {
  718.             /* nothing to do */
  719.         } else if (wantcont) {
  720.             wantcont = inzcont(fields, nfields);
  721.         } else {
  722.             lp = byword(fields[0], line_codes);
  723.             if (lp == NULL)
  724.                 error("input line of unknown type");
  725.             else switch ((int) (lp->l_value)) {
  726.                 case LC_RULE:
  727.                     inrule(fields, nfields);
  728.                     wantcont = FALSE;
  729.                     break;
  730.                 case LC_ZONE:
  731.                     wantcont = inzone(fields, nfields);
  732.                     break;
  733.                 case LC_LINK:
  734.                     inlink(fields, nfields);
  735.                     wantcont = FALSE;
  736.                     break;
  737.                 case LC_LEAP:
  738.                     if (name != leapsec)
  739.                         (void) fprintf(stderr,
  740. "%s: Leap line in non leap seconds file %s\n",
  741.                             progname, name);
  742.                     else    inleap(fields, nfields);
  743.                     wantcont = FALSE;
  744.                     break;
  745.                 default:    /* "cannot happen" */
  746.                     (void) fprintf(stderr,
  747. "%s: panic: Invalid l_value %d\n",
  748.                         progname, lp->l_value);
  749.                     (void) exit(EXIT_FAILURE);
  750.             }
  751.         }
  752.         ifree((char *) fields);
  753.     }
  754.     if (ferror(fp)) {
  755.         (void) fprintf(stderr, "%s: Error reading ", progname);
  756.         (void) perror(filename);
  757.         (void) exit(EXIT_FAILURE);
  758.     }
  759.     if (fp != stdin && fclose(fp)) {
  760.         (void) fprintf(stderr, "%s: Error closing ", progname);
  761.         (void) perror(filename);
  762.         (void) exit(EXIT_FAILURE);
  763.     }
  764.     if (wantcont)
  765.         error("expected continuation line not found");
  766. }
  767.  
  768. /*
  769. ** Convert a string of one of the forms
  770. **    h    -h     hh:mm    -hh:mm    hh:mm:ss    -hh:mm:ss
  771. ** into a number of seconds.
  772. ** A null string maps to zero.
  773. ** Call error with errstring and return zero on errors.
  774. */
  775.  
  776. static long
  777. gethms(string, errstring, signable)
  778. const char *        string;
  779. const char * const    errstring;
  780. const int        signable;
  781. {
  782.     int    hh, mm, ss, sign;
  783.  
  784.     if (string == NULL || *string == '\0')
  785.         return 0;
  786.     if (!signable)
  787.         sign = 1;
  788.     else if (*string == '-') {
  789.         sign = -1;
  790.         ++string;
  791.     } else    sign = 1;
  792.     if (sscanf(string, scheck(string, "%d"), &hh) == 1)
  793.         mm = ss = 0;
  794.     else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)
  795.         ss = 0;
  796.     else if (sscanf(string, scheck(string, "%d:%d:%d"),
  797.         &hh, &mm, &ss) != 3) {
  798.             error(errstring);
  799.             return 0;
  800.     }
  801.     if (hh < 0 || hh >= HOURSPERDAY ||
  802.         mm < 0 || mm >= MINSPERHOUR ||
  803.         ss < 0 || ss > SECSPERMIN) {
  804.             error(errstring);
  805.             return 0;
  806.     }
  807.     return eitol(sign) *
  808.         (eitol(hh * MINSPERHOUR + mm) *
  809.         eitol(SECSPERMIN) + eitol(ss));
  810. }
  811.  
  812. static void
  813. inrule(fields, nfields)
  814. register char ** const    fields;
  815. const int        nfields;
  816. {
  817.     static struct rule    r;
  818.  
  819.     if (nfields != RULE_FIELDS) {
  820.         error("wrong number of fields on Rule line");
  821.         return;
  822.     }
  823.     if (*fields[RF_NAME] == '\0') {
  824.         error("nameless rule");
  825.         return;
  826.     }
  827.     r.r_filename = filename;
  828.     r.r_linenum = linenum;
  829.     r.r_stdoff = gethms(fields[RF_STDOFF], "invalid saved time", TRUE);
  830.     rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
  831.         fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
  832.     r.r_name = ecpyalloc(fields[RF_NAME]);
  833.     r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
  834.     rules = (struct rule *) (void *) erealloc((char *) rules,
  835.         (int) ((nrules + 1) * sizeof *rules));
  836.     rules[nrules++] = r;
  837. }
  838.  
  839. static int
  840. inzone(fields, nfields)
  841. register char ** const    fields;
  842. const int        nfields;
  843. {
  844.     register int    i;
  845.     static char *    buf;
  846.  
  847.     if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
  848.         error("wrong number of fields on Zone line");
  849.         return FALSE;
  850.     }
  851.     if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
  852.         buf = erealloc(buf, (int) (132 + strlen(TZDEFAULT)));
  853.         (void) sprintf(buf,
  854. "\"Zone %s\" line and -l option are mutually exclusive",
  855.             TZDEFAULT);
  856.         error(buf);
  857.         return FALSE;
  858.     }
  859.     if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
  860.         buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES)));
  861.         (void) sprintf(buf,
  862. "\"Zone %s\" line and -p option are mutually exclusive",
  863.             TZDEFRULES);
  864.         error(buf);
  865.         return FALSE;
  866.     }
  867.     for (i = 0; i < nzones; ++i)
  868.         if (zones[i].z_name != NULL &&
  869.             strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
  870.                 buf = erealloc(buf, (int) (132 +
  871.                     strlen(fields[ZF_NAME]) +
  872.                     strlen(zones[i].z_filename)));
  873.                 (void) sprintf(buf,
  874. "duplicate zone name %s (file \"%s\", line %d)",
  875.                     fields[ZF_NAME],
  876.                     zones[i].z_filename,
  877.                     zones[i].z_linenum);
  878.                 error(buf);
  879.                 return FALSE;
  880.         }
  881.     return inzsub(fields, nfields, FALSE);
  882. }
  883.  
  884. static int
  885. inzcont(fields, nfields)
  886. register char ** const    fields;
  887. const int        nfields;
  888. {
  889.     if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
  890.         error("wrong number of fields on Zone continuation line");
  891.         return FALSE;
  892.     }
  893.     return inzsub(fields, nfields, TRUE);
  894. }
  895.  
  896. static int
  897. inzsub(fields, nfields, iscont)
  898. register char ** const    fields;
  899. const int        nfields;
  900. const int        iscont;
  901. {
  902.     register char *        cp;
  903.     static struct zone    z;
  904.     register int        i_gmtoff, i_rule, i_format;
  905.     register int        i_untilyear, i_untilmonth;
  906.     register int        i_untilday, i_untiltime;
  907.     register int        hasuntil;
  908.  
  909.     if (iscont) {
  910.         i_gmtoff = ZFC_GMTOFF;
  911.         i_rule = ZFC_RULE;
  912.         i_format = ZFC_FORMAT;
  913.         i_untilyear = ZFC_TILYEAR;
  914.         i_untilmonth = ZFC_TILMONTH;
  915.         i_untilday = ZFC_TILDAY;
  916.         i_untiltime = ZFC_TILTIME;
  917.         z.z_name = NULL;
  918.     } else {
  919.         i_gmtoff = ZF_GMTOFF;
  920.         i_rule = ZF_RULE;
  921.         i_format = ZF_FORMAT;
  922.         i_untilyear = ZF_TILYEAR;
  923.         i_untilmonth = ZF_TILMONTH;
  924.         i_untilday = ZF_TILDAY;
  925.         i_untiltime = ZF_TILTIME;
  926.         z.z_name = ecpyalloc(fields[ZF_NAME]);
  927.     }
  928.     z.z_filename = filename;
  929.     z.z_linenum = linenum;
  930.     z.z_gmtoff = gethms(fields[i_gmtoff], "invalid GMT offset", TRUE);
  931.     if ((cp = strchr(fields[i_format], '%')) != 0) {
  932.         if (*++cp != 's' || strchr(cp, '%') != 0) {
  933.             error("invalid abbreviation format");
  934.             return FALSE;
  935.         }
  936.     }
  937.     z.z_rule = ecpyalloc(fields[i_rule]);
  938.     z.z_format = ecpyalloc(fields[i_format]);
  939.     hasuntil = nfields > i_untilyear;
  940.     if (hasuntil) {
  941.         z.z_untilrule.r_filename = filename;
  942.         z.z_untilrule.r_linenum = linenum;
  943.         rulesub(&z.z_untilrule,
  944.             fields[i_untilyear],
  945.             "only",
  946.             "",
  947.             (nfields > i_untilmonth) ?
  948.             fields[i_untilmonth] : "Jan",
  949.             (nfields > i_untilday) ? fields[i_untilday] : "1",
  950.             (nfields > i_untiltime) ? fields[i_untiltime] : "0");
  951.         z.z_untiltime = rpytime(&z.z_untilrule,
  952.             z.z_untilrule.r_loyear);
  953.         if (iscont && nzones > 0 &&
  954.             z.z_untiltime > min_time &&
  955.             z.z_untiltime < max_time &&
  956.             zones[nzones - 1].z_untiltime > min_time &&
  957.             zones[nzones - 1].z_untiltime < max_time &&
  958.             zones[nzones - 1].z_untiltime >= z.z_untiltime) {
  959. error("Zone continuation line end time is not after end time of previous line");
  960.                 return FALSE;
  961.         }
  962.     }
  963.     zones = (struct zone *) (void *) erealloc((char *) zones,
  964.         (int) ((nzones + 1) * sizeof *zones));
  965.     zones[nzones++] = z;
  966.     /*
  967.     ** If there was an UNTIL field on this line,
  968.     ** there's more information about the zone on the next line.
  969.     */
  970.     return hasuntil;
  971. }
  972.  
  973. static void
  974. inleap(fields, nfields)
  975. register char ** const    fields;
  976. const int        nfields;
  977. {
  978.     register const char *        cp;
  979.     register const struct lookup *    lp;
  980.     register int            i, j;
  981.     int                year, month, day;
  982.     long                dayoff, tod;
  983.     time_t                t;
  984.  
  985.     if (nfields != LEAP_FIELDS) {
  986.         error("wrong number of fields on Leap line");
  987.         return;
  988.     }
  989.     dayoff = 0;
  990.     cp = fields[LP_YEAR];
  991.     if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {
  992.             /*
  993.              * Leapin' Lizards!
  994.              */
  995.             error("invalid leaping year");
  996.             return;
  997.     }
  998.     j = EPOCH_YEAR;
  999.     while (j != year) {
  1000.         if (year > j) {
  1001.             i = len_years[isleap(j)];
  1002.             ++j;
  1003.         } else {
  1004.             --j;
  1005.             i = -len_years[isleap(j)];
  1006.         }
  1007.         dayoff = oadd(dayoff, eitol(i));
  1008.     }
  1009.     if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
  1010.         error("invalid month name");
  1011.         return;
  1012.     }
  1013.     month = lp->l_value;
  1014.     j = TM_JANUARY;
  1015.     while (j != month) {
  1016.         i = len_months[isleap(year)][j];
  1017.         dayoff = oadd(dayoff, eitol(i));
  1018.         ++j;
  1019.     }
  1020.     cp = fields[LP_DAY];
  1021.     if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
  1022.         day <= 0 || day > len_months[isleap(year)][month]) {
  1023.             error("invalid day of month");
  1024.             return;
  1025.     }
  1026.     dayoff = oadd(dayoff, eitol(day - 1));
  1027.     if (dayoff < 0 && !tt_signed) {
  1028.         error("time before zero");
  1029.         return;
  1030.     }
  1031.     t = (time_t) dayoff * SECSPERDAY;
  1032.     /*
  1033.     ** Cheap overflow check.
  1034.     */
  1035.     if (t / SECSPERDAY != dayoff) {
  1036.         error("time overflow");
  1037.         return;
  1038.     }
  1039.     tod = gethms(fields[LP_TIME], "invalid time of day", FALSE);
  1040.     cp = fields[LP_CORR];
  1041.     {
  1042.         register int    positive;
  1043.         int        count;
  1044.  
  1045.         if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
  1046.             positive = FALSE;
  1047.             count = 1;
  1048.         } else if (strcmp(cp, "--") == 0) {
  1049.             positive = FALSE;
  1050.             count = 2;
  1051.         } else if (strcmp(cp, "+") == 0) {
  1052.             positive = TRUE;
  1053.             count = 1;
  1054.         } else if (strcmp(cp, "++") == 0) {
  1055.             positive = TRUE;
  1056.             count = 2;
  1057.         } else {
  1058.             error("illegal CORRECTION field on Leap line");
  1059.             return;
  1060.         }
  1061.         if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
  1062.             error("illegal Rolling/Stationary field on Leap line");
  1063.             return;
  1064.         }
  1065.         leapadd(tadd(t, tod), positive, lp->l_value, count);
  1066.     }
  1067. }
  1068.  
  1069. static void
  1070. inlink(fields, nfields)
  1071. register char ** const    fields;
  1072. const int        nfields;
  1073. {
  1074.     struct link    l;
  1075.  
  1076.     if (nfields != LINK_FIELDS) {
  1077.         error("wrong number of fields on Link line");
  1078.         return;
  1079.     }
  1080.     if (*fields[LF_FROM] == '\0') {
  1081.         error("blank FROM field on Link line");
  1082.         return;
  1083.     }
  1084.     if (*fields[LF_TO] == '\0') {
  1085.         error("blank TO field on Link line");
  1086.         return;
  1087.     }
  1088.     l.l_filename = filename;
  1089.     l.l_linenum = linenum;
  1090.     l.l_from = ecpyalloc(fields[LF_FROM]);
  1091.     l.l_to = ecpyalloc(fields[LF_TO]);
  1092.     links = (struct link *) (void *) erealloc((char *) links,
  1093.         (int) ((nlinks + 1) * sizeof *links));
  1094.     links[nlinks++] = l;
  1095. }
  1096.  
  1097. static void
  1098. rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
  1099. register struct rule * const    rp;
  1100. const char * const        loyearp;
  1101. const char * const        hiyearp;
  1102. const char * const        typep;
  1103. const char * const        monthp;
  1104. const char * const        dayp;
  1105. const char * const        timep;
  1106. {
  1107.     register const struct lookup *    lp;
  1108.     register const char *        cp;
  1109.     register char *            dp;
  1110.     register char *            ep;
  1111.  
  1112.     if ((lp = byword(monthp, mon_names)) == NULL) {
  1113.         error("invalid month name");
  1114.         return;
  1115.     }
  1116.     rp->r_month = lp->l_value;
  1117.     rp->r_todisstd = FALSE;
  1118.     rp->r_todisuniv = FALSE;
  1119.     dp = ecpyalloc(timep);
  1120.     if (*dp != '\0') {
  1121.         ep = dp + strlen(dp) - 1;
  1122.         switch (lowerit(*ep)) {
  1123.             case 's':    /* Standard */
  1124.                 rp->r_todisstd = TRUE;
  1125.                 rp->r_todisuniv = FALSE;
  1126.                 *ep = '\0';
  1127.                 break;
  1128.             case 'w':    /* Wall */
  1129.                 rp->r_todisstd = FALSE;
  1130.                 rp->r_todisuniv = FALSE;
  1131.                 *ep = '\0';
  1132.             case 'g':    /* Greenwich */
  1133.             case 'u':    /* Universal */
  1134.             case 'z':    /* Zulu */
  1135.                 rp->r_todisstd = TRUE;
  1136.                 rp->r_todisuniv = TRUE;
  1137.                 *ep = '\0';
  1138.                 break;
  1139.         }
  1140.     }
  1141.     rp->r_tod = gethms(dp, "invalid time of day", FALSE);
  1142.     ifree(dp);
  1143.     /*
  1144.     ** Year work.
  1145.     */
  1146.     cp = loyearp;
  1147.     if ((lp = byword(cp, begin_years)) != NULL) switch ((int) lp->l_value) {
  1148.         case YR_MINIMUM:
  1149.             rp->r_loyear = min_int;
  1150.             break;
  1151.         case YR_MAXIMUM:
  1152.             rp->r_loyear = max_int;
  1153.             break;
  1154.         default:    /* "cannot happen" */
  1155.             (void) fprintf(stderr,
  1156.                 "%s: panic: Invalid l_value %d\n",
  1157.                 progname, lp->l_value);
  1158.             (void) exit(EXIT_FAILURE);
  1159.     } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
  1160.         error("invalid starting year");
  1161.         return;
  1162.     }
  1163.     cp = hiyearp;
  1164.     if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
  1165.         case YR_MINIMUM:
  1166.             rp->r_hiyear = min_int;
  1167.             break;
  1168.         case YR_MAXIMUM:
  1169.             rp->r_hiyear = max_int;
  1170.             break;
  1171.         case YR_ONLY:
  1172.             rp->r_hiyear = rp->r_loyear;
  1173.             break;
  1174.         default:    /* "cannot happen" */
  1175.             (void) fprintf(stderr,
  1176.                 "%s: panic: Invalid l_value %d\n",
  1177.                 progname, lp->l_value);
  1178.             (void) exit(EXIT_FAILURE);
  1179.     } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
  1180.         error("invalid ending year");
  1181.         return;
  1182.     }
  1183.     if (rp->r_loyear > rp->r_hiyear) {
  1184.         error("starting year greater than ending year");
  1185.         return;
  1186.     }
  1187.     if (*typep == '\0')
  1188.         rp->r_yrtype = NULL;
  1189.     else {
  1190.         if (rp->r_loyear == rp->r_hiyear) {
  1191.             error("typed single year");
  1192.             return;
  1193.         }
  1194.         rp->r_yrtype = ecpyalloc(typep);
  1195.     }
  1196.     /*
  1197.     ** Day work.
  1198.     ** Accept things such as:
  1199.     **    1
  1200.     **    last-Sunday
  1201.     **    Sun<=20
  1202.     **    Sun>=7
  1203.     */
  1204.     dp = ecpyalloc(dayp);
  1205.     if ((lp = byword(dp, lasts)) != NULL) {
  1206.         rp->r_dycode = DC_DOWLEQ;
  1207.         rp->r_wday = lp->l_value;
  1208.         rp->r_dayofmonth = len_months[1][rp->r_month];
  1209.     } else {
  1210.         if ((ep = strchr(dp, '<')) != 0)
  1211.             rp->r_dycode = DC_DOWLEQ;
  1212.         else if ((ep = strchr(dp, '>')) != 0)
  1213.             rp->r_dycode = DC_DOWGEQ;
  1214.         else {
  1215.             ep = dp;
  1216.             rp->r_dycode = DC_DOM;
  1217.         }
  1218.         if (rp->r_dycode != DC_DOM) {
  1219.             *ep++ = 0;
  1220.             if (*ep++ != '=') {
  1221.                 error("invalid day of month");
  1222.                 ifree(dp);
  1223.                 return;
  1224.             }
  1225.             if ((lp = byword(dp, wday_names)) == NULL) {
  1226.                 error("invalid weekday name");
  1227.                 ifree(dp);
  1228.                 return;
  1229.             }
  1230.             rp->r_wday = lp->l_value;
  1231.         }
  1232.         if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 ||
  1233.             rp->r_dayofmonth <= 0 ||
  1234.             (rp->r_dayofmonth > len_months[1][rp->r_month])) {
  1235.                 error("invalid day of month");
  1236.                 ifree(dp);
  1237.                 return;
  1238.         }
  1239.     }
  1240.     ifree(dp);
  1241. }
  1242.  
  1243. static void
  1244. convert(val, buf)
  1245. const long    val;
  1246. char * const    buf;
  1247. {
  1248.     register int    i;
  1249.     register long    shift;
  1250.  
  1251.     for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
  1252.         buf[i] = val >> shift;
  1253. }
  1254.  
  1255. static void
  1256. puttzcode(val, fp)
  1257. const long    val;
  1258. FILE * const    fp;
  1259. {
  1260.     char    buf[4];
  1261.  
  1262.     convert(val, buf);
  1263.     (void) fwrite((genericptr_T) buf,
  1264.         (fwrite_size_T) sizeof buf,
  1265.         (fwrite_size_T) 1, fp);
  1266. }
  1267.  
  1268. static void
  1269. writezone(name)
  1270. const char * const    name;
  1271. {
  1272.     register FILE *        fp;
  1273.     register int        i, j;
  1274.     static char *        fullname;
  1275.     static struct tzhead    tzh;
  1276.  
  1277.     fullname = erealloc(fullname,
  1278.         (int) (strlen(directory) + 1 + strlen(name) + 1));
  1279.     (void) sprintf(fullname, "%s/%s", directory, name);
  1280.     if ((fp = fopen(fullname, "wb")) == NULL) {
  1281.         if (mkdirs(fullname) != 0)
  1282.             (void) exit(EXIT_FAILURE);
  1283.         if ((fp = fopen(fullname, "wb")) == NULL) {
  1284.             (void) fprintf(stderr, "%s: Can't create ", progname);
  1285.             (void) perror(fullname);
  1286.             (void) exit(EXIT_FAILURE);
  1287.         }
  1288.     }
  1289.     convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
  1290.     convert(eitol(leapcnt), tzh.tzh_leapcnt);
  1291.     convert(eitol(timecnt), tzh.tzh_timecnt);
  1292.     convert(eitol(typecnt), tzh.tzh_typecnt);
  1293.     convert(eitol(charcnt), tzh.tzh_charcnt);
  1294.     (void) fwrite((genericptr_T) &tzh,
  1295.         (fwrite_size_T) sizeof tzh,
  1296.         (fwrite_size_T) 1, fp);
  1297.     for (i = 0; i < timecnt; ++i) {
  1298.         j = leapcnt;
  1299.         while (--j >= 0)
  1300.             if (ats[i] >= trans[j]) {
  1301.                 ats[i] = tadd(ats[i], corr[j]);
  1302.                 break;
  1303.             }
  1304.         puttzcode((long) ats[i], fp);
  1305.     }
  1306.     if (timecnt > 0)
  1307.         (void) fwrite((genericptr_T) types,
  1308.             (fwrite_size_T) sizeof types[0],
  1309.             (fwrite_size_T) timecnt, fp);
  1310.     for (i = 0; i < typecnt; ++i) {
  1311.         puttzcode((long) gmtoffs[i], fp);
  1312.         (void) putc(isdsts[i], fp);
  1313.         (void) putc(abbrinds[i], fp);
  1314.     }
  1315.     if (charcnt != 0)
  1316.         (void) fwrite((genericptr_T) chars,
  1317.             (fwrite_size_T) sizeof chars[0],
  1318.             (fwrite_size_T) charcnt, fp);
  1319.     for (i = 0; i < leapcnt; ++i) {
  1320.         if (roll[i]) {
  1321.             if (timecnt == 0 || trans[i] < ats[0]) {
  1322.                 j = 0;
  1323.                 while (isdsts[j])
  1324.                     if (++j >= typecnt) {
  1325.                         j = 0;
  1326.                         break;
  1327.                     }
  1328.             } else {
  1329.                 j = 1;
  1330.                 while (j < timecnt && trans[i] >= ats[j])
  1331.                     ++j;
  1332.                 j = types[j - 1];
  1333.             }
  1334.             puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
  1335.         } else    puttzcode((long) trans[i], fp);
  1336.         puttzcode((long) corr[i], fp);
  1337.     }
  1338.     for (i = 0; i < typecnt; ++i)
  1339.         (void) putc(ttisstds[i], fp);
  1340.     if (ferror(fp) || fclose(fp)) {
  1341.         (void) fprintf(stderr, "%s: Write error on ", progname);
  1342.         (void) perror(fullname);
  1343.         (void) exit(EXIT_FAILURE);
  1344.     }
  1345. }
  1346.  
  1347. static void
  1348. outzone(zpfirst, zonecount)
  1349. const struct zone * const    zpfirst;
  1350. const int            zonecount;
  1351. {
  1352.     register const struct zone *    zp;
  1353.     register struct rule *        rp;
  1354.     register int            i, j;
  1355.     register int            usestart, useuntil;
  1356.     register time_t            starttime, untiltime;
  1357.     register long            gmtoff;
  1358.     register long            stdoff;
  1359.     register int            year;
  1360.     register long            startoff;
  1361.     register int            startisdst;
  1362.     register int            startttisstd;
  1363.     register int            type;
  1364.     char                startbuf[BUFSIZ];
  1365.  
  1366.     INITIALIZE(untiltime);
  1367.     INITIALIZE(starttime);
  1368.     INITIALIZE(startoff);
  1369.     /*
  1370.     ** Now. . .finally. . .generate some useful data!
  1371.     */
  1372.     timecnt = 0;
  1373.     typecnt = 0;
  1374.     charcnt = 0;
  1375.     /*
  1376.     ** A guess that may well be corrected later.
  1377.     */
  1378.     stdoff = 0;
  1379.     /*
  1380.     ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au)
  1381.     ** for noting the need to unconditionally initialize startttisstd.
  1382.     */
  1383.     startttisstd = FALSE;
  1384. #ifdef lint
  1385.     starttime = 0;
  1386. #endif /* defined lint */
  1387.     for (i = 0; i < zonecount; ++i) {
  1388.         zp = &zpfirst[i];
  1389.         usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
  1390.         useuntil = i < (zonecount - 1);
  1391.         if (useuntil && zp->z_untiltime <= min_time)
  1392.             continue;
  1393.         gmtoff = zp->z_gmtoff;
  1394.         eat(zp->z_filename, zp->z_linenum);
  1395.         startisdst = -1;
  1396.         if (zp->z_nrules == 0) {
  1397.             stdoff = zp->z_stdoff;
  1398.             (void) strcpy(startbuf, zp->z_format);
  1399.             type = addtype(oadd(zp->z_gmtoff, stdoff),
  1400.                 startbuf, stdoff != 0, startttisstd);
  1401.             if (usestart)
  1402.                 addtt(starttime, type);
  1403.             else if (stdoff != 0)
  1404.                 addtt(min_time, type);
  1405.         } else for (year = min_year; year <= max_year; ++year) {
  1406.             if (useuntil && year > zp->z_untilrule.r_hiyear)
  1407.                 break;
  1408.             /*
  1409.             ** Mark which rules to do in the current year.
  1410.             ** For those to do, calculate rpytime(rp, year);
  1411.             */
  1412.             for (j = 0; j < zp->z_nrules; ++j) {
  1413.                 rp = &zp->z_rules[j];
  1414.                 eats(zp->z_filename, zp->z_linenum,
  1415.                     rp->r_filename, rp->r_linenum);
  1416.                 rp->r_todo = year >= rp->r_loyear &&
  1417.                         year <= rp->r_hiyear &&
  1418.                         yearistype(year, rp->r_yrtype);
  1419.                 if (rp->r_todo)
  1420.                     rp->r_temp = rpytime(rp, year);
  1421.             }
  1422.             for ( ; ; ) {
  1423.                 register int    k;
  1424.                 register time_t    jtime, ktime;
  1425.                 register long    offset;
  1426.                 char        buf[BUFSIZ];
  1427.  
  1428.                 INITIALIZE(ktime);
  1429.                 if (useuntil) {
  1430.                     /*
  1431.                     ** Turn untiltime into GMT
  1432.                     ** assuming the current gmtoff and
  1433.                     ** stdoff values.
  1434.                     */
  1435.                     untiltime = zp->z_untiltime;
  1436.                     if (!zp->z_untilrule.r_todisuniv)
  1437.                         untiltime = tadd(untiltime,
  1438.                             -gmtoff);
  1439.                     if (!zp->z_untilrule.r_todisstd)
  1440.                         untiltime = tadd(untiltime,
  1441.                             -stdoff);
  1442.                 }
  1443.                 /*
  1444.                 ** Find the rule (of those to do, if any)
  1445.                 ** that takes effect earliest in the year.
  1446.                 */
  1447.                 k = -1;
  1448. #ifdef lint
  1449.                 ktime = 0;
  1450. #endif /* defined lint */
  1451.                 for (j = 0; j < zp->z_nrules; ++j) {
  1452.                     rp = &zp->z_rules[j];
  1453.                     if (!rp->r_todo)
  1454.                         continue;
  1455.                     eats(zp->z_filename, zp->z_linenum,
  1456.                         rp->r_filename, rp->r_linenum);
  1457.                     offset = rp->r_todisuniv ? 0 : gmtoff;
  1458.                     if (!rp->r_todisstd)
  1459.                         offset = oadd(offset, stdoff);
  1460.                     jtime = rp->r_temp;
  1461.                     if (jtime == min_time ||
  1462.                         jtime == max_time)
  1463.                             continue;
  1464.                     jtime = tadd(jtime, -offset);
  1465.                     if (k < 0 || jtime < ktime) {
  1466.                         k = j;
  1467.                         ktime = jtime;
  1468.                     }
  1469.                 }
  1470.                 if (k < 0)
  1471.                     break;    /* go on to next year */
  1472.                 rp = &zp->z_rules[k];
  1473.                 rp->r_todo = FALSE;
  1474.                 if (useuntil && ktime >= untiltime)
  1475.                     break;
  1476.                 if (usestart) {
  1477.                     if (ktime < starttime) {
  1478.                     stdoff = rp->r_stdoff;
  1479.                     startoff = oadd(zp->z_gmtoff,
  1480.                         rp->r_stdoff);
  1481.                     (void) sprintf(startbuf, zp->z_format,
  1482.                         rp->r_abbrvar);
  1483.                     startisdst = rp->r_stdoff != 0;
  1484.                     continue;
  1485.                     }
  1486.                     usestart = FALSE;
  1487.                     if (ktime != starttime) {
  1488.                     if (startisdst < 0 &&
  1489.                         zp->z_gmtoff !=
  1490.                         (zp - 1)->z_gmtoff) {
  1491.                         type = (timecnt == 0) ? 0 :
  1492.                             types[timecnt - 1];
  1493.                         startoff = oadd(gmtoffs[type],
  1494.                             -(zp - 1)->z_gmtoff);
  1495.                         startisdst = startoff != 0;
  1496.                         startoff = oadd(startoff,
  1497.                             zp->z_gmtoff);
  1498.                         (void) strcpy(startbuf,
  1499.                             &chars[abbrinds[type]]);
  1500.                     }
  1501.                     if (startisdst >= 0)
  1502. addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd));
  1503.                     }
  1504.                 }
  1505.                 eats(zp->z_filename, zp->z_linenum,
  1506.                     rp->r_filename, rp->r_linenum);
  1507.                 (void) sprintf(buf, zp->z_format,
  1508.                     rp->r_abbrvar);
  1509.                 offset = oadd(zp->z_gmtoff, rp->r_stdoff);
  1510.                 type = addtype(offset, buf, rp->r_stdoff != 0,
  1511.                     rp->r_todisstd);
  1512.                 addtt(ktime, type);
  1513.                 stdoff = rp->r_stdoff;
  1514.             }
  1515.         }
  1516.         /*
  1517.         ** Now we may get to set starttime for the next zone line.
  1518.         */
  1519.         if (useuntil) {
  1520.             starttime = tadd(zp->z_untiltime, -gmtoff);
  1521.             startttisstd = zp->z_untilrule.r_todisstd;
  1522.             if (!startttisstd)
  1523.                 starttime = tadd(starttime, -stdoff);
  1524.         }
  1525.     }
  1526.     writezone(zpfirst->z_name);
  1527. }
  1528.  
  1529. static void
  1530. addtt(starttime, type)
  1531. const time_t    starttime;
  1532. const int    type;
  1533. {
  1534.     if (timecnt != 0 && type == types[timecnt - 1])
  1535.         return;    /* easy enough! */
  1536.     if (timecnt == 0 && type == 0 && isdsts[0] == 0)
  1537.         return; /* handled by default rule */
  1538.     if (timecnt >= TZ_MAX_TIMES) {
  1539.         error("too many transitions?!");
  1540.         (void) exit(EXIT_FAILURE);
  1541.     }
  1542.     ats[timecnt] = starttime;
  1543.     types[timecnt] = type;
  1544.     ++timecnt;
  1545. }
  1546.  
  1547. static int
  1548. addtype(gmtoff, abbr, isdst, ttisstd)
  1549. const long        gmtoff;
  1550. const char * const    abbr;
  1551. const int        isdst;
  1552. const int        ttisstd;
  1553. {
  1554.     register int    i, j;
  1555.  
  1556.     /*
  1557.     ** See if there's already an entry for this zone type.
  1558.     ** If so, just return its index.
  1559.     */
  1560.     for (i = 0; i < typecnt; ++i) {
  1561.         if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
  1562.             strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
  1563.             ttisstd == ttisstds[i])
  1564.                 return i;
  1565.     }
  1566.     /*
  1567.     ** There isn't one; add a new one, unless there are already too
  1568.     ** many.
  1569.     */
  1570.     if (typecnt >= TZ_MAX_TYPES) {
  1571.         error("too many local time types");
  1572.         (void) exit(EXIT_FAILURE);
  1573.     }
  1574.     gmtoffs[i] = gmtoff;
  1575.     isdsts[i] = isdst;
  1576.     ttisstds[i] = ttisstd;
  1577.  
  1578.     for (j = 0; j < charcnt; ++j)
  1579.         if (strcmp(&chars[j], abbr) == 0)
  1580.             break;
  1581.     if (j == charcnt)
  1582.         newabbr(abbr);
  1583.     abbrinds[i] = j;
  1584.     ++typecnt;
  1585.     return i;
  1586. }
  1587.  
  1588. static void
  1589. leapadd(t, positive, rolling, count)
  1590. const time_t    t;
  1591. const int    positive;
  1592. const int    rolling;
  1593. int        count;
  1594. {
  1595.     register int    i, j;
  1596.  
  1597.     if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {
  1598.         error("too many leap seconds");
  1599.         (void) exit(EXIT_FAILURE);
  1600.     }
  1601.     for (i = 0; i < leapcnt; ++i)
  1602.         if (t <= trans[i]) {
  1603.             if (t == trans[i]) {
  1604.                 error("repeated leap second moment");
  1605.                 (void) exit(EXIT_FAILURE);
  1606.             }
  1607.             break;
  1608.         }
  1609.     do {
  1610.         for (j = leapcnt; j > i; --j) {
  1611.             trans[j] = trans[j - 1];
  1612.             corr[j] = corr[j - 1];
  1613.             roll[j] = roll[j - 1];
  1614.         }
  1615.         trans[i] = t;
  1616.         corr[i] = positive ? 1L : eitol(-count);
  1617.         roll[i] = rolling;
  1618.         ++leapcnt;
  1619.     } while (positive && --count != 0);
  1620. }
  1621.  
  1622. static void
  1623. adjleap P((void))
  1624. {
  1625.     register int    i;
  1626.     register long    last = 0;
  1627.  
  1628.     /*
  1629.     ** propagate leap seconds forward
  1630.     */
  1631.     for (i = 0; i < leapcnt; ++i) {
  1632.         trans[i] = tadd(trans[i], last);
  1633.         last = corr[i] += last;
  1634.     }
  1635. }
  1636.  
  1637. static int
  1638. yearistype(year, type)
  1639. const int        year;
  1640. const char * const    type;
  1641. {
  1642.     static char *    buf;
  1643.     int        result;
  1644.  
  1645.     if (type == NULL || *type == '\0')
  1646.         return TRUE;
  1647.     buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type)));
  1648.     (void) sprintf(buf, "%s %d %s", yitcommand, year, type);
  1649.     result = system(buf);
  1650.     if (result == 0)
  1651.         return TRUE;
  1652.     if (result == (1 << 8))
  1653.         return FALSE;
  1654.     error("Wild result from command execution");
  1655.     (void) fprintf(stderr, "%s: command was '%s', result was %d\n",
  1656.         progname, buf, result);
  1657.     for ( ; ; )
  1658.         (void) exit(EXIT_FAILURE);
  1659. }
  1660.  
  1661. static int
  1662. lowerit(a)
  1663. const int    a;
  1664. {
  1665.     return (isascii(a) && isupper(a)) ? tolower(a) : a;
  1666. }
  1667.  
  1668. static int
  1669. ciequal(ap, bp)        /* case-insensitive equality */
  1670. register const char *    ap;
  1671. register const char *    bp;
  1672. {
  1673.     while (lowerit(*ap) == lowerit(*bp++))
  1674.         if (*ap++ == '\0')
  1675.             return TRUE;
  1676.     return FALSE;
  1677. }
  1678.  
  1679. static int
  1680. itsabbr(abbr, word)
  1681. register const char *    abbr;
  1682. register const char *    word;
  1683. {
  1684.     if (lowerit(*abbr) != lowerit(*word))
  1685.         return FALSE;
  1686.     ++word;
  1687.     while (*++abbr != '\0')
  1688.         do if (*word == '\0')
  1689.             return FALSE;
  1690.                 while (lowerit(*word++) != lowerit(*abbr));
  1691.     return TRUE;
  1692. }
  1693.  
  1694. static const struct lookup *
  1695. byword(word, table)
  1696. register const char * const        word;
  1697. register const struct lookup * const    table;
  1698. {
  1699.     register const struct lookup *    foundlp;
  1700.     register const struct lookup *    lp;
  1701.  
  1702.     if (word == NULL || table == NULL)
  1703.         return NULL;
  1704.     /*
  1705.     ** Look for exact match.
  1706.     */
  1707.     for (lp = table; lp->l_word != NULL; ++lp)
  1708.         if (ciequal(word, lp->l_word))
  1709.             return lp;
  1710.     /*
  1711.     ** Look for inexact match.
  1712.     */
  1713.     foundlp = NULL;
  1714.     for (lp = table; lp->l_word != NULL; ++lp)
  1715.         if (itsabbr(word, lp->l_word))
  1716.             if (foundlp == NULL)
  1717.                 foundlp = lp;
  1718.             else    return NULL;    /* multiple inexact matches */
  1719.     return foundlp;
  1720. }
  1721.  
  1722. static char **
  1723. getfields(cp)
  1724. register char *    cp;
  1725. {
  1726.     register char *        dp;
  1727.     register char **    array;
  1728.     register int        nsubs;
  1729.  
  1730.     if (cp == NULL)
  1731.         return NULL;
  1732.     array = (char **) (void *)
  1733.         emalloc((int) ((strlen(cp) + 1) * sizeof *array));
  1734.     nsubs = 0;
  1735.     for ( ; ; ) {
  1736.         while (isascii(*cp) && isspace(*cp))
  1737.             ++cp;
  1738.         if (*cp == '\0' || *cp == '#')
  1739.             break;
  1740.         array[nsubs++] = dp = cp;
  1741.         do {
  1742.             if ((*dp = *cp++) != '"')
  1743.                 ++dp;
  1744.             else while ((*dp = *cp++) != '"')
  1745.                 if (*dp != '\0')
  1746.                     ++dp;
  1747.                 else    error("Odd number of quotation marks");
  1748.         } while (*cp != '\0' && *cp != '#' &&
  1749.             (!isascii(*cp) || !isspace(*cp)));
  1750.         if (isascii(*cp) && isspace(*cp))
  1751.             ++cp;
  1752.         *dp = '\0';
  1753.     }
  1754.     array[nsubs] = NULL;
  1755.     return array;
  1756. }
  1757.  
  1758. static long
  1759. oadd(t1, t2)
  1760. const long    t1;
  1761. const long    t2;
  1762. {
  1763.     register long    t;
  1764.  
  1765.     t = t1 + t2;
  1766.     if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
  1767.         error("time overflow");
  1768.         (void) exit(EXIT_FAILURE);
  1769.     }
  1770.     return t;
  1771. }
  1772.  
  1773. static time_t
  1774. tadd(t1, t2)
  1775. const time_t    t1;
  1776. const long    t2;
  1777. {
  1778.     register time_t    t;
  1779.  
  1780.     if (t1 == max_time && t2 > 0)
  1781.         return max_time;
  1782.     if (t1 == min_time && t2 < 0)
  1783.         return min_time;
  1784.     t = t1 + t2;
  1785.     if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
  1786.         error("time overflow");
  1787.         (void) exit(EXIT_FAILURE);
  1788.     }
  1789.     return t;
  1790. }
  1791.  
  1792. /*
  1793. ** Given a rule, and a year, compute the date - in seconds since January 1,
  1794. ** 1970, 00:00 LOCAL time - in that year that the rule refers to.
  1795. */
  1796.  
  1797. static time_t
  1798. rpytime(rp, wantedy)
  1799. register const struct rule * const    rp;
  1800. register const int            wantedy;
  1801. {
  1802.     register int    y, m, i;
  1803.     register long    dayoff;            /* with a nod to Margaret O. */
  1804.     register time_t    t;
  1805.  
  1806.     if (wantedy == min_int)
  1807.         return min_time;
  1808.     if (wantedy == max_int)
  1809.         return max_time;
  1810.     dayoff = 0;
  1811.     m = TM_JANUARY;
  1812.     y = EPOCH_YEAR;
  1813.     while (wantedy != y) {
  1814.         if (wantedy > y) {
  1815.             i = len_years[isleap(y)];
  1816.             ++y;
  1817.         } else {
  1818.             --y;
  1819.             i = -len_years[isleap(y)];
  1820.         }
  1821.         dayoff = oadd(dayoff, eitol(i));
  1822.     }
  1823.     while (m != rp->r_month) {
  1824.         i = len_months[isleap(y)][m];
  1825.         dayoff = oadd(dayoff, eitol(i));
  1826.         ++m;
  1827.     }
  1828.     i = rp->r_dayofmonth;
  1829.     if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
  1830.         if (rp->r_dycode == DC_DOWLEQ)
  1831.             --i;
  1832.         else {
  1833.             error("use of 2/29 in non leap-year");
  1834.             (void) exit(EXIT_FAILURE);
  1835.         }
  1836.     }
  1837.     --i;
  1838.     dayoff = oadd(dayoff, eitol(i));
  1839.     if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
  1840.         register long    wday;
  1841.  
  1842. #define LDAYSPERWEEK    ((long) DAYSPERWEEK)
  1843.         wday = eitol(EPOCH_WDAY);
  1844.         /*
  1845.         ** Don't trust mod of negative numbers.
  1846.         */
  1847.         if (dayoff >= 0)
  1848.             wday = (wday + dayoff) % LDAYSPERWEEK;
  1849.         else {
  1850.             wday -= ((-dayoff) % LDAYSPERWEEK);
  1851.             if (wday < 0)
  1852.                 wday += LDAYSPERWEEK;
  1853.         }
  1854.         while (wday != eitol(rp->r_wday))
  1855.             if (rp->r_dycode == DC_DOWGEQ) {
  1856.                 dayoff = oadd(dayoff, (long) 1);
  1857.                 if (++wday >= LDAYSPERWEEK)
  1858.                     wday = 0;
  1859.                 ++i;
  1860.             } else {
  1861.                 dayoff = oadd(dayoff, (long) -1);
  1862.                 if (--wday < 0)
  1863.                     wday = LDAYSPERWEEK - 1;
  1864.                 --i;
  1865.             }
  1866.         if (i < 0 || i >= len_months[isleap(y)][m]) {
  1867.             error("no day in month matches rule");
  1868.             (void) exit(EXIT_FAILURE);
  1869.         }
  1870.     }
  1871.     if (dayoff < 0 && !tt_signed)
  1872.         return min_time;
  1873.     t = (time_t) dayoff * SECSPERDAY;
  1874.     /*
  1875.     ** Cheap overflow check.
  1876.     */
  1877.     if (t / SECSPERDAY != dayoff)
  1878.         return (dayoff > 0) ? max_time : min_time;
  1879.     return tadd(t, rp->r_tod);
  1880. }
  1881.  
  1882. static void
  1883. newabbr(string)
  1884. const char * const    string;
  1885. {
  1886.     register int    i;
  1887.  
  1888.     i = strlen(string) + 1;
  1889.     if (charcnt + i > TZ_MAX_CHARS) {
  1890.         error("too many, or too long, time zone abbreviations");
  1891.         (void) exit(EXIT_FAILURE);
  1892.     }
  1893.     (void) strcpy(&chars[charcnt], string);
  1894.     charcnt += eitol(i);
  1895. }
  1896.  
  1897. static int
  1898. mkdirs(argname)
  1899. char * const    argname;
  1900. {
  1901.     register char *    name;
  1902.     register char *    cp;
  1903.  
  1904.     if (argname == NULL || *argname == '\0')
  1905.         return 0;
  1906.     cp = name = ecpyalloc(argname);
  1907.     while ((cp = strchr(cp + 1, '/')) != 0) {
  1908.         *cp = '\0';
  1909. #ifndef unix
  1910.         /*
  1911.         ** MS-DOS drive specifier?
  1912.         */
  1913.         if (strlen(name) == 2 && isascii(name[0]) &&
  1914.             isalpha(name[0]) && name[1] == ':') {
  1915.                 *cp = '/';
  1916.                 continue;
  1917.         }
  1918. #endif /* !defined unix */
  1919.         if (!itsdir(name)) {
  1920.             /*
  1921.             ** It doesn't seem to exist, so we try to create it.
  1922.             */
  1923.             if (emkdir(name, 0755) != 0) {
  1924.                 (void) fprintf(stderr,
  1925.                     "%s: Can't create directory ",
  1926.                     progname);
  1927.                 (void) perror(name);
  1928.                 ifree(name);
  1929.                 return -1;
  1930.             }
  1931.         }
  1932.         *cp = '/';
  1933.     }
  1934.     ifree(name);
  1935.     return 0;
  1936. }
  1937.  
  1938. static long
  1939. eitol(i)
  1940. const int    i;
  1941. {
  1942.     long    l;
  1943.  
  1944.     l = i;
  1945.     if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) {
  1946.         (void) fprintf(stderr,
  1947.             "%s: %d did not sign extend correctly\n",
  1948.             progname, i);
  1949.         (void) exit(EXIT_FAILURE);
  1950.     }
  1951.     return l;
  1952. }
  1953.  
  1954. /*
  1955. ** UNIX was a registered trademark of UNIX System Laboratories in 1993.
  1956. */
  1957.