]>
Commit | Line | Data |
---|---|---|
374ca955 | 1 | diff -u -r ../tzcode.orig/Makefile ./Makefile |
24b030c3 A |
2 | --- Makefile.orig 2006-11-27 05:54:05.000000000 -0800 |
3 | +++ Makefile 2006-12-06 14:54:28.000000000 -0800 | |
374ca955 A |
4 | @@ -40,7 +40,7 @@ |
5 | # (and subdirectories). | |
6 | # Use an absolute path name for TZDIR unless you're just testing the software. | |
7 | ||
8 | -TZDIR= $(TOPDIR)/etc/zoneinfo | |
9 | +TZDIR= zoneinfo | |
10 | ||
11 | # The "tzselect", "zic", and "zdump" commands get installed in. . . | |
12 | ||
24b030c3 | 13 | @@ -241,9 +241,11 @@ |
374ca955 A |
14 | |
15 | ############################################################################### | |
16 | ||
17 | -cc= cc | |
18 | +cc= gcc | |
19 | CC= $(cc) -DTZDIR=\"$(TZDIR)\" | |
20 | ||
21 | +CPP= g++ | |
22 | + | |
23 | TZCSRCS= zic.c localtime.c asctime.c scheck.c ialloc.c | |
24 | TZCOBJS= zic.o localtime.o asctime.o scheck.o ialloc.o | |
24b030c3 A |
25 | TZDSRCS= zdump.c localtime.c ialloc.c |
26 | @@ -278,7 +280,10 @@ | |
374ca955 A |
27 | |
28 | SHELL= /bin/sh | |
29 | ||
30 | -all: tzselect zic zdump $(LIBOBJS) | |
24b030c3 | 31 | +LS= /bin/ls |
374ca955 A |
32 | +SED= /usr/bin/sed |
33 | + | |
34 | +all: tzselect zic zdump $(LIBOBJS) tz2icu | |
35 | ||
36 | ALL: all date | |
37 | ||
24b030c3 | 38 | @@ -311,9 +316,12 @@ |
374ca955 A |
39 | zdump: $(TZDOBJS) |
40 | $(CC) $(CFLAGS) $(LFLAGS) $(TZDOBJS) $(LDLIBS) -o $@ | |
41 | ||
42 | -zic: $(TZCOBJS) yearistype | |
43 | +zic: $(TZCOBJS) yearistype tz2icu.h | |
44 | $(CC) $(CFLAGS) $(LFLAGS) $(TZCOBJS) $(LDLIBS) -o $@ | |
45 | ||
46 | +tz2icu: tz2icu.cpp tz2icu.h | |
47 | + $(CPP) -W -Wall -pedantic tz2icu.cpp -o $@ | |
48 | + | |
49 | yearistype: yearistype.sh | |
50 | cp yearistype.sh yearistype | |
51 | chmod +x yearistype | |
24b030c3 | 52 | @@ -324,6 +332,9 @@ |
374ca955 A |
53 | right_only: zic leapseconds $(TDATA) |
54 | $(ZIC) -y $(YEARISTYPE) -d $(TZDIR) -L leapseconds $(TDATA) | |
55 | ||
56 | +icu_data: tz2icu posix_only | |
57 | + ./tz2icu zoneinfo zone.tab `$(LS) tzdata*.tar.gz | $(SED) -e "s/^tzdata//;s/\.tar\.gz$$//"` | |
58 | + | |
59 | # In earlier versions of this makefile, the other two directories were | |
60 | # subdirectories of $(TZDIR). However, this led to configuration errors. | |
61 | # For example, with posix_right under the earlier scheme, | |
62 | diff -u -r ../tzcode.orig/zic.c ./zic.c | |
24b030c3 A |
63 | --- zic.c.orig 2006-12-06 14:29:17.000000000 -0800 |
64 | +++ zic.c 2006-12-06 14:51:36.000000000 -0800 | |
65 | @@ -26,6 +26,20 @@ | |
374ca955 A |
66 | #define MKDIR_UMASK 0755 |
67 | #endif | |
68 | ||
69 | +/* Enable extensions and modifications for ICU. */ | |
70 | +#define ICU | |
71 | + | |
72 | +/* Continue executing after link failure. Even if ICU is undefined | |
73 | + * (for vanilla zic behavior), ICU_LINKS should be defined, since zic | |
74 | + * appears to fail on the 2003 data the first time through during the | |
75 | + * linking phase. Running zic twice, with ICU_LINKS defined, causes | |
76 | + * links to be handled correctly. */ | |
77 | +#define ICU_LINKS | |
78 | + | |
79 | +#ifdef ICU | |
80 | +#include "tz2icu.h" | |
81 | +#endif | |
82 | + | |
83 | /* | |
84 | ** On some ancient hosts, predicates like `isspace(C)' are defined | |
24b030c3 A |
85 | ** only if isascii(C) || C == EOF. Modern hosts obey the C Standard, |
86 | @@ -106,8 +120,14 @@ | |
374ca955 A |
87 | extern int optind; |
88 | ||
24b030c3 | 89 | static void addtt P((zic_t starttime, int type)); |
374ca955 A |
90 | +#ifdef ICU |
91 | +static int addtype P((long gmtoff, long rawoff, long dstoff, | |
92 | + const char * abbr, int isdst, | |
93 | + int ttisstd, int ttisgmt)); | |
94 | +#else | |
95 | static int addtype P((long gmtoff, const char * abbr, int isdst, | |
96 | int ttisstd, int ttisgmt)); | |
97 | +#endif | |
24b030c3 | 98 | static void leapadd P((zic_t t, int positive, int rolling, int count)); |
374ca955 A |
99 | static void adjleap P((void)); |
100 | static void associate P((void)); | |
24b030c3 | 101 | @@ -287,6 +307,18 @@ |
374ca955 A |
102 | const int l_value; |
103 | }; | |
104 | ||
105 | +#ifdef ICU | |
106 | + | |
107 | +/* Indices into rules[] for final rules. They will occur in pairs, | |
108 | + * with finalRules[i] occurring before finalRules[i+1] in the year. | |
109 | + * Each zone need only store a start year, a standard offset, and an | |
110 | + * index into finalRules[]. FinalRules[] are aliases into rules[]. */ | |
111 | + | |
112 | +static const struct rule ** finalRules; | |
113 | +static int finalRulesCount; | |
114 | + | |
115 | +#endif | |
116 | + | |
117 | static struct lookup const * byword P((const char * string, | |
118 | const struct lookup * lp)); | |
119 | ||
24b030c3 | 120 | @@ -369,6 +401,11 @@ |
374ca955 A |
121 | unsigned char type; |
122 | } attypes[TZ_MAX_TIMES]; | |
123 | static long gmtoffs[TZ_MAX_TYPES]; | |
124 | +#ifdef ICU | |
125 | +/* gmtoffs[i] = rawoffs[i] + dstoffs[i] */ | |
126 | +static long rawoffs[TZ_MAX_TYPES]; | |
127 | +static long dstoffs[TZ_MAX_TYPES]; | |
128 | +#endif | |
129 | static char isdsts[TZ_MAX_TYPES]; | |
130 | static unsigned char abbrinds[TZ_MAX_TYPES]; | |
131 | static char ttisstds[TZ_MAX_TYPES]; | |
24b030c3 A |
132 | @@ -480,6 +517,62 @@ |
133 | exit(EXIT_FAILURE); | |
374ca955 A |
134 | } |
135 | ||
136 | +#ifdef ICU | |
137 | + | |
138 | +/* File into which we will write supplemental ICU data. */ | |
139 | +static FILE * icuFile; | |
140 | + | |
141 | +void emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset, | |
142 | + const struct rule* rule, | |
143 | + int ruleIndex, int startYear) { | |
144 | + /* machine-readable section */ | |
145 | + fprintf(f, "zone %s %d %d %s", zoneName, zoneOffset, startYear, rule->r_name); | |
146 | + | |
147 | + /* human-readable section */ | |
148 | + fprintf(f, " # zone %s, offset %d, year >= %d, rule %s (%d)\n", | |
149 | + zoneName, zoneOffset, startYear, | |
150 | + rule->r_name, ruleIndex); | |
151 | +} | |
152 | + | |
153 | +void emit_icu_link(FILE* f, const char* from, const char* to) { | |
154 | + /* machine-readable section */ | |
155 | + fprintf(f, "link %s %s\n", from, to); | |
156 | +} | |
157 | + | |
158 | +static const char* DYCODE[] = {"DOM", "DOWGEQ", "DOWLEQ"}; | |
159 | + | |
160 | +void emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex) { | |
161 | + if (r->r_yrtype != NULL) { | |
162 | + warning("year types not supported by ICU"); | |
163 | + fprintf(stderr, "rule %s, file %s, line %d\n", | |
164 | + r->r_name, r->r_filename, r->r_linenum); | |
165 | + } | |
166 | + | |
167 | + /* machine-readable section */ | |
168 | + fprintf(f, "rule %s %s %d %d %d %d %d %d %d", | |
169 | + r->r_name, DYCODE[r->r_dycode], | |
170 | + r->r_month, r->r_dayofmonth, | |
171 | + (r->r_dycode == DC_DOM ? -1 : r->r_wday), | |
172 | + r->r_tod, r->r_todisstd, r->r_todisgmt, r->r_stdoff | |
173 | + ); | |
174 | + | |
175 | + /* human-readable section */ | |
176 | + fprintf(f, " # %d: %s, file %s, line %d", | |
177 | + ruleIndex, r->r_name, r->r_filename, r->r_linenum); | |
178 | + fprintf(f, ", mode %s", DYCODE[r->r_dycode]); | |
179 | + fprintf(f, ", %s, dom %d", mon_names[r->r_month].l_word, r->r_dayofmonth); | |
180 | + if (r->r_dycode != DC_DOM) { | |
181 | + fprintf(f, ", %s", wday_names[r->r_wday].l_word); | |
182 | + } | |
183 | + fprintf(f, ", time %d", r->r_tod); | |
184 | + fprintf(f, ", isstd %d", r->r_todisstd); | |
185 | + fprintf(f, ", isgmt %d", r->r_todisgmt); | |
186 | + fprintf(f, ", offset %ld", r->r_stdoff); | |
187 | + fprintf(f, "\n"); | |
188 | +} | |
189 | + | |
190 | +#endif | |
191 | + | |
192 | static const char * psxrules; | |
193 | static const char * lcltime; | |
194 | static const char * directory; | |
24b030c3 | 195 | @@ -591,6 +684,14 @@ |
374ca955 A |
196 | adjleap(); |
197 | } | |
198 | ||
199 | +#ifdef ICU | |
200 | + if ((icuFile = fopen(ICU_ZONE_FILE, "w")) == NULL) { | |
201 | + const char *e = strerror(errno); | |
202 | + (void) fprintf(stderr, _("%s: Can't open %s: %s\n"), | |
203 | + progname, ICU_ZONE_FILE, e); | |
204 | + (void) exit(EXIT_FAILURE); | |
205 | + } | |
206 | +#endif | |
207 | for (i = optind; i < argc; ++i) | |
208 | infile(argv[i]); | |
209 | if (errors) | |
24b030c3 | 210 | @@ -610,6 +711,9 @@ |
374ca955 A |
211 | for (i = 0; i < nlinks; ++i) { |
212 | eat(links[i].l_filename, links[i].l_linenum); | |
213 | dolink(links[i].l_from, links[i].l_to); | |
214 | +#ifdef ICU | |
24b030c3 | 215 | + emit_icu_link(icuFile, links[i].l_from, links[i].l_to); |
374ca955 | 216 | +#endif |
24b030c3 A |
217 | if (noise) |
218 | for (j = 0; j < nlinks; ++j) | |
219 | if (strcmp(links[i].l_to, | |
220 | @@ -624,6 +728,11 @@ | |
374ca955 A |
221 | eat("command line", 1); |
222 | dolink(psxrules, TZDEFRULES); | |
223 | } | |
224 | +#ifdef ICU | |
225 | + for (i=0; i<finalRulesCount; ++i) { | |
226 | + emit_icu_rule(icuFile, finalRules[i], i); | |
227 | + } | |
228 | +#endif /*ICU*/ | |
229 | return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE; | |
230 | } | |
231 | ||
24b030c3 | 232 | @@ -689,7 +798,9 @@ |
374ca955 A |
233 | (void) fprintf(stderr, |
234 | _("%s: Can't link from %s to %s: %s\n"), | |
235 | progname, fromname, toname, e); | |
236 | +#ifndef ICU_LINKS | |
24b030c3 | 237 | exit(EXIT_FAILURE); |
374ca955 A |
238 | +#endif |
239 | } | |
240 | } | |
241 | ifree(fromname); | |
24b030c3 A |
242 | @@ -1655,7 +1766,12 @@ |
243 | #define DO(field) (void) fwrite((void *) tzh.field, \ | |
244 | (size_t) sizeof tzh.field, (size_t) 1, fp) | |
245 | tzh = tzh0; | |
374ca955 A |
246 | +#ifdef ICU |
247 | + * (ICUZoneinfoVersion*) &tzh.tzh_reserved = TZ_ICU_VERSION; | |
248 | + (void) strncpy(tzh.tzh_magic, TZ_ICU_MAGIC, sizeof tzh.tzh_magic); | |
249 | +#else | |
24b030c3 | 250 | (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); |
374ca955 | 251 | +#endif |
24b030c3 A |
252 | tzh.tzh_version[0] = ZIC_VERSION; |
253 | convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt); | |
254 | convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt); | |
255 | @@ -1688,7 +1804,12 @@ | |
256 | } | |
257 | for (i = 0; i < typecnt; ++i) | |
258 | if (writetype[i]) { | |
374ca955 A |
259 | +#ifdef ICU |
260 | + puttzcode((long) rawoffs[i], fp); | |
261 | + puttzcode((long) dstoffs[i], fp); | |
262 | +#else | |
24b030c3 | 263 | puttzcode(gmtoffs[i], fp); |
374ca955 | 264 | +#endif |
24b030c3 A |
265 | (void) putc(isdsts[i], fp); |
266 | (void) putc((unsigned char) indmap[abbrinds[i]], fp); | |
267 | } | |
268 | @@ -1957,6 +2078,24 @@ | |
374ca955 A |
269 | } |
270 | } | |
271 | ||
272 | +#ifdef ICU | |
273 | + | |
274 | +int add_icu_final_rules(const struct rule* r1, const struct rule* r2) { | |
275 | + int i; | |
276 | + | |
277 | + for (i=0; i<finalRulesCount; ++i) { /* i+=2 should work too */ | |
278 | + if (r1==finalRules[i]) return i; /* [sic] pointer comparison */ | |
279 | + } | |
280 | + | |
281 | + finalRules = (const struct rule**) (void*) erealloc((char *) finalRules, | |
282 | + (finalRulesCount + 2) * sizeof(*finalRules)); | |
283 | + finalRules[finalRulesCount++] = r1; | |
284 | + finalRules[finalRulesCount++] = r2; | |
285 | + return finalRulesCount - 2; | |
286 | +} | |
287 | + | |
288 | +#endif /*ICU*/ | |
289 | + | |
290 | static void | |
291 | outzone(zpfirst, zonecount) | |
292 | const struct zone * const zpfirst; | |
24b030c3 A |
293 | @@ -1979,6 +2118,11 @@ |
294 | register char * envvar; | |
295 | register int max_abbr_len; | |
296 | register int max_envvar_len; | |
374ca955 A |
297 | +#ifdef ICU |
298 | + int finalRuleYear, finalRuleIndex; | |
299 | + const struct rule* finalRule1; | |
300 | + const struct rule* finalRule2; | |
301 | +#endif | |
302 | ||
24b030c3 A |
303 | max_abbr_len = 2 + max_format_len + max_abbrvar_len; |
304 | max_envvar_len = 2 * max_abbr_len + 5 * 9; | |
305 | @@ -2055,11 +2199,55 @@ | |
374ca955 A |
306 | eat(zp->z_filename, zp->z_linenum); |
307 | *startbuf = '\0'; | |
308 | startoff = zp->z_gmtoff; | |
309 | +#ifdef ICU | |
310 | + finalRuleYear = finalRuleIndex = -1; | |
311 | + finalRule1 = finalRule2 = NULL; | |
312 | + if (i == (zonecount - 1)) { /* !useuntil */ | |
313 | + /* Look for exactly 2 rules that end at 'max' and | |
314 | + * note them. Determine max(r_loyear) for the 2 of | |
315 | + * them. */ | |
316 | + for (j=0; j<zp->z_nrules; ++j) { | |
317 | + rp = &zp->z_rules[j]; | |
318 | + if (rp->r_hiyear == INT_MAX) { | |
319 | + if (finalRule1 == NULL) { | |
320 | + finalRule1 = rp; | |
321 | + finalRuleYear = rp->r_loyear; | |
322 | + } else if (finalRule2 == NULL) { | |
323 | + finalRule2 = rp; | |
324 | + if (rp->r_loyear > finalRuleYear) { | |
325 | + finalRuleYear = rp->r_loyear; | |
326 | + } | |
327 | + } else { | |
328 | + error("more than two max rules found (ICU)"); | |
329 | + exit(EXIT_FAILURE); | |
330 | + } | |
331 | + } | |
332 | + } | |
333 | + if (finalRule1 != NULL && finalRule2 == NULL) { | |
334 | + error("only one max rule found (ICU)"); | |
335 | + exit(EXIT_FAILURE); | |
336 | + } | |
337 | + if (finalRule1 != NULL) { | |
338 | + /* Swap if necessary so finalRule1 occurs before | |
339 | + * finalRule2 */ | |
340 | + if (finalRule1->r_month > finalRule2->r_month) { | |
341 | + const struct rule* t = finalRule1; | |
342 | + finalRule1 = finalRule2; | |
343 | + finalRule2 = t; | |
344 | + } | |
345 | + /* Add final rule to our list */ | |
346 | + finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2); | |
347 | + } | |
348 | + } | |
349 | +#endif | |
350 | if (zp->z_nrules == 0) { | |
351 | stdoff = zp->z_stdoff; | |
352 | doabbr(startbuf, zp->z_format, | |
24b030c3 | 353 | (char *) NULL, stdoff != 0, FALSE); |
374ca955 A |
354 | type = addtype(oadd(zp->z_gmtoff, stdoff), |
355 | +#ifdef ICU | |
356 | + zp->z_gmtoff, stdoff, | |
357 | +#endif | |
358 | startbuf, stdoff != 0, startttisstd, | |
359 | startttisgmt); | |
360 | if (usestart) { | |
24b030c3 | 361 | @@ -2132,6 +2320,15 @@ |
374ca955 A |
362 | break; /* go on to next year */ |
363 | rp = &zp->z_rules[k]; | |
364 | rp->r_todo = FALSE; | |
365 | +#ifdef ICU | |
366 | + if (year >= finalRuleYear && rp == finalRule1) { | |
367 | + emit_icu_zone(icuFile, | |
368 | + zpfirst->z_name, zp->z_gmtoff, | |
369 | + rp, finalRuleIndex, year); | |
370 | + /* only emit this for the first year */ | |
371 | + finalRule1 = NULL; | |
372 | + } | |
373 | +#endif | |
374 | if (useuntil && ktime >= untiltime) | |
375 | break; | |
376 | stdoff = rp->r_stdoff; | |
24b030c3 A |
377 | @@ -2163,8 +2360,14 @@ |
378 | doabbr(ab, zp->z_format, rp->r_abbrvar, | |
379 | rp->r_stdoff != 0, FALSE); | |
374ca955 A |
380 | offset = oadd(zp->z_gmtoff, rp->r_stdoff); |
381 | +#ifdef ICU | |
382 | + type = addtype(offset, zp->z_gmtoff, rp->r_stdoff, | |
24b030c3 | 383 | + ab, rp->r_stdoff != 0, |
374ca955 A |
384 | + rp->r_todisstd, rp->r_todisgmt); |
385 | +#else | |
24b030c3 | 386 | type = addtype(offset, ab, rp->r_stdoff != 0, |
374ca955 A |
387 | rp->r_todisstd, rp->r_todisgmt); |
388 | +#endif | |
389 | addtt(ktime, type); | |
390 | } | |
391 | } | |
24b030c3 | 392 | @@ -2178,10 +2381,19 @@ |
374ca955 A |
393 | if (*startbuf == '\0') |
394 | error(_("can't determine time zone abbreviation to use just after until time")); | |
395 | else addtt(starttime, | |
396 | +#ifdef ICU | |
397 | + addtype(startoff, | |
398 | + zp->z_gmtoff, startoff - zp->z_gmtoff, | |
399 | + startbuf, | |
400 | + startoff != zp->z_gmtoff, | |
401 | + startttisstd, | |
402 | + startttisgmt)); | |
403 | +#else | |
404 | addtype(startoff, startbuf, | |
405 | startoff != zp->z_gmtoff, | |
406 | startttisstd, | |
407 | startttisgmt)); | |
408 | +#endif | |
409 | } | |
410 | /* | |
411 | ** Now we may get to set starttime for the next zone line. | |
24b030c3 | 412 | @@ -2210,6 +2422,10 @@ |
374ca955 A |
413 | if (starttime <= min_time || |
414 | (timecnt == 1 && attypes[0].at < min_time)) { | |
415 | gmtoffs[0] = gmtoffs[type]; | |
416 | +#ifdef ICU | |
417 | + rawoffs[0] = rawoffs[type]; | |
418 | + dstoffs[0] = dstoffs[type]; | |
419 | +#endif | |
420 | isdsts[0] = isdsts[type]; | |
421 | ttisstds[0] = ttisstds[type]; | |
422 | ttisgmts[0] = ttisgmts[type]; | |
24b030c3 | 423 | @@ -2231,8 +2447,15 @@ |
374ca955 A |
424 | } |
425 | ||
426 | static int | |
427 | +#ifdef ICU | |
428 | +addtype(gmtoff, rawoff, dstoff, abbr, isdst, ttisstd, ttisgmt) | |
429 | +const long gmtoff; | |
430 | +const long rawoff; | |
431 | +const long dstoff; | |
432 | +#else | |
433 | addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt) | |
434 | const long gmtoff; | |
435 | +#endif | |
436 | const char * const abbr; | |
437 | const int isdst; | |
438 | const int ttisstd; | |
24b030c3 | 439 | @@ -2252,12 +2475,25 @@ |
374ca955 | 440 | error(_("internal error - addtype called with bad ttisgmt")); |
24b030c3 | 441 | exit(EXIT_FAILURE); |
374ca955 A |
442 | } |
443 | +#ifdef ICU | |
444 | + if (isdst != (dstoff != 0)) { | |
445 | + error(_("internal error - addtype called with bad isdst/dstoff")); | |
446 | + (void) exit(EXIT_FAILURE); | |
447 | + } | |
448 | + if (gmtoff != (rawoff + dstoff)) { | |
449 | + error(_("internal error - addtype called with bad gmt/raw/dstoff")); | |
450 | + (void) exit(EXIT_FAILURE); | |
451 | + } | |
452 | +#endif | |
453 | /* | |
454 | ** See if there's already an entry for this zone type. | |
455 | ** If so, just return its index. | |
456 | */ | |
457 | for (i = 0; i < typecnt; ++i) { | |
458 | if (gmtoff == gmtoffs[i] && isdst == isdsts[i] && | |
459 | +#ifdef ICU | |
460 | + rawoff == rawoffs[i] && dstoff == dstoffs[i] && | |
461 | +#endif | |
462 | strcmp(abbr, &chars[abbrinds[i]]) == 0 && | |
463 | ttisstd == ttisstds[i] && | |
464 | ttisgmt == ttisgmts[i]) | |
24b030c3 A |
465 | @@ -2272,6 +2508,10 @@ |
466 | exit(EXIT_FAILURE); | |
374ca955 A |
467 | } |
468 | gmtoffs[i] = gmtoff; | |
469 | +#ifdef ICU | |
470 | + rawoffs[i] = rawoff; | |
471 | + dstoffs[i] = dstoff; | |
472 | +#endif | |
473 | isdsts[i] = isdst; | |
474 | ttisstds[i] = ttisstd; | |
475 | ttisgmts[i] = ttisgmt; |