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