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