1/* 2** This file is in the public domain, so clarified as of 3** 2006-07-17 by Arthur David Olson. 4*/ 5 6static 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 14typedef 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 61struct 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 98struct 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 116extern int getopt(int argc, char * const argv[], 117 const char * options); 118extern int link(const char * fromname, const char * toname); 119extern char * optarg; 120extern int optind; 121 122static void addtt(zic_t starttime, int type); 123#ifdef ICU 124static int addtype(long gmtoff, long rawoff, long dstoff, 125 const char * abbr, int isdst, 126 int ttisstd, int ttisgmt); 127#else 128static int addtype(long gmtoff, const char * abbr, int isdst, 129 int ttisstd, int ttisgmt); 130#endif 131static void leapadd(zic_t t, int positive, int rolling, int count); 132static void adjleap(void); 133static void associate(void); 134static int ciequal(const char * ap, const char * bp); 135static void convert(long val, char * buf); 136static void convert64(zic_t val, char * buf); 137static void dolink(const char * fromfield, const char * tofield); 138static void doabbr(char * abbr, const char * format, 139 const char * letters, int isdst, int doquotes); 140static void eat(const char * name, int num); 141static void eats(const char * name, int num, 142 const char * rname, int rnum); 143static long eitol(int i); 144static void error(const char * message); 145static char ** getfields(char * buf); 146static long gethms(const char * string, const char * errstrng, 147 int signable); 148static void infile(const char * filename); 149static void inleap(char ** fields, int nfields); 150static void inlink(char ** fields, int nfields); 151static void inrule(char ** fields, int nfields); 152static int inzcont(char ** fields, int nfields); 153static int inzone(char ** fields, int nfields); 154static int inzsub(char ** fields, int nfields, int iscont); 155static int is32(zic_t x); 156static int itsabbr(const char * abbr, const char * word); 157static int itsdir(const char * name); 158static int lowerit(int c); 159static char * memcheck(char * tocheck); 160static int mkdirs(char * filename); 161static void newabbr(const char * abbr); 162static long oadd(long t1, long t2); 163static void outzone(const struct zone * zp, int ntzones); 164static void puttzcode(long code, FILE * fp); 165static void puttzcode64(zic_t code, FILE * fp); 166static int rcomp(const void * leftp, const void * rightp); 167static zic_t rpytime(const struct rule * rp, int wantedy); 168static 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); 172static int stringoffset(char * result, long offset); 173static int stringrule(char * result, const struct rule * rp, 174 long dstoff, long gmtoff); 175static void stringzone(char * result, 176 const struct zone * zp, int ntzones); 177static void setboundaries(void); 178static zic_t tadd(zic_t t1, long t2); 179static void usage(FILE *stream, int status); 180static void writezone(const char * name, const char * string); 181static int yearistype(int year, const char * type); 182#ifdef ICU 183static void emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset, 184 const struct rule* rule, 185 int ruleIndex, int startYear); 186static void emit_icu_link(FILE* f, const char* from, const char* to); 187static void emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex); 188static int add_icu_final_rules(const struct rule* r1, const struct rule* r2); 189#endif 190 191static int charcnt; 192static int errors; 193static const char * filename; 194static int leapcnt; 195static int leapseen; 196static int leapminyear; 197static int leapmaxyear; 198static int linenum; 199static int max_abbrvar_len; 200static int max_format_len; 201static zic_t max_time; 202static int max_year; 203static zic_t min_time; 204static int min_year; 205static int noise; 206static const char * rfilename; 207static int rlinenum; 208static const char * progname; 209static int timecnt; 210static 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 293static struct rule * rules; 294static int nrules; /* number of rules */ 295 296static struct zone * zones; 297static int nzones; /* number of zones */ 298 299struct link { 300 const char * l_filename; 301 int l_linenum; 302 const char * l_from; 303 const char * l_to; 304}; 305 306static struct link * links; 307static int nlinks; 308 309struct 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[]. */ 319static const struct rule ** finalRules; 320static int finalRulesCount; 321#endif 322 323static struct lookup const * byword(const char * string, 324 const struct lookup * lp); 325 326static 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 334static 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 350static 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 361static 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 372static struct lookup const begin_years[] = { 373 { "minimum", YR_MINIMUM }, 374 { "maximum", YR_MAXIMUM }, 375 { NULL, 0 } 376}; 377 378static struct lookup const end_years[] = { 379 { "minimum", YR_MINIMUM }, 380 { "maximum", YR_MAXIMUM }, 381 { "only", YR_ONLY }, 382 { NULL, 0 } 383}; 384 385static struct lookup const leap_types[] = { 386 { "Rolling", TRUE }, 387 { "Stationary", FALSE }, 388 { NULL, 0 } 389}; 390 391static 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 396static const int len_years[2] = { 397 DAYSPERNYEAR, DAYSPERLYEAR 398}; 399 400static struct attype { 401 zic_t at; 402 unsigned char type; 403} attypes[TZ_MAX_TIMES]; 404static long gmtoffs[TZ_MAX_TYPES]; 405#ifdef ICU 406/* gmtoffs[i] = rawoffs[i] + dstoffs[i] */ 407static long rawoffs[TZ_MAX_TYPES]; 408static long dstoffs[TZ_MAX_TYPES]; 409#endif 410static char isdsts[TZ_MAX_TYPES]; 411static unsigned char abbrinds[TZ_MAX_TYPES]; 412static char ttisstds[TZ_MAX_TYPES]; 413static char ttisgmts[TZ_MAX_TYPES]; 414static char chars[TZ_MAX_CHARS]; 415static zic_t trans[TZ_MAX_LEAPS]; 416static long corr[TZ_MAX_LEAPS]; 417static char roll[TZ_MAX_LEAPS]; 418 419/* 420** Memory allocation. 421*/ 422 423static char * 424memcheck(ptr) 425char * 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 446static void 447eats(name, num, rname, rnum) 448const char * const name; 449const int num; 450const char * const rname; 451const int rnum; 452{ 453 filename = name; 454 linenum = num; 455 rfilename = rname; 456 rlinenum = rnum; 457} 458 459static void 460eat(name, num) 461const char * const name; 462const int num; 463{ 464 eats(name, num, (char *) NULL, -1); 465} 466 467static void 468error(string) 469const 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 485static void 486warning(string) 487const 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 498static void 499usage(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\ 505Report bugs to tz@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. */ 512static FILE * icuFile; 513 514static void 515emit_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 527static void 528emit_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 533static const char* DYCODE[] = {"DOM", "DOWGEQ", "DOWLEQ"}; 534 535static void 536emit_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 566static int 567add_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 582static const char * psxrules; 583static const char * lcltime; 584static const char * directory; 585static const char * leapsec; 586static const char * yitcommand; 587 588int 589main(argc, argv) 590int argc; 591char * 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 747static void 748dolink(fromfield, tofield) 749const char * const fromfield; 750const 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) 799warning(_("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 820static void 821setboundaries(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 831static int 832itsdir(name) 833const 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 853static int 854rcomp(cp1, cp2) 855const void * cp1; 856const void * cp2; 857{ 858 return strcmp(((const struct rule *) cp1)->r_name, 859 ((const struct rule *) cp2)->r_name); 860} 861 862static void 863associate(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 938static void 939infile(name) 940const 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 1042static long 1043gethms(string, errstring, signable) 1044const char * string; 1045const char * const errstring; 1046const 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)))) 1082warning(_("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 1087static void 1088inrule(fields, nfields) 1089register char ** const fields; 1090const 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 1116static int 1117inzone(fields, nfields) 1118register char ** const fields; 1119const 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 1161static int 1162inzcont(fields, nfields) 1163register char ** const fields; 1164const 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 1173static int 1174inzsub(fields, nfields, iscont) 1175register char ** const fields; 1176const int nfields; 1177const 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 1254static void 1255inleap(fields, nfields) 1256register char ** const fields; 1257const 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 1358static void 1359inlink(fields, nfields) 1360register char ** const fields; 1361const 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 1386static void 1387rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep) 1388register struct rule * const rp; 1389const char * const loyearp; 1390const char * const hiyearp; 1391const char * const typep; 1392const char * const monthp; 1393const char * const dayp; 1394const 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 1537static void 1538convert(val, buf) 1539const long val; 1540char * 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 1549static void 1550convert64(val, buf) 1551const zic_t val; 1552char * 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 1561static void 1562puttzcode(val, fp) 1563const long val; 1564FILE * 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 1572static void 1573puttzcode64(val, fp) 1574const zic_t val; 1575FILE * 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 1583static int 1584atcomp(avp, bvp) 1585const void * avp; 1586const 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 1594static int 1595is32(x) 1596const zic_t x; 1597{ 1598 return INT32_MIN <= x && x <= INT32_MAX; 1599} 1600 1601static void 1602writezone(name, string) 1603const char * const name; 1604const 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 1874static void 1875doabbr(abbr, format, letters, isdst, doquotes) 1876char * const abbr; 1877const char * const format; 1878const char * const letters; 1879const int isdst; 1880const 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 1915static void 1916updateminmax(x) 1917const int x; 1918{ 1919 if (min_year > x) 1920 min_year = x; 1921 if (max_year < x) 1922 max_year = x; 1923} 1924 1925static int 1926stringoffset(result, offset) 1927char * result; 1928long 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 1957static int 1958stringrule(result, rp, dstoff, gmtoff) 1959char * result; 1960const struct rule * const rp; 1961const long dstoff; 1962const 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 2012static void 2013stringzone(result, zpfirst, zonecount) 2014char * result; 2015const struct zone * const zpfirst; 2016const 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 2095static void 2096outzone(zpfirst, zonecount) 2097const struct zone * const zpfirst; 2098const 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 2166wp = 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 (finalRule1 == NULL) { 2213 finalRule1 = rp; 2214 finalRuleYear = rp->r_loyear; 2215 } else if (finalRule2 == NULL) { 2216 finalRule2 = rp; 2217 if (rp->r_loyear > finalRuleYear) { 2218 finalRuleYear = rp->r_loyear; 2219 } 2220 } else { 2221 error("more than two max rules found (ICU)"); 2222 exit(EXIT_FAILURE); 2223 } 2224 } 2225 } 2226 if (finalRule1 != NULL && finalRule2 == NULL) { 2227 error("only one max rule found (ICU)"); 2228 exit(EXIT_FAILURE); 2229 } 2230 if (finalRule1 != NULL) { 2231 if (finalRule1->r_stdoff == finalRule2->r_stdoff) { 2232 /* America/Resolute in 2009a uses a pair of rules 2233 * which does not change the offset. ICU ignores 2234 * such rules without actual time transitions. */ 2235 finalRuleYear = finalRuleIndex = -1; 2236 finalRule1 = finalRule2 = NULL; 2237 } else { 2238 /* Swap if necessary so finalRule1 occurs before 2239 * finalRule2 */ 2240 if (finalRule1->r_month > finalRule2->r_month) { 2241 const struct rule* t = finalRule1; 2242 finalRule1 = finalRule2; 2243 finalRule2 = t; 2244 } 2245 /* Add final rule to our list */ 2246 finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2); 2247 } 2248 } 2249 } 2250#endif 2251 2252 if (zp->z_nrules == 0) { 2253 stdoff = zp->z_stdoff; 2254 doabbr(startbuf, zp->z_format, 2255 (char *) NULL, stdoff != 0, FALSE); 2256 type = addtype(oadd(zp->z_gmtoff, stdoff), 2257#ifdef ICU 2258 zp->z_gmtoff, stdoff, 2259#endif 2260 startbuf, stdoff != 0, startttisstd, 2261 startttisgmt); 2262 if (usestart) { 2263 addtt(starttime, type); 2264 usestart = FALSE; 2265 } else if (stdoff != 0) 2266 addtt(min_time, type); 2267 } else for (year = min_year; year <= max_year; ++year) { 2268 if (useuntil && year > zp->z_untilrule.r_hiyear) 2269 break; 2270 /* 2271 ** Mark which rules to do in the current year. 2272 ** For those to do, calculate rpytime(rp, year); 2273 */ 2274 for (j = 0; j < zp->z_nrules; ++j) { 2275 rp = &zp->z_rules[j]; 2276 eats(zp->z_filename, zp->z_linenum, 2277 rp->r_filename, rp->r_linenum); 2278 rp->r_todo = year >= rp->r_loyear && 2279 year <= rp->r_hiyear && 2280 yearistype(year, rp->r_yrtype); 2281 if (rp->r_todo) 2282 rp->r_temp = rpytime(rp, year); 2283 } 2284 for ( ; ; ) { 2285 register int k; 2286 register zic_t jtime, ktime; 2287 register long offset; 2288 2289 INITIALIZE(ktime); 2290 if (useuntil) { 2291 /* 2292 ** Turn untiltime into UTC 2293 ** assuming the current gmtoff and 2294 ** stdoff values. 2295 */ 2296 untiltime = zp->z_untiltime; 2297 if (!zp->z_untilrule.r_todisgmt) 2298 untiltime = tadd(untiltime, 2299 -gmtoff); 2300 if (!zp->z_untilrule.r_todisstd) 2301 untiltime = tadd(untiltime, 2302 -stdoff); 2303 } 2304 /* 2305 ** Find the rule (of those to do, if any) 2306 ** that takes effect earliest in the year. 2307 */ 2308 k = -1; 2309 for (j = 0; j < zp->z_nrules; ++j) { 2310 rp = &zp->z_rules[j]; 2311 if (!rp->r_todo) 2312 continue; 2313 eats(zp->z_filename, zp->z_linenum, 2314 rp->r_filename, rp->r_linenum); 2315 offset = rp->r_todisgmt ? 0 : gmtoff; 2316 if (!rp->r_todisstd) 2317 offset = oadd(offset, stdoff); 2318 jtime = rp->r_temp; 2319 if (jtime == min_time || 2320 jtime == max_time) 2321 continue; 2322 jtime = tadd(jtime, -offset); 2323 if (k < 0 || jtime < ktime) { 2324 k = j; 2325 ktime = jtime; 2326 } 2327 } 2328 if (k < 0) 2329 break; /* go on to next year */ 2330 rp = &zp->z_rules[k]; 2331 rp->r_todo = FALSE; 2332 if (useuntil && ktime >= untiltime) 2333 break; 2334 stdoff = rp->r_stdoff; 2335 if (usestart && ktime == starttime) 2336 usestart = FALSE; 2337 if (usestart) { 2338 if (ktime < starttime) { 2339 startoff = oadd(zp->z_gmtoff, 2340 stdoff); 2341 doabbr(startbuf, zp->z_format, 2342 rp->r_abbrvar, 2343 rp->r_stdoff != 0, 2344 FALSE); 2345 continue; 2346 } 2347 if (*startbuf == '\0' && 2348 startoff == oadd(zp->z_gmtoff, 2349 stdoff)) { 2350 doabbr(startbuf, 2351 zp->z_format, 2352 rp->r_abbrvar, 2353 rp->r_stdoff != 2354 0, 2355 FALSE); 2356 } 2357 } 2358#ifdef ICU 2359 if (year >= finalRuleYear && rp == finalRule1) { 2360 /* We want to shift final year 1 year after 2361 * the actual final rule takes effect (year + 1), 2362 * because the previous type is valid until the first 2363 * transition defined by the final rule. Otherwise 2364 * we may see unexpected offset shift at the 2365 * begining of the year when the final rule takes 2366 * effect. */ 2367 2368 /* ICU currently can support signed int32 transition 2369 * times. Thus, the transitions in year 2038 may be 2370 * truncated. At this moment (tzdata2008g), only 2371 * Rule Brazil is impacted by this limitation, because 2372 * the final set of rules are starting in 2038. Although 2373 * this code put the first couple of transitions populated 2374 * by the final rules, they will be dropped off when 2375 * collecting transition times. So, we need to keep 2376 * the start year of the final rule in 2038, not 2039. 2377 * Fortunately, the Brazil rules in 2038 and beyond use 2378 * the same base offset/dst saving amount. Thus, even 2379 * we skip the first couple of transitions, the final 2380 * rule set for 2038 works properly. So for now, 2381 * we do not increment the final rule start year only when 2382 * it falls into year 2038. We need to revisit this code 2383 * in future to fix the root cause of this problem (ICU 2384 * resource type limitation - signed int32). 2385 * Oct 7, 2008 - Yoshito */ 2386 int finalStartYear = (year == 2038) ? year : year + 1; 2387 emit_icu_zone(icuFile, 2388 zpfirst->z_name, zp->z_gmtoff, 2389 rp, finalRuleIndex, finalStartYear); 2390 /* only emit this for the first year */ 2391 finalRule1 = NULL; 2392 } 2393#endif 2394 eats(zp->z_filename, zp->z_linenum, 2395 rp->r_filename, rp->r_linenum); 2396 doabbr(ab, zp->z_format, rp->r_abbrvar, 2397 rp->r_stdoff != 0, FALSE); 2398 offset = oadd(zp->z_gmtoff, rp->r_stdoff); 2399#ifdef ICU 2400 type = addtype(offset, zp->z_gmtoff, rp->r_stdoff, 2401 ab, rp->r_stdoff != 0, 2402 rp->r_todisstd, rp->r_todisgmt); 2403#else 2404 type = addtype(offset, ab, rp->r_stdoff != 0, 2405 rp->r_todisstd, rp->r_todisgmt); 2406#endif 2407 addtt(ktime, type); 2408 } 2409 } 2410 if (usestart) { 2411 if (*startbuf == '\0' && 2412 zp->z_format != NULL && 2413 strchr(zp->z_format, '%') == NULL && 2414 strchr(zp->z_format, '/') == NULL) 2415 (void) strcpy(startbuf, zp->z_format); 2416 eat(zp->z_filename, zp->z_linenum); 2417 if (*startbuf == '\0') 2418error(_("can't determine time zone abbreviation to use just after until time")); 2419 else addtt(starttime, 2420#ifdef ICU 2421 addtype(startoff, 2422 zp->z_gmtoff, startoff - zp->z_gmtoff, 2423 startbuf, 2424 startoff != zp->z_gmtoff, 2425 startttisstd, 2426 startttisgmt)); 2427#else 2428 addtype(startoff, startbuf, 2429 startoff != zp->z_gmtoff, 2430 startttisstd, 2431 startttisgmt)); 2432#endif 2433 } 2434 /* 2435 ** Now we may get to set starttime for the next zone line. 2436 */ 2437 if (useuntil) { 2438 startttisstd = zp->z_untilrule.r_todisstd; 2439 startttisgmt = zp->z_untilrule.r_todisgmt; 2440 starttime = zp->z_untiltime; 2441 if (!startttisstd) 2442 starttime = tadd(starttime, -stdoff); 2443 if (!startttisgmt) 2444 starttime = tadd(starttime, -gmtoff); 2445 } 2446 } 2447 writezone(zpfirst->z_name, envvar); 2448 ifree(startbuf); 2449 ifree(ab); 2450 ifree(envvar); 2451} 2452 2453static void 2454addtt(starttime, type) 2455const zic_t starttime; 2456int type; 2457{ 2458 if (starttime <= min_time || 2459 (timecnt == 1 && attypes[0].at < min_time)) { 2460 gmtoffs[0] = gmtoffs[type]; 2461#ifdef ICU 2462 rawoffs[0] = rawoffs[type]; 2463 dstoffs[0] = dstoffs[type]; 2464#endif 2465 isdsts[0] = isdsts[type]; 2466 ttisstds[0] = ttisstds[type]; 2467 ttisgmts[0] = ttisgmts[type]; 2468 if (abbrinds[type] != 0) 2469 (void) strcpy(chars, &chars[abbrinds[type]]); 2470 abbrinds[0] = 0; 2471 charcnt = strlen(chars) + 1; 2472 typecnt = 1; 2473 timecnt = 0; 2474 type = 0; 2475 } 2476 if (timecnt >= TZ_MAX_TIMES) { 2477 error(_("too many transitions?!")); 2478 exit(EXIT_FAILURE); 2479 } 2480 attypes[timecnt].at = starttime; 2481 attypes[timecnt].type = type; 2482 ++timecnt; 2483} 2484 2485static int 2486#ifdef ICU 2487addtype(gmtoff, rawoff, dstoff, abbr, isdst, ttisstd, ttisgmt) 2488const long gmtoff; 2489const long rawoff; 2490const long dstoff; 2491#else 2492addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt) 2493const long gmtoff; 2494#endif 2495const char * const abbr; 2496const int isdst; 2497const int ttisstd; 2498const int ttisgmt; 2499{ 2500 register int i, j; 2501 2502 if (isdst != TRUE && isdst != FALSE) { 2503 error(_("internal error - addtype called with bad isdst")); 2504 exit(EXIT_FAILURE); 2505 } 2506 if (ttisstd != TRUE && ttisstd != FALSE) { 2507 error(_("internal error - addtype called with bad ttisstd")); 2508 exit(EXIT_FAILURE); 2509 } 2510 if (ttisgmt != TRUE && ttisgmt != FALSE) { 2511 error(_("internal error - addtype called with bad ttisgmt")); 2512 exit(EXIT_FAILURE); 2513 } 2514#ifdef ICU 2515 if (isdst != (dstoff != 0)) { 2516 error(_("internal error - addtype called with bad isdst/dstoff")); 2517 (void) exit(EXIT_FAILURE); 2518 } 2519 if (gmtoff != (rawoff + dstoff)) { 2520 error(_("internal error - addtype called with bad gmt/raw/dstoff")); 2521 (void) exit(EXIT_FAILURE); 2522 } 2523#endif 2524 /* 2525 ** See if there's already an entry for this zone type. 2526 ** If so, just return its index. 2527 */ 2528 for (i = 0; i < typecnt; ++i) { 2529 if (gmtoff == gmtoffs[i] && isdst == isdsts[i] && 2530#ifdef ICU 2531 rawoff == rawoffs[i] && dstoff == dstoffs[i] && 2532#endif 2533 strcmp(abbr, &chars[abbrinds[i]]) == 0 && 2534 ttisstd == ttisstds[i] && 2535 ttisgmt == ttisgmts[i]) 2536 return i; 2537 } 2538 /* 2539 ** There isn't one; add a new one, unless there are already too 2540 ** many. 2541 */ 2542 if (typecnt >= TZ_MAX_TYPES) { 2543 error(_("too many local time types")); 2544 exit(EXIT_FAILURE); 2545 } 2546 if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) { 2547 error(_("UTC offset out of range")); 2548 exit(EXIT_FAILURE); 2549 } 2550 gmtoffs[i] = gmtoff; 2551#ifdef ICU 2552 rawoffs[i] = rawoff; 2553 dstoffs[i] = dstoff; 2554#endif 2555 isdsts[i] = isdst; 2556 ttisstds[i] = ttisstd; 2557 ttisgmts[i] = ttisgmt; 2558 2559 for (j = 0; j < charcnt; ++j) 2560 if (strcmp(&chars[j], abbr) == 0) 2561 break; 2562 if (j == charcnt) 2563 newabbr(abbr); 2564 abbrinds[i] = j; 2565 ++typecnt; 2566 return i; 2567} 2568 2569static void 2570leapadd(t, positive, rolling, count) 2571const zic_t t; 2572const int positive; 2573const int rolling; 2574int count; 2575{ 2576 register int i, j; 2577 2578 if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { 2579 error(_("too many leap seconds")); 2580 exit(EXIT_FAILURE); 2581 } 2582 for (i = 0; i < leapcnt; ++i) 2583 if (t <= trans[i]) { 2584 if (t == trans[i]) { 2585 error(_("repeated leap second moment")); 2586 exit(EXIT_FAILURE); 2587 } 2588 break; 2589 } 2590 do { 2591 for (j = leapcnt; j > i; --j) { 2592 trans[j] = trans[j - 1]; 2593 corr[j] = corr[j - 1]; 2594 roll[j] = roll[j - 1]; 2595 } 2596 trans[i] = t; 2597 corr[i] = positive ? 1L : eitol(-count); 2598 roll[i] = rolling; 2599 ++leapcnt; 2600 } while (positive && --count != 0); 2601} 2602 2603static void 2604adjleap(void) 2605{ 2606 register int i; 2607 register long last = 0; 2608 2609 /* 2610 ** propagate leap seconds forward 2611 */ 2612 for (i = 0; i < leapcnt; ++i) { 2613 trans[i] = tadd(trans[i], last); 2614 last = corr[i] += last; 2615 } 2616} 2617 2618static int 2619yearistype(year, type) 2620const int year; 2621const char * const type; 2622{ 2623 static char * buf; 2624 int result; 2625 2626 if (type == NULL || *type == '\0') 2627 return TRUE; 2628 buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type))); 2629 (void) sprintf(buf, "%s %d %s", yitcommand, year, type); 2630 result = system(buf); 2631 if (WIFEXITED(result)) switch (WEXITSTATUS(result)) { 2632 case 0: 2633 return TRUE; 2634 case 1: 2635 return FALSE; 2636 } 2637 error(_("Wild result from command execution")); 2638 (void) fprintf(stderr, _("%s: command was '%s', result was %d\n"), 2639 progname, buf, result); 2640 for ( ; ; ) 2641 exit(EXIT_FAILURE); 2642} 2643 2644static int 2645lowerit(a) 2646int a; 2647{ 2648 a = (unsigned char) a; 2649 return (isascii(a) && isupper(a)) ? tolower(a) : a; 2650} 2651 2652static int 2653ciequal(ap, bp) /* case-insensitive equality */ 2654register const char * ap; 2655register const char * bp; 2656{ 2657 while (lowerit(*ap) == lowerit(*bp++)) 2658 if (*ap++ == '\0') 2659 return TRUE; 2660 return FALSE; 2661} 2662 2663static int 2664itsabbr(abbr, word) 2665register const char * abbr; 2666register const char * word; 2667{ 2668 if (lowerit(*abbr) != lowerit(*word)) 2669 return FALSE; 2670 ++word; 2671 while (*++abbr != '\0') 2672 do { 2673 if (*word == '\0') 2674 return FALSE; 2675 } while (lowerit(*word++) != lowerit(*abbr)); 2676 return TRUE; 2677} 2678 2679static const struct lookup * 2680byword(word, table) 2681register const char * const word; 2682register const struct lookup * const table; 2683{ 2684 register const struct lookup * foundlp; 2685 register const struct lookup * lp; 2686 2687 if (word == NULL || table == NULL) 2688 return NULL; 2689 /* 2690 ** Look for exact match. 2691 */ 2692 for (lp = table; lp->l_word != NULL; ++lp) 2693 if (ciequal(word, lp->l_word)) 2694 return lp; 2695 /* 2696 ** Look for inexact match. 2697 */ 2698 foundlp = NULL; 2699 for (lp = table; lp->l_word != NULL; ++lp) 2700 if (itsabbr(word, lp->l_word)) { 2701 if (foundlp == NULL) 2702 foundlp = lp; 2703 else return NULL; /* multiple inexact matches */ 2704 } 2705 return foundlp; 2706} 2707 2708static char ** 2709getfields(cp) 2710register char * cp; 2711{ 2712 register char * dp; 2713 register char ** array; 2714 register int nsubs; 2715 2716 if (cp == NULL) 2717 return NULL; 2718 array = (char **) (void *) 2719 emalloc((int) ((strlen(cp) + 1) * sizeof *array)); 2720 nsubs = 0; 2721 for ( ; ; ) { 2722 while (isascii((unsigned char) *cp) && 2723 isspace((unsigned char) *cp)) 2724 ++cp; 2725 if (*cp == '\0' || *cp == '#') 2726 break; 2727 array[nsubs++] = dp = cp; 2728 do { 2729 if ((*dp = *cp++) != '"') 2730 ++dp; 2731 else while ((*dp = *cp++) != '"') 2732 if (*dp != '\0') 2733 ++dp; 2734 else { 2735 error(_( 2736 "Odd number of quotation marks" 2737 )); 2738 exit(1); 2739 } 2740 } while (*cp != '\0' && *cp != '#' && 2741 (!isascii(*cp) || !isspace((unsigned char) *cp))); 2742 if (isascii(*cp) && isspace((unsigned char) *cp)) 2743 ++cp; 2744 *dp = '\0'; 2745 } 2746 array[nsubs] = NULL; 2747 return array; 2748} 2749 2750static long 2751oadd(t1, t2) 2752const long t1; 2753const long t2; 2754{ 2755 register long t; 2756 2757 t = t1 + t2; 2758 if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { 2759 error(_("time overflow")); 2760 exit(EXIT_FAILURE); 2761 } 2762 return t; 2763} 2764 2765static zic_t 2766tadd(t1, t2) 2767const zic_t t1; 2768const long t2; 2769{ 2770 register zic_t t; 2771 2772 if (t1 == max_time && t2 > 0) 2773 return max_time; 2774 if (t1 == min_time && t2 < 0) 2775 return min_time; 2776 t = t1 + t2; 2777 if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { 2778 error(_("time overflow")); 2779 exit(EXIT_FAILURE); 2780 } 2781 return t; 2782} 2783 2784/* 2785** Given a rule, and a year, compute the date - in seconds since January 1, 2786** 1970, 00:00 LOCAL time - in that year that the rule refers to. 2787*/ 2788 2789static zic_t 2790rpytime(rp, wantedy) 2791register const struct rule * const rp; 2792register const int wantedy; 2793{ 2794 register int y, m, i; 2795 register long dayoff; /* with a nod to Margaret O. */ 2796 register zic_t t; 2797 2798 if (wantedy == INT_MIN) 2799 return min_time; 2800 if (wantedy == INT_MAX) 2801 return max_time; 2802 dayoff = 0; 2803 m = TM_JANUARY; 2804 y = EPOCH_YEAR; 2805 while (wantedy != y) { 2806 if (wantedy > y) { 2807 i = len_years[isleap(y)]; 2808 ++y; 2809 } else { 2810 --y; 2811 i = -len_years[isleap(y)]; 2812 } 2813 dayoff = oadd(dayoff, eitol(i)); 2814 } 2815 while (m != rp->r_month) { 2816 i = len_months[isleap(y)][m]; 2817 dayoff = oadd(dayoff, eitol(i)); 2818 ++m; 2819 } 2820 i = rp->r_dayofmonth; 2821 if (m == TM_FEBRUARY && i == 29 && !isleap(y)) { 2822 if (rp->r_dycode == DC_DOWLEQ) 2823 --i; 2824 else { 2825 error(_("use of 2/29 in non leap-year")); 2826 exit(EXIT_FAILURE); 2827 } 2828 } 2829 --i; 2830 dayoff = oadd(dayoff, eitol(i)); 2831 if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) { 2832 register long wday; 2833 2834#define LDAYSPERWEEK ((long) DAYSPERWEEK) 2835 wday = eitol(EPOCH_WDAY); 2836 /* 2837 ** Don't trust mod of negative numbers. 2838 */ 2839 if (dayoff >= 0) 2840 wday = (wday + dayoff) % LDAYSPERWEEK; 2841 else { 2842 wday -= ((-dayoff) % LDAYSPERWEEK); 2843 if (wday < 0) 2844 wday += LDAYSPERWEEK; 2845 } 2846 while (wday != eitol(rp->r_wday)) 2847 if (rp->r_dycode == DC_DOWGEQ) { 2848 dayoff = oadd(dayoff, (long) 1); 2849 if (++wday >= LDAYSPERWEEK) 2850 wday = 0; 2851 ++i; 2852 } else { 2853 dayoff = oadd(dayoff, (long) -1); 2854 if (--wday < 0) 2855 wday = LDAYSPERWEEK - 1; 2856 --i; 2857 } 2858 if (i < 0 || i >= len_months[isleap(y)][m]) { 2859 if (noise) 2860 warning(_("rule goes past start/end of month--\ 2861will not work with pre-2004 versions of zic")); 2862 } 2863 } 2864 if (dayoff < min_time / SECSPERDAY) 2865 return min_time; 2866 if (dayoff > max_time / SECSPERDAY) 2867 return max_time; 2868 t = (zic_t) dayoff * SECSPERDAY; 2869 return tadd(t, rp->r_tod); 2870} 2871 2872static void 2873newabbr(string) 2874const char * const string; 2875{ 2876 register int i; 2877 2878 if (strcmp(string, GRANDPARENTED) != 0) { 2879 register const char * cp; 2880 register char * wp; 2881 2882 /* 2883 ** Want one to ZIC_MAX_ABBR_LEN_WO_WARN alphabetics 2884 ** optionally followed by a + or - and a number from 1 to 14. 2885 */ 2886 cp = string; 2887 wp = NULL; 2888 while (isascii((unsigned char) *cp) && 2889 isalpha((unsigned char) *cp)) 2890 ++cp; 2891 if (cp - string == 0) 2892wp = _("time zone abbreviation lacks alphabetic at start"); 2893 if (noise && cp - string > 3) 2894wp = _("time zone abbreviation has more than 3 alphabetics"); 2895 if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN) 2896wp = _("time zone abbreviation has too many alphabetics"); 2897 if (wp == NULL && (*cp == '+' || *cp == '-')) { 2898 ++cp; 2899 if (isascii((unsigned char) *cp) && 2900 isdigit((unsigned char) *cp)) 2901 if (*cp++ == '1' && 2902 *cp >= '0' && *cp <= '4') 2903 ++cp; 2904 } 2905 if (*cp != '\0') 2906wp = _("time zone abbreviation differs from POSIX standard"); 2907 if (wp != NULL) { 2908 wp = ecpyalloc(wp); 2909 wp = ecatalloc(wp, " ("); 2910 wp = ecatalloc(wp, string); 2911 wp = ecatalloc(wp, ")"); 2912 warning(wp); 2913 ifree(wp); 2914 } 2915 } 2916 i = strlen(string) + 1; 2917 if (charcnt + i > TZ_MAX_CHARS) { 2918 error(_("too many, or too long, time zone abbreviations")); 2919 exit(EXIT_FAILURE); 2920 } 2921 (void) strcpy(&chars[charcnt], string); 2922 charcnt += eitol(i); 2923} 2924 2925static int 2926mkdirs(argname) 2927char * argname; 2928{ 2929 register char * name; 2930 register char * cp; 2931 2932 if (argname == NULL || *argname == '\0') 2933 return 0; 2934 cp = name = ecpyalloc(argname); 2935 while ((cp = strchr(cp + 1, '/')) != 0) { 2936 *cp = '\0'; 2937#ifndef unix 2938 /* 2939 ** DOS drive specifier? 2940 */ 2941 if (isalpha((unsigned char) name[0]) && 2942 name[1] == ':' && name[2] == '\0') { 2943 *cp = '/'; 2944 continue; 2945 } 2946#endif /* !defined unix */ 2947 if (!itsdir(name)) { 2948 /* 2949 ** It doesn't seem to exist, so we try to create it. 2950 ** Creation may fail because of the directory being 2951 ** created by some other multiprocessor, so we get 2952 ** to do extra checking. 2953 */ 2954 if (mkdir(name, MKDIR_UMASK) != 0) { 2955 const char *e = strerror(errno); 2956 2957 if (errno != EEXIST || !itsdir(name)) { 2958 (void) fprintf(stderr, 2959_("%s: Can't create directory %s: %s\n"), 2960 progname, name, e); 2961 ifree(name); 2962 return -1; 2963 } 2964 } 2965 } 2966 *cp = '/'; 2967 } 2968 ifree(name); 2969 return 0; 2970} 2971 2972static long 2973eitol(i) 2974const int i; 2975{ 2976 long l; 2977 2978 l = i; 2979 if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) { 2980 (void) fprintf(stderr, 2981 _("%s: %d did not sign extend correctly\n"), 2982 progname, i); 2983 exit(EXIT_FAILURE); 2984 } 2985 return l; 2986} 2987 2988/* 2989** UNIX was a registered trademark of The Open Group in 2003. 2990*/ 2991