home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / gcc / ixemulsrc.lha / ixemul / utils / zic.c < prev    next >
C/C++ Source or Header  |  1996-12-11  |  50KB  |  2,149 lines

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