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