Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / icu / source / tools / tzcode / zic.c
1 /*
2 ** This file is in the public domain, so clarified as of
3 ** 2006-07-17 by Arthur David Olson.
4 */
5
6 static char     elsieid[] = "@(#)zic.c  8.18";
7
8 #include "private.h"
9 #include "locale.h"
10 #include "tzfile.h"
11
12 #define ZIC_VERSION     '2'
13
14 typedef int_fast64_t    zic_t;
15
16 #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
17 #define ZIC_MAX_ABBR_LEN_WO_WARN        6
18 #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
19
20 #if HAVE_SYS_STAT_H
21 #include "sys/stat.h"
22 #endif
23 #ifdef S_IRUSR
24 #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
25 #else
26 #define MKDIR_UMASK 0755
27 #endif
28
29 /* Enable extensions and modifications for ICU. */
30 #define ICU
31
32 /* Continue executing after link failure. Even if ICU is undefined
33  * (for vanilla zic behavior), ICU_LINKS should be defined, since zic
34  * appears to fail on the 2003 data the first time through during the
35  * linking phase. Running zic twice, with ICU_LINKS defined, causes
36  * links to be handled correctly. */
37 #define ICU_LINKS
38
39 #ifdef ICU
40 #include "tz2icu.h"
41 #endif
42
43 /*
44 ** On some ancient hosts, predicates like `isspace(C)' are defined
45 ** only if isascii(C) || C == EOF. Modern hosts obey the C Standard,
46 ** which says they are defined only if C == ((unsigned char) C) || C == EOF.
47 ** Neither the C Standard nor Posix require that `isascii' exist.
48 ** For portability, we check both ancient and modern requirements.
49 ** If isascii is not defined, the isascii check succeeds trivially.
50 */
51 #include "ctype.h"
52 #ifndef isascii
53 #define isascii(x) 1
54 #endif
55
56 #define OFFSET_STRLEN_MAXIMUM   (7 + INT_STRLEN_MAXIMUM(long))
57 #define RULE_STRLEN_MAXIMUM     8       /* "Mdd.dd.d" */
58
59 #define end(cp) (strchr((cp), '\0'))
60
61 struct rule {
62         const char *    r_filename;
63         int             r_linenum;
64         const char *    r_name;
65
66         int             r_loyear;       /* for example, 1986 */
67         int             r_hiyear;       /* for example, 1986 */
68         const char *    r_yrtype;
69         int             r_lowasnum;
70         int             r_hiwasnum;
71
72         int             r_month;        /* 0..11 */
73
74         int             r_dycode;       /* see below */
75         int             r_dayofmonth;
76         int             r_wday;
77
78         long            r_tod;          /* time from midnight */
79         int             r_todisstd;     /* above is standard time if TRUE */
80                                         /* or wall clock time if FALSE */
81         int             r_todisgmt;     /* above is GMT if TRUE */
82                                         /* or local time if FALSE */
83         long            r_stdoff;       /* offset from standard time */
84         const char *    r_abbrvar;      /* variable part of abbreviation */
85
86         int             r_todo;         /* a rule to do (used in outzone) */
87         zic_t           r_temp;         /* used in outzone */
88 };
89
90 /*
91 **      r_dycode                r_dayofmonth    r_wday
92 */
93
94 #define DC_DOM          0       /* 1..31 */     /* unused */
95 #define DC_DOWGEQ       1       /* 1..31 */     /* 0..6 (Sun..Sat) */
96 #define DC_DOWLEQ       2       /* 1..31 */     /* 0..6 (Sun..Sat) */
97
98 struct zone {
99         const char *    z_filename;
100         int             z_linenum;
101
102         const char *    z_name;
103         long            z_gmtoff;
104         const char *    z_rule;
105         const char *    z_format;
106
107         long            z_stdoff;
108
109         struct rule *   z_rules;
110         int             z_nrules;
111
112         struct rule     z_untilrule;
113         zic_t           z_untiltime;
114 };
115
116 extern int      getopt(int argc, char * const argv[],
117                         const char * options);
118 extern int      link(const char * fromname, const char * toname);
119 extern char *   optarg;
120 extern int      optind;
121
122 static void     addtt(zic_t starttime, int type);
123 #ifdef ICU
124 static int      addtype(long gmtoff, long rawoff, long dstoff,
125                                 const char * abbr, int isdst,
126                                 int ttisstd, int ttisgmt);
127 #else
128 static int      addtype(long gmtoff, const char * abbr, int isdst,
129                                 int ttisstd, int ttisgmt);
130 #endif
131 static void     leapadd(zic_t t, int positive, int rolling, int count);
132 static void     adjleap(void);
133 static void     associate(void);
134 static int      ciequal(const char * ap, const char * bp);
135 static void     convert(long val, char * buf);
136 static void     convert64(zic_t val, char * buf);
137 static void     dolink(const char * fromfield, const char * tofield);
138 static void     doabbr(char * abbr, const char * format,
139                         const char * letters, int isdst, int doquotes);
140 static void     eat(const char * name, int num);
141 static void     eats(const char * name, int num,
142                         const char * rname, int rnum);
143 static long     eitol(int i);
144 static void     error(const char * message);
145 static char **  getfields(char * buf);
146 static long     gethms(const char * string, const char * errstrng,
147                         int signable);
148 static void     infile(const char * filename);
149 static void     inleap(char ** fields, int nfields);
150 static void     inlink(char ** fields, int nfields);
151 static void     inrule(char ** fields, int nfields);
152 static int      inzcont(char ** fields, int nfields);
153 static int      inzone(char ** fields, int nfields);
154 static int      inzsub(char ** fields, int nfields, int iscont);
155 static int      is32(zic_t x);
156 static int      itsabbr(const char * abbr, const char * word);
157 static int      itsdir(const char * name);
158 static int      lowerit(int c);
159 static char *   memcheck(char * tocheck);
160 static int      mkdirs(char * filename);
161 static void     newabbr(const char * abbr);
162 static long     oadd(long t1, long t2);
163 static void     outzone(const struct zone * zp, int ntzones);
164 static void     puttzcode(long code, FILE * fp);
165 static void     puttzcode64(zic_t code, FILE * fp);
166 static int      rcomp(const void * leftp, const void * rightp);
167 static zic_t    rpytime(const struct rule * rp, int wantedy);
168 static void     rulesub(struct rule * rp,
169                         const char * loyearp, const char * hiyearp,
170                         const char * typep, const char * monthp,
171                         const char * dayp, const char * timep);
172 static int      stringoffset(char * result, long offset);
173 static int      stringrule(char * result, const struct rule * rp,
174                         long dstoff, long gmtoff);
175 static void     stringzone(char * result,
176                         const struct zone * zp, int ntzones);
177 static void     setboundaries(void);
178 static zic_t    tadd(zic_t t1, long t2);
179 static void     usage(FILE *stream, int status);
180 static void     writezone(const char * name, const char * string);
181 static int      yearistype(int year, const char * type);
182 #ifdef ICU
183 static void     emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset,
184                                         const struct rule* rule,
185                                         int ruleIndex, int startYear);
186 static void     emit_icu_link(FILE* f, const char* from, const char* to);
187 static void     emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex);
188 static int      add_icu_final_rules(const struct rule* r1, const struct rule* r2);
189 #endif
190
191 static int              charcnt;
192 static int              errors;
193 static const char *     filename;
194 static int              leapcnt;
195 static int              leapseen;
196 static int              leapminyear;
197 static int              leapmaxyear;
198 static int              linenum;
199 static int              max_abbrvar_len;
200 static int              max_format_len;
201 static zic_t            max_time;
202 static int              max_year;
203 static zic_t            min_time;
204 static int              min_year;
205 static int              noise;
206 static const char *     rfilename;
207 static int              rlinenum;
208 static const char *     progname;
209 static int              timecnt;
210 static int              typecnt;
211
212 /*
213 ** Line codes.
214 */
215
216 #define LC_RULE         0
217 #define LC_ZONE         1
218 #define LC_LINK         2
219 #define LC_LEAP         3
220
221 /*
222 ** Which fields are which on a Zone line.
223 */
224
225 #define ZF_NAME         1
226 #define ZF_GMTOFF       2
227 #define ZF_RULE         3
228 #define ZF_FORMAT       4
229 #define ZF_TILYEAR      5
230 #define ZF_TILMONTH     6
231 #define ZF_TILDAY       7
232 #define ZF_TILTIME      8
233 #define ZONE_MINFIELDS  5
234 #define ZONE_MAXFIELDS  9
235
236 /*
237 ** Which fields are which on a Zone continuation line.
238 */
239
240 #define ZFC_GMTOFF      0
241 #define ZFC_RULE        1
242 #define ZFC_FORMAT      2
243 #define ZFC_TILYEAR     3
244 #define ZFC_TILMONTH    4
245 #define ZFC_TILDAY      5
246 #define ZFC_TILTIME     6
247 #define ZONEC_MINFIELDS 3
248 #define ZONEC_MAXFIELDS 7
249
250 /*
251 ** Which files are which on a Rule line.
252 */
253
254 #define RF_NAME         1
255 #define RF_LOYEAR       2
256 #define RF_HIYEAR       3
257 #define RF_COMMAND      4
258 #define RF_MONTH        5
259 #define RF_DAY          6
260 #define RF_TOD          7
261 #define RF_STDOFF       8
262 #define RF_ABBRVAR      9
263 #define RULE_FIELDS     10
264
265 /*
266 ** Which fields are which on a Link line.
267 */
268
269 #define LF_FROM         1
270 #define LF_TO           2
271 #define LINK_FIELDS     3
272
273 /*
274 ** Which fields are which on a Leap line.
275 */
276
277 #define LP_YEAR         1
278 #define LP_MONTH        2
279 #define LP_DAY          3
280 #define LP_TIME         4
281 #define LP_CORR         5
282 #define LP_ROLL         6
283 #define LEAP_FIELDS     7
284
285 /*
286 ** Year synonyms.
287 */
288
289 #define YR_MINIMUM      0
290 #define YR_MAXIMUM      1
291 #define YR_ONLY         2
292
293 static struct rule *    rules;
294 static int              nrules; /* number of rules */
295
296 static struct zone *    zones;
297 static int              nzones; /* number of zones */
298
299 struct link {
300         const char *    l_filename;
301         int             l_linenum;
302         const char *    l_from;
303         const char *    l_to;
304 };
305
306 static struct link *    links;
307 static int              nlinks;
308
309 struct lookup {
310         const char *    l_word;
311         const int       l_value;
312 };
313
314 #ifdef ICU
315 /* Indices into rules[] for final rules.  They will occur in pairs,
316  * with finalRules[i] occurring before finalRules[i+1] in the year.
317  * Each zone need only store a start year, a standard offset, and an
318  * index into finalRules[].  FinalRules[] are aliases into rules[]. */
319 static const struct rule **     finalRules;
320 static int                                      finalRulesCount;
321 #endif
322
323 static struct lookup const *    byword(const char * string,
324                                         const struct lookup * lp);
325
326 static struct lookup const      line_codes[] = {
327         { "Rule",       LC_RULE },
328         { "Zone",       LC_ZONE },
329         { "Link",       LC_LINK },
330         { "Leap",       LC_LEAP },
331         { NULL,         0}
332 };
333
334 static struct lookup const      mon_names[] = {
335         { "January",    TM_JANUARY },
336         { "February",   TM_FEBRUARY },
337         { "March",      TM_MARCH },
338         { "April",      TM_APRIL },
339         { "May",        TM_MAY },
340         { "June",       TM_JUNE },
341         { "July",       TM_JULY },
342         { "August",     TM_AUGUST },
343         { "September",  TM_SEPTEMBER },
344         { "October",    TM_OCTOBER },
345         { "November",   TM_NOVEMBER },
346         { "December",   TM_DECEMBER },
347         { NULL,         0 }
348 };
349
350 static struct lookup const      wday_names[] = {
351         { "Sunday",     TM_SUNDAY },
352         { "Monday",     TM_MONDAY },
353         { "Tuesday",    TM_TUESDAY },
354         { "Wednesday",  TM_WEDNESDAY },
355         { "Thursday",   TM_THURSDAY },
356         { "Friday",     TM_FRIDAY },
357         { "Saturday",   TM_SATURDAY },
358         { NULL,         0 }
359 };
360
361 static struct lookup const      lasts[] = {
362         { "last-Sunday",        TM_SUNDAY },
363         { "last-Monday",        TM_MONDAY },
364         { "last-Tuesday",       TM_TUESDAY },
365         { "last-Wednesday",     TM_WEDNESDAY },
366         { "last-Thursday",      TM_THURSDAY },
367         { "last-Friday",        TM_FRIDAY },
368         { "last-Saturday",      TM_SATURDAY },
369         { NULL,                 0 }
370 };
371
372 static struct lookup const      begin_years[] = {
373         { "minimum",    YR_MINIMUM },
374         { "maximum",    YR_MAXIMUM },
375         { NULL,         0 }
376 };
377
378 static struct lookup const      end_years[] = {
379         { "minimum",    YR_MINIMUM },
380         { "maximum",    YR_MAXIMUM },
381         { "only",       YR_ONLY },
382         { NULL,         0 }
383 };
384
385 static struct lookup const      leap_types[] = {
386         { "Rolling",    TRUE },
387         { "Stationary", FALSE },
388         { NULL,         0 }
389 };
390
391 static const int        len_months[2][MONSPERYEAR] = {
392         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
393         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
394 };
395
396 static const int        len_years[2] = {
397         DAYSPERNYEAR, DAYSPERLYEAR
398 };
399
400 static struct attype {
401         zic_t           at;
402         unsigned char   type;
403 }                       attypes[TZ_MAX_TIMES];
404 static long             gmtoffs[TZ_MAX_TYPES];
405 #ifdef ICU
406 /* gmtoffs[i] = rawoffs[i] + dstoffs[i] */
407 static long             rawoffs[TZ_MAX_TYPES];
408 static long             dstoffs[TZ_MAX_TYPES];
409 #endif
410 static char             isdsts[TZ_MAX_TYPES];
411 static unsigned char    abbrinds[TZ_MAX_TYPES];
412 static char             ttisstds[TZ_MAX_TYPES];
413 static char             ttisgmts[TZ_MAX_TYPES];
414 static char             chars[TZ_MAX_CHARS];
415 static zic_t            trans[TZ_MAX_LEAPS];
416 static long             corr[TZ_MAX_LEAPS];
417 static char             roll[TZ_MAX_LEAPS];
418
419 /*
420 ** Memory allocation.
421 */
422
423 static char *
424 memcheck(ptr)
425 char * const    ptr;
426 {
427         if (ptr == NULL) {
428                 const char *e = strerror(errno);
429
430                 (void) fprintf(stderr, _("%s: Memory exhausted: %s\n"),
431                         progname, e);
432                 exit(EXIT_FAILURE);
433         }
434         return ptr;
435 }
436
437 #define emalloc(size)           memcheck(imalloc(size))
438 #define erealloc(ptr, size)     memcheck(irealloc((ptr), (size)))
439 #define ecpyalloc(ptr)          memcheck(icpyalloc(ptr))
440 #define ecatalloc(oldp, newp)   memcheck(icatalloc((oldp), (newp)))
441
442 /*
443 ** Error handling.
444 */
445
446 static void
447 eats(name, num, rname, rnum)
448 const char * const      name;
449 const int               num;
450 const char * const      rname;
451 const int               rnum;
452 {
453         filename = name;
454         linenum = num;
455         rfilename = rname;
456         rlinenum = rnum;
457 }
458
459 static void
460 eat(name, num)
461 const char * const      name;
462 const int               num;
463 {
464         eats(name, num, (char *) NULL, -1);
465 }
466
467 static void
468 error(string)
469 const char * const      string;
470 {
471         /*
472         ** Match the format of "cc" to allow sh users to
473         **      zic ... 2>&1 | error -t "*" -v
474         ** on BSD systems.
475         */
476         (void) fprintf(stderr, _("\"%s\", line %d: %s"),
477                 filename, linenum, string);
478         if (rfilename != NULL)
479                 (void) fprintf(stderr, _(" (rule from \"%s\", line %d)"),
480                         rfilename, rlinenum);
481         (void) fprintf(stderr, "\n");
482         ++errors;
483 }
484
485 static void
486 warning(string)
487 const char * const      string;
488 {
489         char *  cp;
490
491         cp = ecpyalloc(_("warning: "));
492         cp = ecatalloc(cp, string);
493         error(cp);
494         ifree(cp);
495         --errors;
496 }
497
498 static void
499 usage(FILE *stream, int status)
500 {
501         (void) fprintf(stream, _("%s: usage is %s \
502 [ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
503 \t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\
504 \n\
505 Report bugs to tz@elsie.nci.nih.gov.\n"),
506                        progname, progname);
507         exit(status);
508 }
509
510 #ifdef ICU
511 /* File into which we will write supplemental ICU data. */
512 static FILE *   icuFile;
513
514 static void
515 emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset,
516                                         const struct rule* rule,
517                                         int ruleIndex, int startYear) {
518         /* machine-readable section */
519         fprintf(f, "zone %s %d %d %s", zoneName, zoneOffset, startYear, rule->r_name);
520
521         /* human-readable section */
522         fprintf(f, " # zone %s, offset %d, year >= %d, rule %s (%d)\n",
523                         zoneName, zoneOffset, startYear,
524                         rule->r_name, ruleIndex);
525 }
526
527 static void
528 emit_icu_link(FILE* f, const char* from, const char* to) {
529         /* machine-readable section */
530         fprintf(f, "link %s %s\n", from, to);
531 }
532
533 static const char* DYCODE[] = {"DOM", "DOWGEQ", "DOWLEQ"};
534
535 static void
536 emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex) {
537         if (r->r_yrtype != NULL) {
538                 warning("year types not supported by ICU");
539                 fprintf(stderr, "rule %s, file %s, line %d\n",
540                                 r->r_name, r->r_filename, r->r_linenum);
541     }
542
543         /* machine-readable section */
544         fprintf(f, "rule %s %s %d %d %d %ld %d %d %ld",
545                         r->r_name, DYCODE[r->r_dycode],
546                         r->r_month, r->r_dayofmonth,
547                         (r->r_dycode == DC_DOM ? -1 : r->r_wday),
548                         r->r_tod, r->r_todisstd, r->r_todisgmt, r->r_stdoff
549                         );
550
551         /* human-readable section */
552         fprintf(f, " # %d: %s, file %s, line %d",
553                         ruleIndex, r->r_name, r->r_filename, r->r_linenum);
554         fprintf(f, ", mode %s", DYCODE[r->r_dycode]);
555         fprintf(f, ", %s, dom %d", mon_names[r->r_month].l_word, r->r_dayofmonth);
556         if (r->r_dycode != DC_DOM) {
557                 fprintf(f, ", %s", wday_names[r->r_wday].l_word);
558         }
559         fprintf(f, ", time %ld", r->r_tod);
560         fprintf(f, ", isstd %d", r->r_todisstd);
561         fprintf(f, ", isgmt %d", r->r_todisgmt);
562         fprintf(f, ", offset %ld", r->r_stdoff);
563         fprintf(f, "\n");
564 }
565
566 static int
567 add_icu_final_rules(const struct rule* r1, const struct rule* r2) {
568         int i;
569
570         for (i=0; i<finalRulesCount; ++i) { /* i+=2 should work too */
571                 if (r1==finalRules[i]) return i; /* [sic] pointer comparison */
572         }
573
574         finalRules = (const struct rule**) (void*) erealloc((char *) finalRules,
575                                 (finalRulesCount + 2) * sizeof(*finalRules));
576         finalRules[finalRulesCount++] = r1;
577         finalRules[finalRulesCount++] = r2;
578         return finalRulesCount - 2;
579 }
580 #endif
581
582 static const char *     psxrules;
583 static const char *     lcltime;
584 static const char *     directory;
585 static const char *     leapsec;
586 static const char *     yitcommand;
587
588 int
589 main(argc, argv)
590 int     argc;
591 char *  argv[];
592 {
593         register int    i;
594         register int    j;
595         register int    c;
596
597 #ifdef unix
598         (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
599 #endif /* defined unix */
600 #if HAVE_GETTEXT
601         (void) setlocale(LC_ALL, "");
602 #ifdef TZ_DOMAINDIR
603         (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
604 #endif /* defined TEXTDOMAINDIR */
605         (void) textdomain(TZ_DOMAIN);
606 #endif /* HAVE_GETTEXT */
607         progname = argv[0];
608         if (TYPE_BIT(zic_t) < 64) {
609                 (void) fprintf(stderr, "%s: %s\n", progname,
610                         _("wild compilation-time specification of zic_t"));
611                 exit(EXIT_FAILURE);
612         }
613         for (i = 1; i < argc; ++i)
614                 if (strcmp(argv[i], "--version") == 0) {
615                         (void) printf("%s\n", elsieid);
616                         exit(EXIT_SUCCESS);
617                 } else if (strcmp(argv[i], "--help") == 0) {
618                         usage(stdout, EXIT_SUCCESS);
619                 }
620         while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
621                 switch (c) {
622                         default:
623                                 usage(stderr, EXIT_FAILURE);
624                         case 'd':
625                                 if (directory == NULL)
626                                         directory = optarg;
627                                 else {
628                                         (void) fprintf(stderr,
629 _("%s: More than one -d option specified\n"),
630                                                 progname);
631                                         exit(EXIT_FAILURE);
632                                 }
633                                 break;
634                         case 'l':
635                                 if (lcltime == NULL)
636                                         lcltime = optarg;
637                                 else {
638                                         (void) fprintf(stderr,
639 _("%s: More than one -l option specified\n"),
640                                                 progname);
641                                         exit(EXIT_FAILURE);
642                                 }
643                                 break;
644                         case 'p':
645                                 if (psxrules == NULL)
646                                         psxrules = optarg;
647                                 else {
648                                         (void) fprintf(stderr,
649 _("%s: More than one -p option specified\n"),
650                                                 progname);
651                                         exit(EXIT_FAILURE);
652                                 }
653                                 break;
654                         case 'y':
655                                 if (yitcommand == NULL)
656                                         yitcommand = optarg;
657                                 else {
658                                         (void) fprintf(stderr,
659 _("%s: More than one -y option specified\n"),
660                                                 progname);
661                                         exit(EXIT_FAILURE);
662                                 }
663                                 break;
664                         case 'L':
665                                 if (leapsec == NULL)
666                                         leapsec = optarg;
667                                 else {
668                                         (void) fprintf(stderr,
669 _("%s: More than one -L option specified\n"),
670                                                 progname);
671                                         exit(EXIT_FAILURE);
672                                 }
673                                 break;
674                         case 'v':
675                                 noise = TRUE;
676                                 break;
677                         case 's':
678                                 (void) printf("%s: -s ignored\n", progname);
679                                 break;
680                 }
681         if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
682                 usage(stderr, EXIT_FAILURE);    /* usage message by request */
683         if (directory == NULL)
684                 directory = TZDIR;
685         if (yitcommand == NULL)
686                 yitcommand = "yearistype";
687
688         setboundaries();
689
690         if (optind < argc && leapsec != NULL) {
691                 infile(leapsec);
692                 adjleap();
693         }
694
695 #ifdef ICU
696         if ((icuFile = fopen(ICU_ZONE_FILE, "w")) == NULL) {
697                 const char *e = strerror(errno);
698                 (void) fprintf(stderr, _("%s: Can't open %s: %s\n"),
699                                                 progname, ICU_ZONE_FILE, e);
700                 (void) exit(EXIT_FAILURE);
701         }
702 #endif
703         for (i = optind; i < argc; ++i)
704                 infile(argv[i]);
705         if (errors)
706                 exit(EXIT_FAILURE);
707         associate();
708         for (i = 0; i < nzones; i = j) {
709                 /*
710                 ** Find the next non-continuation zone entry.
711                 */
712                 for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
713                         continue;
714                 outzone(&zones[i], j - i);
715         }
716         /*
717         ** Make links.
718         */
719         for (i = 0; i < nlinks; ++i) {
720                 eat(links[i].l_filename, links[i].l_linenum);
721                 dolink(links[i].l_from, links[i].l_to);
722 #ifdef ICU
723                 emit_icu_link(icuFile, links[i].l_from, links[i].l_to);
724 #endif
725                 if (noise)
726                         for (j = 0; j < nlinks; ++j)
727                                 if (strcmp(links[i].l_to,
728                                         links[j].l_from) == 0)
729                                                 warning(_("link to link"));
730         }
731         if (lcltime != NULL) {
732                 eat("command line", 1);
733                 dolink(lcltime, TZDEFAULT);
734         }
735         if (psxrules != NULL) {
736                 eat("command line", 1);
737                 dolink(psxrules, TZDEFRULES);
738         }
739 #ifdef ICU
740         for (i=0; i<finalRulesCount; ++i) {
741                 emit_icu_rule(icuFile, finalRules[i], i);
742         }
743 #endif /*ICU*/
744         return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
745 }
746
747 static void
748 dolink(fromfield, tofield)
749 const char * const      fromfield;
750 const char * const      tofield;
751 {
752         register char * fromname;
753         register char * toname;
754
755         if (fromfield[0] == '/')
756                 fromname = ecpyalloc(fromfield);
757         else {
758                 fromname = ecpyalloc(directory);
759                 fromname = ecatalloc(fromname, "/");
760                 fromname = ecatalloc(fromname, fromfield);
761         }
762         if (tofield[0] == '/')
763                 toname = ecpyalloc(tofield);
764         else {
765                 toname = ecpyalloc(directory);
766                 toname = ecatalloc(toname, "/");
767                 toname = ecatalloc(toname, tofield);
768         }
769         /*
770         ** We get to be careful here since
771         ** there's a fair chance of root running us.
772         */
773         if (!itsdir(toname))
774                 (void) remove(toname);
775         if (link(fromname, toname) != 0) {
776                 int     result;
777
778                 if (mkdirs(toname) != 0)
779                         exit(EXIT_FAILURE);
780
781                 result = link(fromname, toname);
782 #if HAVE_SYMLINK
783                 if (result != 0 &&
784                         access(fromname, F_OK) == 0 &&
785                         !itsdir(fromname)) {
786                                 const char *s = tofield;
787                                 register char * symlinkcontents = NULL;
788
789                                 while ((s = strchr(s+1, '/')) != NULL)
790                                         symlinkcontents =
791                                                 ecatalloc(symlinkcontents,
792                                                 "../");
793                                 symlinkcontents =
794                                         ecatalloc(symlinkcontents,
795                                         fromname);
796                                 result = symlink(symlinkcontents,
797                                         toname);
798                                 if (result == 0)
799 warning(_("hard link failed, symbolic link used"));
800                                 ifree(symlinkcontents);
801                 }
802 #endif /* HAVE_SYMLINK */
803                 if (result != 0) {
804                         const char *e = strerror(errno);
805
806                         (void) fprintf(stderr,
807                                 _("%s: Can't link from %s to %s: %s\n"),
808                                 progname, fromname, toname, e);
809 #ifndef ICU_LINKS
810                         exit(EXIT_FAILURE);
811 #endif
812                 }
813         }
814         ifree(fromname);
815         ifree(toname);
816 }
817
818 #define TIME_T_BITS_IN_FILE     64
819
820 static void
821 setboundaries(void)
822 {
823         register int    i;
824
825         min_time = -1;
826         for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
827                 min_time *= 2;
828         max_time = -(min_time + 1);
829 }
830
831 static int
832 itsdir(name)
833 const char * const      name;
834 {
835         register char * myname;
836         register int    accres;
837
838         myname = ecpyalloc(name);
839         myname = ecatalloc(myname, "/.");
840         accres = access(myname, F_OK);
841         ifree(myname);
842         return accres == 0;
843 }
844
845 /*
846 ** Associate sets of rules with zones.
847 */
848
849 /*
850 ** Sort by rule name.
851 */
852
853 static int
854 rcomp(cp1, cp2)
855 const void *    cp1;
856 const void *    cp2;
857 {
858         return strcmp(((const struct rule *) cp1)->r_name,
859                 ((const struct rule *) cp2)->r_name);
860 }
861
862 static void
863 associate(void)
864 {
865         register struct zone *  zp;
866         register struct rule *  rp;
867         register int            base, out;
868         register int            i, j;
869
870         if (nrules != 0) {
871                 (void) qsort((void *) rules, (size_t) nrules,
872                         (size_t) sizeof *rules, rcomp);
873                 for (i = 0; i < nrules - 1; ++i) {
874                         if (strcmp(rules[i].r_name,
875                                 rules[i + 1].r_name) != 0)
876                                         continue;
877                         if (strcmp(rules[i].r_filename,
878                                 rules[i + 1].r_filename) == 0)
879                                         continue;
880                         eat(rules[i].r_filename, rules[i].r_linenum);
881                         warning(_("same rule name in multiple files"));
882                         eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
883                         warning(_("same rule name in multiple files"));
884                         for (j = i + 2; j < nrules; ++j) {
885                                 if (strcmp(rules[i].r_name,
886                                         rules[j].r_name) != 0)
887                                                 break;
888                                 if (strcmp(rules[i].r_filename,
889                                         rules[j].r_filename) == 0)
890                                                 continue;
891                                 if (strcmp(rules[i + 1].r_filename,
892                                         rules[j].r_filename) == 0)
893                                                 continue;
894                                 break;
895                         }
896                         i = j - 1;
897                 }
898         }
899         for (i = 0; i < nzones; ++i) {
900                 zp = &zones[i];
901                 zp->z_rules = NULL;
902                 zp->z_nrules = 0;
903         }
904         for (base = 0; base < nrules; base = out) {
905                 rp = &rules[base];
906                 for (out = base + 1; out < nrules; ++out)
907                         if (strcmp(rp->r_name, rules[out].r_name) != 0)
908                                 break;
909                 for (i = 0; i < nzones; ++i) {
910                         zp = &zones[i];
911                         if (strcmp(zp->z_rule, rp->r_name) != 0)
912                                 continue;
913                         zp->z_rules = rp;
914                         zp->z_nrules = out - base;
915                 }
916         }
917         for (i = 0; i < nzones; ++i) {
918                 zp = &zones[i];
919                 if (zp->z_nrules == 0) {
920                         /*
921                         ** Maybe we have a local standard time offset.
922                         */
923                         eat(zp->z_filename, zp->z_linenum);
924                         zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"),
925                                 TRUE);
926                         /*
927                         ** Note, though, that if there's no rule,
928                         ** a '%s' in the format is a bad thing.
929                         */
930                         if (strchr(zp->z_format, '%') != 0)
931                                 error(_("%s in ruleless zone"));
932                 }
933         }
934         if (errors)
935                 exit(EXIT_FAILURE);
936 }
937
938 static void
939 infile(name)
940 const char *    name;
941 {
942         register FILE *                 fp;
943         register char **                fields;
944         register char *                 cp;
945         register const struct lookup *  lp;
946         register int                    nfields;
947         register int                    wantcont;
948         register int                    num;
949         char                            buf[BUFSIZ];
950
951         if (strcmp(name, "-") == 0) {
952                 name = _("standard input");
953                 fp = stdin;
954         } else if ((fp = fopen(name, "r")) == NULL) {
955                 const char *e = strerror(errno);
956
957                 (void) fprintf(stderr, _("%s: Can't open %s: %s\n"),
958                         progname, name, e);
959                 exit(EXIT_FAILURE);
960         }
961         wantcont = FALSE;
962         for (num = 1; ; ++num) {
963                 eat(name, num);
964                 if (fgets(buf, (int) sizeof buf, fp) != buf)
965                         break;
966                 cp = strchr(buf, '\n');
967                 if (cp == NULL) {
968                         error(_("line too long"));
969                         exit(EXIT_FAILURE);
970                 }
971                 *cp = '\0';
972                 fields = getfields(buf);
973                 nfields = 0;
974                 while (fields[nfields] != NULL) {
975                         static char     nada;
976
977                         if (strcmp(fields[nfields], "-") == 0)
978                                 fields[nfields] = &nada;
979                         ++nfields;
980                 }
981                 if (nfields == 0) {
982                         /* nothing to do */
983                 } else if (wantcont) {
984                         wantcont = inzcont(fields, nfields);
985                 } else {
986                         lp = byword(fields[0], line_codes);
987                         if (lp == NULL)
988                                 error(_("input line of unknown type"));
989                         else switch ((int) (lp->l_value)) {
990                                 case LC_RULE:
991                                         inrule(fields, nfields);
992                                         wantcont = FALSE;
993                                         break;
994                                 case LC_ZONE:
995                                         wantcont = inzone(fields, nfields);
996                                         break;
997                                 case LC_LINK:
998                                         inlink(fields, nfields);
999                                         wantcont = FALSE;
1000                                         break;
1001                                 case LC_LEAP:
1002                                         if (name != leapsec)
1003                                                 (void) fprintf(stderr,
1004 _("%s: Leap line in non leap seconds file %s\n"),
1005                                                         progname, name);
1006                                         else    inleap(fields, nfields);
1007                                         wantcont = FALSE;
1008                                         break;
1009                                 default:        /* "cannot happen" */
1010                                         (void) fprintf(stderr,
1011 _("%s: panic: Invalid l_value %d\n"),
1012                                                 progname, lp->l_value);
1013                                         exit(EXIT_FAILURE);
1014                         }
1015                 }
1016                 ifree((char *) fields);
1017         }
1018         if (ferror(fp)) {
1019                 (void) fprintf(stderr, _("%s: Error reading %s\n"),
1020                         progname, filename);
1021                 exit(EXIT_FAILURE);
1022         }
1023         if (fp != stdin && fclose(fp)) {
1024                 const char *e = strerror(errno);
1025
1026                 (void) fprintf(stderr, _("%s: Error closing %s: %s\n"),
1027                         progname, filename, e);
1028                 exit(EXIT_FAILURE);
1029         }
1030         if (wantcont)
1031                 error(_("expected continuation line not found"));
1032 }
1033
1034 /*
1035 ** Convert a string of one of the forms
1036 **      h       -h      hh:mm   -hh:mm  hh:mm:ss        -hh:mm:ss
1037 ** into a number of seconds.
1038 ** A null string maps to zero.
1039 ** Call error with errstring and return zero on errors.
1040 */
1041
1042 static long
1043 gethms(string, errstring, signable)
1044 const char *            string;
1045 const char * const      errstring;
1046 const int               signable;
1047 {
1048         long    hh;
1049         int     mm, ss, sign;
1050
1051         if (string == NULL || *string == '\0')
1052                 return 0;
1053         if (!signable)
1054                 sign = 1;
1055         else if (*string == '-') {
1056                 sign = -1;
1057                 ++string;
1058         } else  sign = 1;
1059         if (sscanf(string, scheck(string, "%ld"), &hh) == 1)
1060                 mm = ss = 0;
1061         else if (sscanf(string, scheck(string, "%ld:%d"), &hh, &mm) == 2)
1062                 ss = 0;
1063         else if (sscanf(string, scheck(string, "%ld:%d:%d"),
1064                 &hh, &mm, &ss) != 3) {
1065                         error(errstring);
1066                         return 0;
1067         }
1068         if (hh < 0 ||
1069                 mm < 0 || mm >= MINSPERHOUR ||
1070                 ss < 0 || ss > SECSPERMIN) {
1071                         error(errstring);
1072                         return 0;
1073         }
1074         if (LONG_MAX / SECSPERHOUR < hh) {
1075                 error(_("time overflow"));
1076                 return 0;
1077         }
1078         if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0)
1079                 warning(_("24:00 not handled by pre-1998 versions of zic"));
1080         if (noise && (hh > HOURSPERDAY ||
1081                 (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
1082 warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
1083         return oadd(eitol(sign) * hh * eitol(SECSPERHOUR),
1084                     eitol(sign) * (eitol(mm) * eitol(SECSPERMIN) + eitol(ss)));
1085 }
1086
1087 static void
1088 inrule(fields, nfields)
1089 register char ** const  fields;
1090 const int               nfields;
1091 {
1092         static struct rule      r;
1093
1094         if (nfields != RULE_FIELDS) {
1095                 error(_("wrong number of fields on Rule line"));
1096                 return;
1097         }
1098         if (*fields[RF_NAME] == '\0') {
1099                 error(_("nameless rule"));
1100                 return;
1101         }
1102         r.r_filename = filename;
1103         r.r_linenum = linenum;
1104         r.r_stdoff = gethms(fields[RF_STDOFF], _("invalid saved time"), TRUE);
1105         rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
1106                 fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
1107         r.r_name = ecpyalloc(fields[RF_NAME]);
1108         r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
1109         if (max_abbrvar_len < strlen(r.r_abbrvar))
1110                 max_abbrvar_len = strlen(r.r_abbrvar);
1111         rules = (struct rule *) (void *) erealloc((char *) rules,
1112                 (int) ((nrules + 1) * sizeof *rules));
1113         rules[nrules++] = r;
1114 }
1115
1116 static int
1117 inzone(fields, nfields)
1118 register char ** const  fields;
1119 const int               nfields;
1120 {
1121         register int    i;
1122         static char *   buf;
1123
1124         if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
1125                 error(_("wrong number of fields on Zone line"));
1126                 return FALSE;
1127         }
1128         if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
1129                 buf = erealloc(buf, (int) (132 + strlen(TZDEFAULT)));
1130                 (void) sprintf(buf,
1131 _("\"Zone %s\" line and -l option are mutually exclusive"),
1132                         TZDEFAULT);
1133                 error(buf);
1134                 return FALSE;
1135         }
1136         if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
1137                 buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES)));
1138                 (void) sprintf(buf,
1139 _("\"Zone %s\" line and -p option are mutually exclusive"),
1140                         TZDEFRULES);
1141                 error(buf);
1142                 return FALSE;
1143         }
1144         for (i = 0; i < nzones; ++i)
1145                 if (zones[i].z_name != NULL &&
1146                         strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
1147                                 buf = erealloc(buf, (int) (132 +
1148                                         strlen(fields[ZF_NAME]) +
1149                                         strlen(zones[i].z_filename)));
1150                                 (void) sprintf(buf,
1151 _("duplicate zone name %s (file \"%s\", line %d)"),
1152                                         fields[ZF_NAME],
1153                                         zones[i].z_filename,
1154                                         zones[i].z_linenum);
1155                                 error(buf);
1156                                 return FALSE;
1157                 }
1158         return inzsub(fields, nfields, FALSE);
1159 }
1160
1161 static int
1162 inzcont(fields, nfields)
1163 register char ** const  fields;
1164 const int               nfields;
1165 {
1166         if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
1167                 error(_("wrong number of fields on Zone continuation line"));
1168                 return FALSE;
1169         }
1170         return inzsub(fields, nfields, TRUE);
1171 }
1172
1173 static int
1174 inzsub(fields, nfields, iscont)
1175 register char ** const  fields;
1176 const int               nfields;
1177 const int               iscont;
1178 {
1179         register char *         cp;
1180         static struct zone      z;
1181         register int            i_gmtoff, i_rule, i_format;
1182         register int            i_untilyear, i_untilmonth;
1183         register int            i_untilday, i_untiltime;
1184         register int            hasuntil;
1185
1186         if (iscont) {
1187                 i_gmtoff = ZFC_GMTOFF;
1188                 i_rule = ZFC_RULE;
1189                 i_format = ZFC_FORMAT;
1190                 i_untilyear = ZFC_TILYEAR;
1191                 i_untilmonth = ZFC_TILMONTH;
1192                 i_untilday = ZFC_TILDAY;
1193                 i_untiltime = ZFC_TILTIME;
1194                 z.z_name = NULL;
1195         } else {
1196                 i_gmtoff = ZF_GMTOFF;
1197                 i_rule = ZF_RULE;
1198                 i_format = ZF_FORMAT;
1199                 i_untilyear = ZF_TILYEAR;
1200                 i_untilmonth = ZF_TILMONTH;
1201                 i_untilday = ZF_TILDAY;
1202                 i_untiltime = ZF_TILTIME;
1203                 z.z_name = ecpyalloc(fields[ZF_NAME]);
1204         }
1205         z.z_filename = filename;
1206         z.z_linenum = linenum;
1207         z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UTC offset"), TRUE);
1208         if ((cp = strchr(fields[i_format], '%')) != 0) {
1209                 if (*++cp != 's' || strchr(cp, '%') != 0) {
1210                         error(_("invalid abbreviation format"));
1211                         return FALSE;
1212                 }
1213         }
1214         z.z_rule = ecpyalloc(fields[i_rule]);
1215         z.z_format = ecpyalloc(fields[i_format]);
1216         if (max_format_len < strlen(z.z_format))
1217                 max_format_len = strlen(z.z_format);
1218         hasuntil = nfields > i_untilyear;
1219         if (hasuntil) {
1220                 z.z_untilrule.r_filename = filename;
1221                 z.z_untilrule.r_linenum = linenum;
1222                 rulesub(&z.z_untilrule,
1223                         fields[i_untilyear],
1224                         "only",
1225                         "",
1226                         (nfields > i_untilmonth) ?
1227                         fields[i_untilmonth] : "Jan",
1228                         (nfields > i_untilday) ? fields[i_untilday] : "1",
1229                         (nfields > i_untiltime) ? fields[i_untiltime] : "0");
1230                 z.z_untiltime = rpytime(&z.z_untilrule,
1231                         z.z_untilrule.r_loyear);
1232                 if (iscont && nzones > 0 &&
1233                         z.z_untiltime > min_time &&
1234                         z.z_untiltime < max_time &&
1235                         zones[nzones - 1].z_untiltime > min_time &&
1236                         zones[nzones - 1].z_untiltime < max_time &&
1237                         zones[nzones - 1].z_untiltime >= z.z_untiltime) {
1238                                 error(_(
1239 "Zone continuation line end time is not after end time of previous line"
1240                                         ));
1241                                 return FALSE;
1242                 }
1243         }
1244         zones = (struct zone *) (void *) erealloc((char *) zones,
1245                 (int) ((nzones + 1) * sizeof *zones));
1246         zones[nzones++] = z;
1247         /*
1248         ** If there was an UNTIL field on this line,
1249         ** there's more information about the zone on the next line.
1250         */
1251         return hasuntil;
1252 }
1253
1254 static void
1255 inleap(fields, nfields)
1256 register char ** const  fields;
1257 const int               nfields;
1258 {
1259         register const char *           cp;
1260         register const struct lookup *  lp;
1261         register int                    i, j;
1262         int                             year, month, day;
1263         long                            dayoff, tod;
1264         zic_t                           t;
1265
1266         if (nfields != LEAP_FIELDS) {
1267                 error(_("wrong number of fields on Leap line"));
1268                 return;
1269         }
1270         dayoff = 0;
1271         cp = fields[LP_YEAR];
1272         if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {
1273                 /*
1274                 ** Leapin' Lizards!
1275                 */
1276                 error(_("invalid leaping year"));
1277                 return;
1278         }
1279         if (!leapseen || leapmaxyear < year)
1280                 leapmaxyear = year;
1281         if (!leapseen || leapminyear > year)
1282                 leapminyear = year;
1283         leapseen = TRUE;
1284         j = EPOCH_YEAR;
1285         while (j != year) {
1286                 if (year > j) {
1287                         i = len_years[isleap(j)];
1288                         ++j;
1289                 } else {
1290                         --j;
1291                         i = -len_years[isleap(j)];
1292                 }
1293                 dayoff = oadd(dayoff, eitol(i));
1294         }
1295         if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
1296                 error(_("invalid month name"));
1297                 return;
1298         }
1299         month = lp->l_value;
1300         j = TM_JANUARY;
1301         while (j != month) {
1302                 i = len_months[isleap(year)][j];
1303                 dayoff = oadd(dayoff, eitol(i));
1304                 ++j;
1305         }
1306         cp = fields[LP_DAY];
1307         if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
1308                 day <= 0 || day > len_months[isleap(year)][month]) {
1309                         error(_("invalid day of month"));
1310                         return;
1311         }
1312         dayoff = oadd(dayoff, eitol(day - 1));
1313         if (dayoff < 0 && !TYPE_SIGNED(zic_t)) {
1314                 error(_("time before zero"));
1315                 return;
1316         }
1317         if (dayoff < min_time / SECSPERDAY) {
1318                 error(_("time too small"));
1319                 return;
1320         }
1321         if (dayoff > max_time / SECSPERDAY) {
1322                 error(_("time too large"));
1323                 return;
1324         }
1325         t = (zic_t) dayoff * SECSPERDAY;
1326         tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
1327         cp = fields[LP_CORR];
1328         {
1329                 register int    positive;
1330                 int             count;
1331
1332                 if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
1333                         positive = FALSE;
1334                         count = 1;
1335                 } else if (strcmp(cp, "--") == 0) {
1336                         positive = FALSE;
1337                         count = 2;
1338                 } else if (strcmp(cp, "+") == 0) {
1339                         positive = TRUE;
1340                         count = 1;
1341                 } else if (strcmp(cp, "++") == 0) {
1342                         positive = TRUE;
1343                         count = 2;
1344                 } else {
1345                         error(_("illegal CORRECTION field on Leap line"));
1346                         return;
1347                 }
1348                 if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
1349                         error(_(
1350                                 "illegal Rolling/Stationary field on Leap line"
1351                                 ));
1352                         return;
1353                 }
1354                 leapadd(tadd(t, tod), positive, lp->l_value, count);
1355         }
1356 }
1357
1358 static void
1359 inlink(fields, nfields)
1360 register char ** const  fields;
1361 const int               nfields;
1362 {
1363         struct link     l;
1364
1365         if (nfields != LINK_FIELDS) {
1366                 error(_("wrong number of fields on Link line"));
1367                 return;
1368         }
1369         if (*fields[LF_FROM] == '\0') {
1370                 error(_("blank FROM field on Link line"));
1371                 return;
1372         }
1373         if (*fields[LF_TO] == '\0') {
1374                 error(_("blank TO field on Link line"));
1375                 return;
1376         }
1377         l.l_filename = filename;
1378         l.l_linenum = linenum;
1379         l.l_from = ecpyalloc(fields[LF_FROM]);
1380         l.l_to = ecpyalloc(fields[LF_TO]);
1381         links = (struct link *) (void *) erealloc((char *) links,
1382                 (int) ((nlinks + 1) * sizeof *links));
1383         links[nlinks++] = l;
1384 }
1385
1386 static void
1387 rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
1388 register struct rule * const    rp;
1389 const char * const              loyearp;
1390 const char * const              hiyearp;
1391 const char * const              typep;
1392 const char * const              monthp;
1393 const char * const              dayp;
1394 const char * const              timep;
1395 {
1396         register const struct lookup *  lp;
1397         register const char *           cp;
1398         register char *                 dp;
1399         register char *                 ep;
1400
1401         if ((lp = byword(monthp, mon_names)) == NULL) {
1402                 error(_("invalid month name"));
1403                 return;
1404         }
1405         rp->r_month = lp->l_value;
1406         rp->r_todisstd = FALSE;
1407         rp->r_todisgmt = FALSE;
1408         dp = ecpyalloc(timep);
1409         if (*dp != '\0') {
1410                 ep = dp + strlen(dp) - 1;
1411                 switch (lowerit(*ep)) {
1412                         case 's':       /* Standard */
1413                                 rp->r_todisstd = TRUE;
1414                                 rp->r_todisgmt = FALSE;
1415                                 *ep = '\0';
1416                                 break;
1417                         case 'w':       /* Wall */
1418                                 rp->r_todisstd = FALSE;
1419                                 rp->r_todisgmt = FALSE;
1420                                 *ep = '\0';
1421                                 break;
1422                         case 'g':       /* Greenwich */
1423                         case 'u':       /* Universal */
1424                         case 'z':       /* Zulu */
1425                                 rp->r_todisstd = TRUE;
1426                                 rp->r_todisgmt = TRUE;
1427                                 *ep = '\0';
1428                                 break;
1429                 }
1430         }
1431         rp->r_tod = gethms(dp, _("invalid time of day"), FALSE);
1432         ifree(dp);
1433         /*
1434         ** Year work.
1435         */
1436         cp = loyearp;
1437         lp = byword(cp, begin_years);
1438         rp->r_lowasnum = lp == NULL;
1439         if (!rp->r_lowasnum) switch ((int) lp->l_value) {
1440                 case YR_MINIMUM:
1441                         rp->r_loyear = INT_MIN;
1442                         break;
1443                 case YR_MAXIMUM:
1444                         rp->r_loyear = INT_MAX;
1445                         break;
1446                 default:        /* "cannot happen" */
1447                         (void) fprintf(stderr,
1448                                 _("%s: panic: Invalid l_value %d\n"),
1449                                 progname, lp->l_value);
1450                         exit(EXIT_FAILURE);
1451         } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
1452                 error(_("invalid starting year"));
1453                 return;
1454         }
1455         cp = hiyearp;
1456         lp = byword(cp, end_years);
1457         rp->r_hiwasnum = lp == NULL;
1458         if (!rp->r_hiwasnum) switch ((int) lp->l_value) {
1459                 case YR_MINIMUM:
1460                         rp->r_hiyear = INT_MIN;
1461                         break;
1462                 case YR_MAXIMUM:
1463                         rp->r_hiyear = INT_MAX;
1464                         break;
1465                 case YR_ONLY:
1466                         rp->r_hiyear = rp->r_loyear;
1467                         break;
1468                 default:        /* "cannot happen" */
1469                         (void) fprintf(stderr,
1470                                 _("%s: panic: Invalid l_value %d\n"),
1471                                 progname, lp->l_value);
1472                         exit(EXIT_FAILURE);
1473         } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
1474                 error(_("invalid ending year"));
1475                 return;
1476         }
1477         if (rp->r_loyear > rp->r_hiyear) {
1478                 error(_("starting year greater than ending year"));
1479                 return;
1480         }
1481         if (*typep == '\0')
1482                 rp->r_yrtype = NULL;
1483         else {
1484                 if (rp->r_loyear == rp->r_hiyear) {
1485                         error(_("typed single year"));
1486                         return;
1487                 }
1488                 rp->r_yrtype = ecpyalloc(typep);
1489         }
1490         /*
1491         ** Day work.
1492         ** Accept things such as:
1493         **      1
1494         **      last-Sunday
1495         **      Sun<=20
1496         **      Sun>=7
1497         */
1498         dp = ecpyalloc(dayp);
1499         if ((lp = byword(dp, lasts)) != NULL) {
1500                 rp->r_dycode = DC_DOWLEQ;
1501                 rp->r_wday = lp->l_value;
1502                 rp->r_dayofmonth = len_months[1][rp->r_month];
1503         } else {
1504                 if ((ep = strchr(dp, '<')) != 0)
1505                         rp->r_dycode = DC_DOWLEQ;
1506                 else if ((ep = strchr(dp, '>')) != 0)
1507                         rp->r_dycode = DC_DOWGEQ;
1508                 else {
1509                         ep = dp;
1510                         rp->r_dycode = DC_DOM;
1511                 }
1512                 if (rp->r_dycode != DC_DOM) {
1513                         *ep++ = 0;
1514                         if (*ep++ != '=') {
1515                                 error(_("invalid day of month"));
1516                                 ifree(dp);
1517                                 return;
1518                         }
1519                         if ((lp = byword(dp, wday_names)) == NULL) {
1520                                 error(_("invalid weekday name"));
1521                                 ifree(dp);
1522                                 return;
1523                         }
1524                         rp->r_wday = lp->l_value;
1525                 }
1526                 if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 ||
1527                         rp->r_dayofmonth <= 0 ||
1528                         (rp->r_dayofmonth > len_months[1][rp->r_month])) {
1529                                 error(_("invalid day of month"));
1530                                 ifree(dp);
1531                                 return;
1532                 }
1533         }
1534         ifree(dp);
1535 }
1536
1537 static void
1538 convert(val, buf)
1539 const long      val;
1540 char * const    buf;
1541 {
1542         register int    i;
1543         register int    shift;
1544
1545         for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
1546                 buf[i] = val >> shift;
1547 }
1548
1549 static void
1550 convert64(val, buf)
1551 const zic_t     val;
1552 char * const    buf;
1553 {
1554         register int    i;
1555         register int    shift;
1556
1557         for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
1558                 buf[i] = val >> shift;
1559 }
1560
1561 static void
1562 puttzcode(val, fp)
1563 const long      val;
1564 FILE * const    fp;
1565 {
1566         char    buf[4];
1567
1568         convert(val, buf);
1569         (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
1570 }
1571
1572 static void
1573 puttzcode64(val, fp)
1574 const zic_t     val;
1575 FILE * const    fp;
1576 {
1577         char    buf[8];
1578
1579         convert64(val, buf);
1580         (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
1581 }
1582
1583 static int
1584 atcomp(avp, bvp)
1585 const void *    avp;
1586 const void *    bvp;
1587 {
1588         const zic_t     a = ((const struct attype *) avp)->at;
1589         const zic_t     b = ((const struct attype *) bvp)->at;
1590
1591         return (a < b) ? -1 : (a > b);
1592 }
1593
1594 static int
1595 is32(x)
1596 const zic_t     x;
1597 {
1598         return INT32_MIN <= x && x <= INT32_MAX;
1599 }
1600
1601 static void
1602 writezone(name, string)
1603 const char * const      name;
1604 const char * const      string;
1605 {
1606         register FILE *                 fp;
1607         register int                    i, j;
1608         register int                    leapcnt32, leapi32;
1609         register int                    timecnt32, timei32;
1610         register int                    pass;
1611         static char *                   fullname;
1612         static const struct tzhead      tzh0;
1613         static struct tzhead            tzh;
1614         zic_t                           ats[TZ_MAX_TIMES];
1615         unsigned char                   types[TZ_MAX_TIMES];
1616
1617         /*
1618         ** Sort.
1619         */
1620         if (timecnt > 1)
1621                 (void) qsort((void *) attypes, (size_t) timecnt,
1622                         (size_t) sizeof *attypes, atcomp);
1623         /*
1624         ** Optimize.
1625         */
1626         {
1627                 int     fromi;
1628                 int     toi;
1629
1630                 toi = 0;
1631                 fromi = 0;
1632                 while (fromi < timecnt && attypes[fromi].at < min_time)
1633                         ++fromi;
1634                 if (isdsts[0] == 0)
1635                         while (fromi < timecnt && attypes[fromi].type == 0)
1636                                 ++fromi;        /* handled by default rule */
1637                 for ( ; fromi < timecnt; ++fromi) {
1638                         if (toi != 0 && ((attypes[fromi].at +
1639                                 gmtoffs[attypes[toi - 1].type]) <=
1640                                 (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
1641                                 : attypes[toi - 2].type]))) {
1642                                         attypes[toi - 1].type =
1643                                                 attypes[fromi].type;
1644                                         continue;
1645                         }
1646                         if (toi == 0 ||
1647                                 attypes[toi - 1].type != attypes[fromi].type)
1648                                         attypes[toi++] = attypes[fromi];
1649                 }
1650                 timecnt = toi;
1651         }
1652         /*
1653         ** Transfer.
1654         */
1655         for (i = 0; i < timecnt; ++i) {
1656                 ats[i] = attypes[i].at;
1657                 types[i] = attypes[i].type;
1658         }
1659         /*
1660         ** Correct for leap seconds.
1661         */
1662         for (i = 0; i < timecnt; ++i) {
1663                 j = leapcnt;
1664                 while (--j >= 0)
1665                         if (ats[i] > trans[j] - corr[j]) {
1666                                 ats[i] = tadd(ats[i], corr[j]);
1667                                 break;
1668                         }
1669         }
1670         /*
1671         ** Figure out 32-bit-limited starts and counts.
1672         */
1673         timecnt32 = timecnt;
1674         timei32 = 0;
1675         leapcnt32 = leapcnt;
1676         leapi32 = 0;
1677         while (timecnt32 > 0 && !is32(ats[timecnt32 - 1]))
1678                 --timecnt32;
1679         while (timecnt32 > 0 && !is32(ats[timei32])) {
1680                 --timecnt32;
1681                 ++timei32;
1682         }
1683         while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1]))
1684                 --leapcnt32;
1685         while (leapcnt32 > 0 && !is32(trans[leapi32])) {
1686                 --leapcnt32;
1687                 ++leapi32;
1688         }
1689         fullname = erealloc(fullname,
1690                 (int) (strlen(directory) + 1 + strlen(name) + 1));
1691         (void) sprintf(fullname, "%s/%s", directory, name);
1692         /*
1693         ** Remove old file, if any, to snap links.
1694         */
1695         if (!itsdir(fullname) && remove(fullname) != 0 && errno != ENOENT) {
1696                 const char *e = strerror(errno);
1697
1698                 (void) fprintf(stderr, _("%s: Can't remove %s: %s\n"),
1699                         progname, fullname, e);
1700                 exit(EXIT_FAILURE);
1701         }
1702         if ((fp = fopen(fullname, "wb")) == NULL) {
1703                 if (mkdirs(fullname) != 0)
1704                         exit(EXIT_FAILURE);
1705                 if ((fp = fopen(fullname, "wb")) == NULL) {
1706                         const char *e = strerror(errno);
1707
1708                         (void) fprintf(stderr, _("%s: Can't create %s: %s\n"),
1709                                 progname, fullname, e);
1710                         exit(EXIT_FAILURE);
1711                 }
1712         }
1713         for (pass = 1; pass <= 2; ++pass) {
1714                 register int    thistimei, thistimecnt;
1715                 register int    thisleapi, thisleapcnt;
1716                 register int    thistimelim, thisleaplim;
1717                 int             writetype[TZ_MAX_TIMES];
1718                 int             typemap[TZ_MAX_TYPES];
1719                 register int    thistypecnt;
1720                 char            thischars[TZ_MAX_CHARS];
1721                 char            thischarcnt;
1722                 int             indmap[TZ_MAX_CHARS];
1723
1724                 if (pass == 1) {
1725                         thistimei = timei32;
1726                         thistimecnt = timecnt32;
1727                         thisleapi = leapi32;
1728                         thisleapcnt = leapcnt32;
1729                 } else {
1730                         thistimei = 0;
1731                         thistimecnt = timecnt;
1732                         thisleapi = 0;
1733                         thisleapcnt = leapcnt;
1734                 }
1735                 thistimelim = thistimei + thistimecnt;
1736                 thisleaplim = thisleapi + thisleapcnt;
1737                 for (i = 0; i < typecnt; ++i)
1738                         writetype[i] = thistimecnt == timecnt;
1739                 if (thistimecnt == 0) {
1740                         /*
1741                         ** No transition times fall in the current
1742                         ** (32- or 64-bit) window.
1743                         */
1744                         if (typecnt != 0)
1745                                 writetype[typecnt - 1] = TRUE;
1746                 } else {
1747                         for (i = thistimei - 1; i < thistimelim; ++i)
1748                                 if (i >= 0)
1749                                         writetype[types[i]] = TRUE;
1750                         /*
1751                         ** For America/Godthab and Antarctica/Palmer
1752                         */
1753                         if (thistimei == 0)
1754                                 writetype[0] = TRUE;
1755                 }
1756                 thistypecnt = 0;
1757                 for (i = 0; i < typecnt; ++i)
1758                         typemap[i] = writetype[i] ?  thistypecnt++ : -1;
1759                 for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
1760                         indmap[i] = -1;
1761                 thischarcnt = 0;
1762                 for (i = 0; i < typecnt; ++i) {
1763                         register char * thisabbr;
1764
1765                         if (!writetype[i])
1766                                 continue;
1767                         if (indmap[abbrinds[i]] >= 0)
1768                                 continue;
1769                         thisabbr = &chars[abbrinds[i]];
1770                         for (j = 0; j < thischarcnt; ++j)
1771                                 if (strcmp(&thischars[j], thisabbr) == 0)
1772                                         break;
1773                         if (j == thischarcnt) {
1774                                 (void) strcpy(&thischars[(int) thischarcnt],
1775                                         thisabbr);
1776                                 thischarcnt += strlen(thisabbr) + 1;
1777                         }
1778                         indmap[abbrinds[i]] = j;
1779                 }
1780 #define DO(field)       (void) fwrite((void *) tzh.field, \
1781                                 (size_t) sizeof tzh.field, (size_t) 1, fp)
1782                 tzh = tzh0;
1783 #ifdef ICU
1784                 * (ICUZoneinfoVersion*) &tzh.tzh_reserved = TZ_ICU_VERSION;
1785                 (void) strncpy(tzh.tzh_magic, TZ_ICU_MAGIC, sizeof tzh.tzh_magic);
1786 #else
1787                 (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
1788 #endif
1789                 tzh.tzh_version[0] = ZIC_VERSION;
1790                 convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt);
1791                 convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt);
1792                 convert(eitol(thisleapcnt), tzh.tzh_leapcnt);
1793                 convert(eitol(thistimecnt), tzh.tzh_timecnt);
1794                 convert(eitol(thistypecnt), tzh.tzh_typecnt);
1795                 convert(eitol(thischarcnt), tzh.tzh_charcnt);
1796                 DO(tzh_magic);
1797                 DO(tzh_version);
1798                 DO(tzh_reserved);
1799                 DO(tzh_ttisgmtcnt);
1800                 DO(tzh_ttisstdcnt);
1801                 DO(tzh_leapcnt);
1802                 DO(tzh_timecnt);
1803                 DO(tzh_typecnt);
1804                 DO(tzh_charcnt);
1805 #undef DO
1806                 for (i = thistimei; i < thistimelim; ++i)
1807                         if (pass == 1)
1808                                 puttzcode((long) ats[i], fp);
1809                         else    puttzcode64(ats[i], fp);
1810                 for (i = thistimei; i < thistimelim; ++i) {
1811                         unsigned char   uc;
1812
1813                         uc = typemap[types[i]];
1814                         (void) fwrite((void *) &uc,
1815                                 (size_t) sizeof uc,
1816                                 (size_t) 1,
1817                                 fp);
1818                 }
1819                 for (i = 0; i < typecnt; ++i)
1820                         if (writetype[i]) {
1821 #ifdef ICU
1822                                 puttzcode((long) rawoffs[i], fp);
1823                                 puttzcode((long) dstoffs[i], fp);
1824 #else
1825                                 puttzcode(gmtoffs[i], fp);
1826 #endif
1827                                 (void) putc(isdsts[i], fp);
1828                                 (void) putc((unsigned char) indmap[abbrinds[i]], fp);
1829                         }
1830                 if (thischarcnt != 0)
1831                         (void) fwrite((void *) thischars,
1832                                 (size_t) sizeof thischars[0],
1833                                 (size_t) thischarcnt, fp);
1834                 for (i = thisleapi; i < thisleaplim; ++i) {
1835                         register zic_t  todo;
1836
1837                         if (roll[i]) {
1838                                 if (timecnt == 0 || trans[i] < ats[0]) {
1839                                         j = 0;
1840                                         while (isdsts[j])
1841                                                 if (++j >= typecnt) {
1842                                                         j = 0;
1843                                                         break;
1844                                                 }
1845                                 } else {
1846                                         j = 1;
1847                                         while (j < timecnt &&
1848                                                 trans[i] >= ats[j])
1849                                                         ++j;
1850                                         j = types[j - 1];
1851                                 }
1852                                 todo = tadd(trans[i], -gmtoffs[j]);
1853                         } else  todo = trans[i];
1854                         if (pass == 1)
1855                                 puttzcode((long) todo, fp);
1856                         else    puttzcode64(todo, fp);
1857                         puttzcode(corr[i], fp);
1858                 }
1859                 for (i = 0; i < typecnt; ++i)
1860                         if (writetype[i])
1861                                 (void) putc(ttisstds[i], fp);
1862                 for (i = 0; i < typecnt; ++i)
1863                         if (writetype[i])
1864                                 (void) putc(ttisgmts[i], fp);
1865         }
1866         (void) fprintf(fp, "\n%s\n", string);
1867         if (ferror(fp) || fclose(fp)) {
1868                 (void) fprintf(stderr, _("%s: Error writing %s\n"),
1869                         progname, fullname);
1870                 exit(EXIT_FAILURE);
1871         }
1872 }
1873
1874 static void
1875 doabbr(abbr, format, letters, isdst, doquotes)
1876 char * const            abbr;
1877 const char * const      format;
1878 const char * const      letters;
1879 const int               isdst;
1880 const int               doquotes;
1881 {
1882         register char * cp;
1883         register char * slashp;
1884         register int    len;
1885
1886         slashp = strchr(format, '/');
1887         if (slashp == NULL) {
1888                 if (letters == NULL)
1889                         (void) strcpy(abbr, format);
1890                 else    (void) sprintf(abbr, format, letters);
1891         } else if (isdst) {
1892                 (void) strcpy(abbr, slashp + 1);
1893         } else {
1894                 if (slashp > format)
1895                         (void) strncpy(abbr, format,
1896                                 (unsigned) (slashp - format));
1897                 abbr[slashp - format] = '\0';
1898         }
1899         if (!doquotes)
1900                 return;
1901         for (cp = abbr; *cp != '\0'; ++cp)
1902                 if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", *cp) == NULL &&
1903                         strchr("abcdefghijklmnopqrstuvwxyz", *cp) == NULL)
1904                                 break;
1905         len = strlen(abbr);
1906         if (len > 0 && *cp == '\0')
1907                 return;
1908         abbr[len + 2] = '\0';
1909         abbr[len + 1] = '>';
1910         for ( ; len > 0; --len)
1911                 abbr[len] = abbr[len - 1];
1912         abbr[0] = '<';
1913 }
1914
1915 static void
1916 updateminmax(x)
1917 const int       x;
1918 {
1919         if (min_year > x)
1920                 min_year = x;
1921         if (max_year < x)
1922                 max_year = x;
1923 }
1924
1925 static int
1926 stringoffset(result, offset)
1927 char *  result;
1928 long    offset;
1929 {
1930         register int    hours;
1931         register int    minutes;
1932         register int    seconds;
1933
1934         result[0] = '\0';
1935         if (offset < 0) {
1936                 (void) strcpy(result, "-");
1937                 offset = -offset;
1938         }
1939         seconds = offset % SECSPERMIN;
1940         offset /= SECSPERMIN;
1941         minutes = offset % MINSPERHOUR;
1942         offset /= MINSPERHOUR;
1943         hours = offset;
1944         if (hours >= HOURSPERDAY) {
1945                 result[0] = '\0';
1946                 return -1;
1947         }
1948         (void) sprintf(end(result), "%d", hours);
1949         if (minutes != 0 || seconds != 0) {
1950                 (void) sprintf(end(result), ":%02d", minutes);
1951                 if (seconds != 0)
1952                         (void) sprintf(end(result), ":%02d", seconds);
1953         }
1954         return 0;
1955 }
1956
1957 static int
1958 stringrule(result, rp, dstoff, gmtoff)
1959 char *                          result;
1960 const struct rule * const       rp;
1961 const long                      dstoff;
1962 const long                      gmtoff;
1963 {
1964         register long   tod;
1965
1966         result = end(result);
1967         if (rp->r_dycode == DC_DOM) {
1968                 register int    month, total;
1969
1970                 if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
1971                         return -1;
1972                 total = 0;
1973                 for (month = 0; month < rp->r_month; ++month)
1974                         total += len_months[0][month];
1975                 (void) sprintf(result, "J%d", total + rp->r_dayofmonth);
1976         } else {
1977                 register int    week;
1978
1979                 if (rp->r_dycode == DC_DOWGEQ) {
1980                         week = 1 + rp->r_dayofmonth / DAYSPERWEEK;
1981                         if ((week - 1) * DAYSPERWEEK + 1 != rp->r_dayofmonth)
1982                                 return -1;
1983                 } else if (rp->r_dycode == DC_DOWLEQ) {
1984                         if (rp->r_dayofmonth == len_months[1][rp->r_month])
1985                                 week = 5;
1986                         else {
1987                                 week = 1 + rp->r_dayofmonth / DAYSPERWEEK;
1988                                 if (week * DAYSPERWEEK - 1 != rp->r_dayofmonth)
1989                                         return -1;
1990                         }
1991                 } else  return -1;      /* "cannot happen" */
1992                 (void) sprintf(result, "M%d.%d.%d",
1993                         rp->r_month + 1, week, rp->r_wday);
1994         }
1995         tod = rp->r_tod;
1996         if (rp->r_todisgmt)
1997                 tod += gmtoff;
1998         if (rp->r_todisstd && rp->r_stdoff == 0)
1999                 tod += dstoff;
2000         if (tod < 0) {
2001                 result[0] = '\0';
2002                 return -1;
2003         }
2004         if (tod != 2 * SECSPERMIN * MINSPERHOUR) {
2005                 (void) strcat(result, "/");
2006                 if (stringoffset(end(result), tod) != 0)
2007                         return -1;
2008         }
2009         return 0;
2010 }
2011
2012 static void
2013 stringzone(result, zpfirst, zonecount)
2014 char *                          result;
2015 const struct zone * const       zpfirst;
2016 const int                       zonecount;
2017 {
2018         register const struct zone *    zp;
2019         register struct rule *          rp;
2020         register struct rule *          stdrp;
2021         register struct rule *          dstrp;
2022         register int                    i;
2023         register const char *           abbrvar;
2024
2025         result[0] = '\0';
2026         zp = zpfirst + zonecount - 1;
2027         stdrp = dstrp = NULL;
2028         for (i = 0; i < zp->z_nrules; ++i) {
2029                 rp = &zp->z_rules[i];
2030                 if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX)
2031                         continue;
2032                 if (rp->r_yrtype != NULL)
2033                         continue;
2034                 if (rp->r_stdoff == 0) {
2035                         if (stdrp == NULL)
2036                                 stdrp = rp;
2037                         else    return;
2038                 } else {
2039                         if (dstrp == NULL)
2040                                 dstrp = rp;
2041                         else    return;
2042                 }
2043         }
2044         if (stdrp == NULL && dstrp == NULL) {
2045                 /*
2046                 ** There are no rules running through "max".
2047                 ** Let's find the latest rule.
2048                 */
2049                 for (i = 0; i < zp->z_nrules; ++i) {
2050                         rp = &zp->z_rules[i];
2051                         if (stdrp == NULL || rp->r_hiyear > stdrp->r_hiyear ||
2052                                 (rp->r_hiyear == stdrp->r_hiyear &&
2053                                 rp->r_month > stdrp->r_month))
2054                                         stdrp = rp;
2055                 }
2056                 if (stdrp != NULL && stdrp->r_stdoff != 0)
2057                         return; /* We end up in DST (a POSIX no-no). */
2058                 /*
2059                 ** Horrid special case: if year is 2037,
2060                 ** presume this is a zone handled on a year-by-year basis;
2061                 ** do not try to apply a rule to the zone.
2062                 */
2063                 if (stdrp != NULL && stdrp->r_hiyear == 2037)
2064                         return;
2065         }
2066         if (stdrp == NULL && zp->z_nrules != 0)
2067                 return;
2068         abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
2069         doabbr(result, zp->z_format, abbrvar, FALSE, TRUE);
2070         if (stringoffset(end(result), -zp->z_gmtoff) != 0) {
2071                 result[0] = '\0';
2072                 return;
2073         }
2074         if (dstrp == NULL)
2075                 return;
2076         doabbr(end(result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE);
2077         if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR)
2078                 if (stringoffset(end(result),
2079                         -(zp->z_gmtoff + dstrp->r_stdoff)) != 0) {
2080                                 result[0] = '\0';
2081                                 return;
2082                 }
2083         (void) strcat(result, ",");
2084         if (stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
2085                 result[0] = '\0';
2086                 return;
2087         }
2088         (void) strcat(result, ",");
2089         if (stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
2090                 result[0] = '\0';
2091                 return;
2092         }
2093 }
2094
2095 static void
2096 outzone(zpfirst, zonecount)
2097 const struct zone * const       zpfirst;
2098 const int                       zonecount;
2099 {
2100         register const struct zone *    zp;
2101         register struct rule *          rp;
2102         register int                    i, j;
2103         register int                    usestart, useuntil;
2104         register zic_t                  starttime, untiltime;
2105         register long                   gmtoff;
2106         register long                   stdoff;
2107         register int                    year;
2108         register long                   startoff;
2109         register int                    startttisstd;
2110         register int                    startttisgmt;
2111         register int                    type;
2112         register char *                 startbuf;
2113         register char *                 ab;
2114         register char *                 envvar;
2115         register int                    max_abbr_len;
2116         register int                    max_envvar_len;
2117 #ifdef ICU
2118         int                                             finalRuleYear, finalRuleIndex;
2119         const struct rule*              finalRule1;
2120         const struct rule*              finalRule2;
2121 #endif
2122
2123         max_abbr_len = 2 + max_format_len + max_abbrvar_len;
2124         max_envvar_len = 2 * max_abbr_len + 5 * 9;
2125         startbuf = emalloc(max_abbr_len + 1);
2126         ab = emalloc(max_abbr_len + 1);
2127         envvar = emalloc(max_envvar_len + 1);
2128         INITIALIZE(untiltime);
2129         INITIALIZE(starttime);
2130         /*
2131         ** Now. . .finally. . .generate some useful data!
2132         */
2133         timecnt = 0;
2134         typecnt = 0;
2135         charcnt = 0;
2136         /*
2137         ** Thanks to Earl Chew
2138         ** for noting the need to unconditionally initialize startttisstd.
2139         */
2140         startttisstd = FALSE;
2141         startttisgmt = FALSE;
2142         min_year = max_year = EPOCH_YEAR;
2143         if (leapseen) {
2144                 updateminmax(leapminyear);
2145                 updateminmax(leapmaxyear);
2146         }
2147         for (i = 0; i < zonecount; ++i) {
2148                 zp = &zpfirst[i];
2149                 if (i < zonecount - 1)
2150                         updateminmax(zp->z_untilrule.r_loyear);
2151                 for (j = 0; j < zp->z_nrules; ++j) {
2152                         rp = &zp->z_rules[j];
2153                         if (rp->r_lowasnum)
2154                                 updateminmax(rp->r_loyear);
2155                         if (rp->r_hiwasnum)
2156                                 updateminmax(rp->r_hiyear);
2157                 }
2158         }
2159         /*
2160         ** Generate lots of data if a rule can't cover all future times.
2161         */
2162         stringzone(envvar, zpfirst, zonecount);
2163         if (noise && envvar[0] == '\0') {
2164                 register char * wp;
2165
2166 wp = ecpyalloc(_("no POSIX environment variable for zone"));
2167                 wp = ecatalloc(wp, " ");
2168                 wp = ecatalloc(wp, zpfirst->z_name);
2169                 warning(wp);
2170                 ifree(wp);
2171         }
2172         if (envvar[0] == '\0') {
2173                 if (min_year >= INT_MIN + YEARSPERREPEAT)
2174                         min_year -= YEARSPERREPEAT;
2175                 else    min_year = INT_MIN;
2176                 if (max_year <= INT_MAX - YEARSPERREPEAT)
2177                         max_year += YEARSPERREPEAT;
2178                 else    max_year = INT_MAX;
2179         }
2180         /*
2181         ** For the benefit of older systems,
2182         ** generate data from 1900 through 2037.
2183         */
2184         if (min_year > 1900)
2185                 min_year = 1900;
2186         if (max_year < 2037)
2187                 max_year = 2037;
2188         for (i = 0; i < zonecount; ++i) {
2189                 /*
2190                 ** A guess that may well be corrected later.
2191                 */
2192                 stdoff = 0;
2193                 zp = &zpfirst[i];
2194                 usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
2195                 useuntil = i < (zonecount - 1);
2196                 if (useuntil && zp->z_untiltime <= min_time)
2197                         continue;
2198                 gmtoff = zp->z_gmtoff;
2199                 eat(zp->z_filename, zp->z_linenum);
2200                 *startbuf = '\0';
2201                 startoff = zp->z_gmtoff;
2202 #ifdef ICU
2203                 finalRuleYear = finalRuleIndex = -1;
2204                 finalRule1 = finalRule2 = NULL;
2205                 if (i == (zonecount - 1)) { /* !useuntil */
2206                         /* Look for exactly 2 rules that end at 'max' and
2207                          * note them. Determine max(r_loyear) for the 2 of
2208                          * them. */
2209                         for (j=0; j<zp->z_nrules; ++j) {
2210                                 rp = &zp->z_rules[j];
2211                                 if (rp->r_hiyear == INT_MAX) {
2212                                         if (rp->r_loyear > finalRuleYear) {
2213                                                 finalRuleYear = rp->r_loyear;
2214                                         }
2215                                         if (finalRule1 == NULL) {
2216                                                 finalRule1 = rp;
2217                                         } else if (finalRule2 == NULL) {
2218                                                 finalRule2 = rp;
2219                                         } else {
2220                                                 error("more than two max rules found (ICU)");
2221                                                 exit(EXIT_FAILURE);
2222                                         }
2223                                 } else if (rp->r_hiyear >= finalRuleYear) {
2224                                         /* There might be an overriding non-max rule
2225                                          * to be applied to a specific year after one of
2226                                          * max rule's start year. For example,
2227                                          *
2228                                          * Rule Foo 2010 max ...
2229                                          * Rule Foo 2015 only ...
2230                                          *
2231                                          * In this case, we need to change the start year of
2232                                          * the final (max) rules to the next year. */
2233                                         finalRuleYear = rp->r_hiyear + 1;
2234
2235                                         /* When above adjustment is done, max_year might need
2236                                          * to be adjusted, so the final rule will be properly
2237                                          * evaluated and emitted by the later code block.
2238                                          *
2239                                          * Note: This may push the start year of the final
2240                                          * rules ahead by 1 year unnecessarily. For example,
2241                                          * If there are two rules, non-max rule and max rule
2242                                          * starting in the same year, such as
2243                                          *
2244                                          * Rule Foo 2010 only ....
2245                                          * Rule Foo 2010 max ....
2246                                          *
2247                                          * In this case, the final (max) rule actually starts
2248                                          * in 2010, instead of 2010. We could make this tool
2249                                          * more intelligent to detect such situation. But pushing
2250                                          * final rule start year to 1 year ahead (in the worst case)
2251                                          * will just populate a few extra transitions, and it still
2252                                          * works fine. So for now, we're not trying to put additional
2253                                          * logic to optimize the case.
2254                                          */
2255                                         if (max_year < finalRuleYear) {
2256                                                 max_year = finalRuleYear;
2257                                         }
2258                                 }
2259                         }
2260                         if (finalRule1 != NULL) {
2261                                 if (finalRule2 == NULL) {
2262                                         warning("only one max rule found (ICU)");
2263                                         finalRuleYear = finalRuleIndex = -1;
2264                                         finalRule1 = NULL;
2265                                 } else {
2266                                         if (finalRule1->r_stdoff == finalRule2->r_stdoff) {
2267                                                 /* America/Resolute in 2009a uses a pair of rules
2268                                                  * which does not change the offset.  ICU ignores
2269                                                  * such rules without actual time transitions. */
2270                                                 finalRuleYear = finalRuleIndex = -1;
2271                                                 finalRule1 = finalRule2 = NULL; 
2272                                         } else {
2273                                                 /* Swap if necessary so finalRule1 occurs before
2274                                                  * finalRule2 */
2275                                                 if (finalRule1->r_month > finalRule2->r_month) {
2276                                                         const struct rule* t = finalRule1;
2277                                                         finalRule1 = finalRule2;
2278                                                         finalRule2 = t;
2279                                                 }
2280                                                 /* Add final rule to our list */
2281                                                 finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2);
2282                                         }
2283                                 }
2284                         }
2285                 }
2286 #endif
2287
2288                 if (zp->z_nrules == 0) {
2289                         stdoff = zp->z_stdoff;
2290                         doabbr(startbuf, zp->z_format,
2291                                 (char *) NULL, stdoff != 0, FALSE);
2292                         type = addtype(oadd(zp->z_gmtoff, stdoff),
2293 #ifdef ICU
2294                                 zp->z_gmtoff, stdoff,
2295 #endif
2296                                 startbuf, stdoff != 0, startttisstd,
2297                                 startttisgmt);
2298                         if (usestart) {
2299                                 addtt(starttime, type);
2300                                 usestart = FALSE;
2301                         } else if (stdoff != 0)
2302                                 addtt(min_time, type);
2303                 } else for (year = min_year; year <= max_year; ++year) {
2304                         if (useuntil && year > zp->z_untilrule.r_hiyear)
2305                                 break;
2306                         /*
2307                         ** Mark which rules to do in the current year.
2308                         ** For those to do, calculate rpytime(rp, year);
2309                         */
2310                         for (j = 0; j < zp->z_nrules; ++j) {
2311                                 rp = &zp->z_rules[j];
2312                                 eats(zp->z_filename, zp->z_linenum,
2313                                         rp->r_filename, rp->r_linenum);
2314                                 rp->r_todo = year >= rp->r_loyear &&
2315                                                 year <= rp->r_hiyear &&
2316                                                 yearistype(year, rp->r_yrtype);
2317                                 if (rp->r_todo)
2318                                         rp->r_temp = rpytime(rp, year);
2319                         }
2320                         for ( ; ; ) {
2321                                 register int    k;
2322                                 register zic_t  jtime, ktime;
2323                                 register long   offset;
2324
2325                                 INITIALIZE(ktime);
2326                                 if (useuntil) {
2327                                         /*
2328                                         ** Turn untiltime into UTC
2329                                         ** assuming the current gmtoff and
2330                                         ** stdoff values.
2331                                         */
2332                                         untiltime = zp->z_untiltime;
2333                                         if (!zp->z_untilrule.r_todisgmt)
2334                                                 untiltime = tadd(untiltime,
2335                                                         -gmtoff);
2336                                         if (!zp->z_untilrule.r_todisstd)
2337                                                 untiltime = tadd(untiltime,
2338                                                         -stdoff);
2339                                 }
2340                                 /*
2341                                 ** Find the rule (of those to do, if any)
2342                                 ** that takes effect earliest in the year.
2343                                 */
2344                                 k = -1;
2345                                 for (j = 0; j < zp->z_nrules; ++j) {
2346                                         rp = &zp->z_rules[j];
2347                                         if (!rp->r_todo)
2348                                                 continue;
2349                                         eats(zp->z_filename, zp->z_linenum,
2350                                                 rp->r_filename, rp->r_linenum);
2351                                         offset = rp->r_todisgmt ? 0 : gmtoff;
2352                                         if (!rp->r_todisstd)
2353                                                 offset = oadd(offset, stdoff);
2354                                         jtime = rp->r_temp;
2355                                         if (jtime == min_time ||
2356                                                 jtime == max_time)
2357                                                         continue;
2358                                         jtime = tadd(jtime, -offset);
2359                                         if (k < 0 || jtime < ktime) {
2360                                                 k = j;
2361                                                 ktime = jtime;
2362                                         }
2363                                 }
2364                                 if (k < 0)
2365                                         break;  /* go on to next year */
2366                                 rp = &zp->z_rules[k];
2367                                 rp->r_todo = FALSE;
2368                                 if (useuntil && ktime >= untiltime)
2369                                         break;
2370                                 stdoff = rp->r_stdoff;
2371                                 if (usestart && ktime == starttime)
2372                                         usestart = FALSE;
2373                                 if (usestart) {
2374                                         if (ktime < starttime) {
2375                                                 startoff = oadd(zp->z_gmtoff,
2376                                                         stdoff);
2377                                                 doabbr(startbuf, zp->z_format,
2378                                                         rp->r_abbrvar,
2379                                                         rp->r_stdoff != 0,
2380                                                         FALSE);
2381                                                 continue;
2382                                         }
2383                                         if (*startbuf == '\0' &&
2384                                                 startoff == oadd(zp->z_gmtoff,
2385                                                 stdoff)) {
2386                                                         doabbr(startbuf,
2387                                                                 zp->z_format,
2388                                                                 rp->r_abbrvar,
2389                                                                 rp->r_stdoff !=
2390                                                                 0,
2391                                                                 FALSE);
2392                                         }
2393                                 }
2394 #ifdef ICU
2395                                 if (year >= finalRuleYear && rp == finalRule1) {
2396                                         /* We want to shift final year 1 year after
2397                                          * the actual final rule takes effect (year + 1),
2398                                          * because the previous type is valid until the first
2399                                          * transition defined by the final rule.  Otherwise
2400                                          * we may see unexpected offset shift at the
2401                                          * begining of the year when the final rule takes
2402                                          * effect.
2403                                          *
2404                                          * Note: This may results some 64bit second transitions
2405                                          * at the very end (year 2038). ICU 4.2 or older releases
2406                                          * cannot handle 64bit second transitions and they are
2407                                          * dropped from zoneinfo.txt. */
2408                                         emit_icu_zone(icuFile,
2409                                                         zpfirst->z_name, zp->z_gmtoff,
2410                                                         rp, finalRuleIndex, year + 1);
2411                                         /* only emit this for the first year */
2412                                         finalRule1 = NULL;
2413                                 }
2414 #endif
2415                                 eats(zp->z_filename, zp->z_linenum,
2416                                         rp->r_filename, rp->r_linenum);
2417                                 doabbr(ab, zp->z_format, rp->r_abbrvar,
2418                                         rp->r_stdoff != 0, FALSE);
2419                                 offset = oadd(zp->z_gmtoff, rp->r_stdoff);
2420 #ifdef ICU
2421                                 type = addtype(offset, zp->z_gmtoff, rp->r_stdoff,
2422                                         ab, rp->r_stdoff != 0,
2423                                         rp->r_todisstd, rp->r_todisgmt);
2424 #else
2425                                 type = addtype(offset, ab, rp->r_stdoff != 0,
2426                                         rp->r_todisstd, rp->r_todisgmt);
2427 #endif
2428                                 addtt(ktime, type);
2429                         }
2430                 }
2431                 if (usestart) {
2432                         if (*startbuf == '\0' &&
2433                                 zp->z_format != NULL &&
2434                                 strchr(zp->z_format, '%') == NULL &&
2435                                 strchr(zp->z_format, '/') == NULL)
2436                                         (void) strcpy(startbuf, zp->z_format);
2437                         eat(zp->z_filename, zp->z_linenum);
2438                         if (*startbuf == '\0')
2439 error(_("can't determine time zone abbreviation to use just after until time"));
2440                         else    addtt(starttime,
2441 #ifdef ICU
2442                                         addtype(startoff,
2443                                                 zp->z_gmtoff, startoff - zp->z_gmtoff,
2444                                                 startbuf,
2445                                                 startoff != zp->z_gmtoff,
2446                                                 startttisstd,
2447                                                 startttisgmt));
2448 #else
2449                                         addtype(startoff, startbuf,
2450                                                 startoff != zp->z_gmtoff,
2451                                                 startttisstd,
2452                                                 startttisgmt));
2453 #endif
2454                 }
2455                 /*
2456                 ** Now we may get to set starttime for the next zone line.
2457                 */
2458                 if (useuntil) {
2459                         startttisstd = zp->z_untilrule.r_todisstd;
2460                         startttisgmt = zp->z_untilrule.r_todisgmt;
2461                         starttime = zp->z_untiltime;
2462                         if (!startttisstd)
2463                                 starttime = tadd(starttime, -stdoff);
2464                         if (!startttisgmt)
2465                                 starttime = tadd(starttime, -gmtoff);
2466                 }
2467         }
2468         writezone(zpfirst->z_name, envvar);
2469         ifree(startbuf);
2470         ifree(ab);
2471         ifree(envvar);
2472 }
2473
2474 static void
2475 addtt(starttime, type)
2476 const zic_t     starttime;
2477 int             type;
2478 {
2479         if (starttime <= min_time ||
2480                 (timecnt == 1 && attypes[0].at < min_time)) {
2481                 gmtoffs[0] = gmtoffs[type];
2482 #ifdef ICU
2483                 rawoffs[0] = rawoffs[type];
2484                 dstoffs[0] = dstoffs[type];
2485 #endif
2486                 isdsts[0] = isdsts[type];
2487                 ttisstds[0] = ttisstds[type];
2488                 ttisgmts[0] = ttisgmts[type];
2489                 if (abbrinds[type] != 0)
2490                         (void) strcpy(chars, &chars[abbrinds[type]]);
2491                 abbrinds[0] = 0;
2492                 charcnt = strlen(chars) + 1;
2493                 typecnt = 1;
2494                 timecnt = 0;
2495                 type = 0;
2496         }
2497         if (timecnt >= TZ_MAX_TIMES) {
2498                 error(_("too many transitions?!"));
2499                 exit(EXIT_FAILURE);
2500         }
2501         attypes[timecnt].at = starttime;
2502         attypes[timecnt].type = type;
2503         ++timecnt;
2504 }
2505
2506 static int
2507 #ifdef ICU
2508 addtype(gmtoff, rawoff, dstoff, abbr, isdst, ttisstd, ttisgmt)
2509 const long              gmtoff;
2510 const long              rawoff;
2511 const long              dstoff;
2512 #else
2513 addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt)
2514 const long              gmtoff;
2515 #endif
2516 const char * const      abbr;
2517 const int               isdst;
2518 const int               ttisstd;
2519 const int               ttisgmt;
2520 {
2521         register int    i, j;
2522
2523         if (isdst != TRUE && isdst != FALSE) {
2524                 error(_("internal error - addtype called with bad isdst"));
2525                 exit(EXIT_FAILURE);
2526         }
2527         if (ttisstd != TRUE && ttisstd != FALSE) {
2528                 error(_("internal error - addtype called with bad ttisstd"));
2529                 exit(EXIT_FAILURE);
2530         }
2531         if (ttisgmt != TRUE && ttisgmt != FALSE) {
2532                 error(_("internal error - addtype called with bad ttisgmt"));
2533                 exit(EXIT_FAILURE);
2534         }
2535 #ifdef ICU
2536         if (isdst != (dstoff != 0)) {
2537                 error(_("internal error - addtype called with bad isdst/dstoff"));
2538                 (void) exit(EXIT_FAILURE);
2539         }
2540         if (gmtoff != (rawoff + dstoff)) {
2541                 error(_("internal error - addtype called with bad gmt/raw/dstoff"));
2542                 (void) exit(EXIT_FAILURE);
2543         }
2544 #endif
2545         /*
2546         ** See if there's already an entry for this zone type.
2547         ** If so, just return its index.
2548         */
2549         for (i = 0; i < typecnt; ++i) {
2550                 if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
2551 #ifdef ICU
2552                         rawoff == rawoffs[i] && dstoff == dstoffs[i] &&
2553 #endif
2554                         strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
2555                         ttisstd == ttisstds[i] &&
2556                         ttisgmt == ttisgmts[i])
2557                                 return i;
2558         }
2559         /*
2560         ** There isn't one; add a new one, unless there are already too
2561         ** many.
2562         */
2563         if (typecnt >= TZ_MAX_TYPES) {
2564                 error(_("too many local time types"));
2565                 exit(EXIT_FAILURE);
2566         }
2567         if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) {
2568                 error(_("UTC offset out of range"));
2569                 exit(EXIT_FAILURE);
2570         }
2571         gmtoffs[i] = gmtoff;
2572 #ifdef ICU
2573         rawoffs[i] = rawoff;
2574         dstoffs[i] = dstoff;
2575 #endif
2576         isdsts[i] = isdst;
2577         ttisstds[i] = ttisstd;
2578         ttisgmts[i] = ttisgmt;
2579
2580         for (j = 0; j < charcnt; ++j)
2581                 if (strcmp(&chars[j], abbr) == 0)
2582                         break;
2583         if (j == charcnt)
2584                 newabbr(abbr);
2585         abbrinds[i] = j;
2586         ++typecnt;
2587         return i;
2588 }
2589
2590 static void
2591 leapadd(t, positive, rolling, count)
2592 const zic_t     t;
2593 const int       positive;
2594 const int       rolling;
2595 int             count;
2596 {
2597         register int    i, j;
2598
2599         if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {
2600                 error(_("too many leap seconds"));
2601                 exit(EXIT_FAILURE);
2602         }
2603         for (i = 0; i < leapcnt; ++i)
2604                 if (t <= trans[i]) {
2605                         if (t == trans[i]) {
2606                                 error(_("repeated leap second moment"));
2607                                 exit(EXIT_FAILURE);
2608                         }
2609                         break;
2610                 }
2611         do {
2612                 for (j = leapcnt; j > i; --j) {
2613                         trans[j] = trans[j - 1];
2614                         corr[j] = corr[j - 1];
2615                         roll[j] = roll[j - 1];
2616                 }
2617                 trans[i] = t;
2618                 corr[i] = positive ? 1L : eitol(-count);
2619                 roll[i] = rolling;
2620                 ++leapcnt;
2621         } while (positive && --count != 0);
2622 }
2623
2624 static void
2625 adjleap(void)
2626 {
2627         register int    i;
2628         register long   last = 0;
2629
2630         /*
2631         ** propagate leap seconds forward
2632         */
2633         for (i = 0; i < leapcnt; ++i) {
2634                 trans[i] = tadd(trans[i], last);
2635                 last = corr[i] += last;
2636         }
2637 }
2638
2639 static int
2640 yearistype(year, type)
2641 const int               year;
2642 const char * const      type;
2643 {
2644         static char *   buf;
2645         int             result;
2646
2647         if (type == NULL || *type == '\0')
2648                 return TRUE;
2649         buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type)));
2650         (void) sprintf(buf, "%s %d %s", yitcommand, year, type);
2651         result = system(buf);
2652         if (WIFEXITED(result)) switch (WEXITSTATUS(result)) {
2653                 case 0:
2654                         return TRUE;
2655                 case 1:
2656                         return FALSE;
2657         }
2658         error(_("Wild result from command execution"));
2659         (void) fprintf(stderr, _("%s: command was '%s', result was %d\n"),
2660                 progname, buf, result);
2661         for ( ; ; )
2662                 exit(EXIT_FAILURE);
2663 }
2664
2665 static int
2666 lowerit(a)
2667 int     a;
2668 {
2669         a = (unsigned char) a;
2670         return (isascii(a) && isupper(a)) ? tolower(a) : a;
2671 }
2672
2673 static int
2674 ciequal(ap, bp)         /* case-insensitive equality */
2675 register const char *   ap;
2676 register const char *   bp;
2677 {
2678         while (lowerit(*ap) == lowerit(*bp++))
2679                 if (*ap++ == '\0')
2680                         return TRUE;
2681         return FALSE;
2682 }
2683
2684 static int
2685 itsabbr(abbr, word)
2686 register const char *   abbr;
2687 register const char *   word;
2688 {
2689         if (lowerit(*abbr) != lowerit(*word))
2690                 return FALSE;
2691         ++word;
2692         while (*++abbr != '\0')
2693                 do {
2694                         if (*word == '\0')
2695                                 return FALSE;
2696                 } while (lowerit(*word++) != lowerit(*abbr));
2697         return TRUE;
2698 }
2699
2700 static const struct lookup *
2701 byword(word, table)
2702 register const char * const             word;
2703 register const struct lookup * const    table;
2704 {
2705         register const struct lookup *  foundlp;
2706         register const struct lookup *  lp;
2707
2708         if (word == NULL || table == NULL)
2709                 return NULL;
2710         /*
2711         ** Look for exact match.
2712         */
2713         for (lp = table; lp->l_word != NULL; ++lp)
2714                 if (ciequal(word, lp->l_word))
2715                         return lp;
2716         /*
2717         ** Look for inexact match.
2718         */
2719         foundlp = NULL;
2720         for (lp = table; lp->l_word != NULL; ++lp)
2721                 if (itsabbr(word, lp->l_word)) {
2722                         if (foundlp == NULL)
2723                                 foundlp = lp;
2724                         else    return NULL;    /* multiple inexact matches */
2725                 }
2726         return foundlp;
2727 }
2728
2729 static char **
2730 getfields(cp)
2731 register char * cp;
2732 {
2733         register char *         dp;
2734         register char **        array;
2735         register int            nsubs;
2736
2737         if (cp == NULL)
2738                 return NULL;
2739         array = (char **) (void *)
2740                 emalloc((int) ((strlen(cp) + 1) * sizeof *array));
2741         nsubs = 0;
2742         for ( ; ; ) {
2743                 while (isascii((unsigned char) *cp) &&
2744                         isspace((unsigned char) *cp))
2745                                 ++cp;
2746                 if (*cp == '\0' || *cp == '#')
2747                         break;
2748                 array[nsubs++] = dp = cp;
2749                 do {
2750                         if ((*dp = *cp++) != '"')
2751                                 ++dp;
2752                         else while ((*dp = *cp++) != '"')
2753                                 if (*dp != '\0')
2754                                         ++dp;
2755                                 else {
2756                                         error(_(
2757                                                 "Odd number of quotation marks"
2758                                                 ));
2759                                         exit(1);
2760                                 }
2761                 } while (*cp != '\0' && *cp != '#' &&
2762                         (!isascii(*cp) || !isspace((unsigned char) *cp)));
2763                 if (isascii(*cp) && isspace((unsigned char) *cp))
2764                         ++cp;
2765                 *dp = '\0';
2766         }
2767         array[nsubs] = NULL;
2768         return array;
2769 }
2770
2771 static long
2772 oadd(t1, t2)
2773 const long      t1;
2774 const long      t2;
2775 {
2776         register long   t;
2777
2778         t = t1 + t2;
2779         if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
2780                 error(_("time overflow"));
2781                 exit(EXIT_FAILURE);
2782         }
2783         return t;
2784 }
2785
2786 static zic_t
2787 tadd(t1, t2)
2788 const zic_t     t1;
2789 const long      t2;
2790 {
2791         register zic_t  t;
2792
2793         if (t1 == max_time && t2 > 0)
2794                 return max_time;
2795         if (t1 == min_time && t2 < 0)
2796                 return min_time;
2797         t = t1 + t2;
2798         if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
2799                 error(_("time overflow"));
2800                 exit(EXIT_FAILURE);
2801         }
2802         return t;
2803 }
2804
2805 /*
2806 ** Given a rule, and a year, compute the date - in seconds since January 1,
2807 ** 1970, 00:00 LOCAL time - in that year that the rule refers to.
2808 */
2809
2810 static zic_t
2811 rpytime(rp, wantedy)
2812 register const struct rule * const      rp;
2813 register const int                      wantedy;
2814 {
2815         register int    y, m, i;
2816         register long   dayoff;                 /* with a nod to Margaret O. */
2817         register zic_t  t;
2818
2819         if (wantedy == INT_MIN)
2820                 return min_time;
2821         if (wantedy == INT_MAX)
2822                 return max_time;
2823         dayoff = 0;
2824         m = TM_JANUARY;
2825         y = EPOCH_YEAR;
2826         while (wantedy != y) {
2827                 if (wantedy > y) {
2828                         i = len_years[isleap(y)];
2829                         ++y;
2830                 } else {
2831                         --y;
2832                         i = -len_years[isleap(y)];
2833                 }
2834                 dayoff = oadd(dayoff, eitol(i));
2835         }
2836         while (m != rp->r_month) {
2837                 i = len_months[isleap(y)][m];
2838                 dayoff = oadd(dayoff, eitol(i));
2839                 ++m;
2840         }
2841         i = rp->r_dayofmonth;
2842         if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
2843                 if (rp->r_dycode == DC_DOWLEQ)
2844                         --i;
2845                 else {
2846                         error(_("use of 2/29 in non leap-year"));
2847                         exit(EXIT_FAILURE);
2848                 }
2849         }
2850         --i;
2851         dayoff = oadd(dayoff, eitol(i));
2852         if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
2853                 register long   wday;
2854
2855 #define LDAYSPERWEEK    ((long) DAYSPERWEEK)
2856                 wday = eitol(EPOCH_WDAY);
2857                 /*
2858                 ** Don't trust mod of negative numbers.
2859                 */
2860                 if (dayoff >= 0)
2861                         wday = (wday + dayoff) % LDAYSPERWEEK;
2862                 else {
2863                         wday -= ((-dayoff) % LDAYSPERWEEK);
2864                         if (wday < 0)
2865                                 wday += LDAYSPERWEEK;
2866                 }
2867                 while (wday != eitol(rp->r_wday))
2868                         if (rp->r_dycode == DC_DOWGEQ) {
2869                                 dayoff = oadd(dayoff, (long) 1);
2870                                 if (++wday >= LDAYSPERWEEK)
2871                                         wday = 0;
2872                                 ++i;
2873                         } else {
2874                                 dayoff = oadd(dayoff, (long) -1);
2875                                 if (--wday < 0)
2876                                         wday = LDAYSPERWEEK - 1;
2877                                 --i;
2878                         }
2879                 if (i < 0 || i >= len_months[isleap(y)][m]) {
2880                         if (noise)
2881                                 warning(_("rule goes past start/end of month--\
2882 will not work with pre-2004 versions of zic"));
2883                 }
2884         }
2885         if (dayoff < min_time / SECSPERDAY)
2886                 return min_time;
2887         if (dayoff > max_time / SECSPERDAY)
2888                 return max_time;
2889         t = (zic_t) dayoff * SECSPERDAY;
2890         return tadd(t, rp->r_tod);
2891 }
2892
2893 static void
2894 newabbr(string)
2895 const char * const      string;
2896 {
2897         register int    i;
2898
2899         if (strcmp(string, GRANDPARENTED) != 0) {
2900                 register const char *   cp;
2901                 register char *         wp;
2902
2903                 /*
2904                 ** Want one to ZIC_MAX_ABBR_LEN_WO_WARN alphabetics
2905                 ** optionally followed by a + or - and a number from 1 to 14.
2906                 */
2907                 cp = string;
2908                 wp = NULL;
2909                 while (isascii((unsigned char) *cp) &&
2910                         isalpha((unsigned char) *cp))
2911                                 ++cp;
2912                 if (cp - string == 0)
2913 wp = _("time zone abbreviation lacks alphabetic at start");
2914                 if (noise && cp - string > 3)
2915 wp = _("time zone abbreviation has more than 3 alphabetics");
2916                 if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
2917 wp = _("time zone abbreviation has too many alphabetics");
2918                 if (wp == NULL && (*cp == '+' || *cp == '-')) {
2919                         ++cp;
2920                         if (isascii((unsigned char) *cp) &&
2921                                 isdigit((unsigned char) *cp))
2922                                         if (*cp++ == '1' &&
2923                                                 *cp >= '0' && *cp <= '4')
2924                                                         ++cp;
2925                 }
2926                 if (*cp != '\0')
2927 wp = _("time zone abbreviation differs from POSIX standard");
2928                 if (wp != NULL) {
2929                         wp = ecpyalloc(wp);
2930                         wp = ecatalloc(wp, " (");
2931                         wp = ecatalloc(wp, string);
2932                         wp = ecatalloc(wp, ")");
2933                         warning(wp);
2934                         ifree(wp);
2935                 }
2936         }
2937         i = strlen(string) + 1;
2938         if (charcnt + i > TZ_MAX_CHARS) {
2939                 error(_("too many, or too long, time zone abbreviations"));
2940                 exit(EXIT_FAILURE);
2941         }
2942         (void) strcpy(&chars[charcnt], string);
2943         charcnt += eitol(i);
2944 }
2945
2946 static int
2947 mkdirs(argname)
2948 char *          argname;
2949 {
2950         register char * name;
2951         register char * cp;
2952
2953         if (argname == NULL || *argname == '\0')
2954                 return 0;
2955         cp = name = ecpyalloc(argname);
2956         while ((cp = strchr(cp + 1, '/')) != 0) {
2957                 *cp = '\0';
2958 #ifndef unix
2959                 /*
2960                 ** DOS drive specifier?
2961                 */
2962                 if (isalpha((unsigned char) name[0]) &&
2963                         name[1] == ':' && name[2] == '\0') {
2964                                 *cp = '/';
2965                                 continue;
2966                 }
2967 #endif /* !defined unix */
2968                 if (!itsdir(name)) {
2969                         /*
2970                         ** It doesn't seem to exist, so we try to create it.
2971                         ** Creation may fail because of the directory being
2972                         ** created by some other multiprocessor, so we get
2973                         ** to do extra checking.
2974                         */
2975                         if (mkdir(name, MKDIR_UMASK) != 0) {
2976                                 const char *e = strerror(errno);
2977
2978                                 if (errno != EEXIST || !itsdir(name)) {
2979                                         (void) fprintf(stderr,
2980 _("%s: Can't create directory %s: %s\n"),
2981                                                 progname, name, e);
2982                                         ifree(name);
2983                                         return -1;
2984                                 }
2985                         }
2986                 }
2987                 *cp = '/';
2988         }
2989         ifree(name);
2990         return 0;
2991 }
2992
2993 static long
2994 eitol(i)
2995 const int       i;
2996 {
2997         long    l;
2998
2999         l = i;
3000         if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) {
3001                 (void) fprintf(stderr,
3002                         _("%s: %d did not sign extend correctly\n"),
3003                         progname, i);
3004                 exit(EXIT_FAILURE);
3005         }
3006         return l;
3007 }
3008
3009 /*
3010 ** UNIX was a registered trademark of The Open Group in 2003.
3011 */