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