~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/timezone/zic.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

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