1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/tools/tzcode/zic.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3011 @@ 1.4 +/* 1.5 +** This file is in the public domain, so clarified as of 1.6 +** 2006-07-17 by Arthur David Olson. 1.7 +*/ 1.8 + 1.9 +static char elsieid[] = "@(#)zic.c 8.18"; 1.10 + 1.11 +#include "private.h" 1.12 +#include "locale.h" 1.13 +#include "tzfile.h" 1.14 + 1.15 +#define ZIC_VERSION '2' 1.16 + 1.17 +typedef int_fast64_t zic_t; 1.18 + 1.19 +#ifndef ZIC_MAX_ABBR_LEN_WO_WARN 1.20 +#define ZIC_MAX_ABBR_LEN_WO_WARN 6 1.21 +#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */ 1.22 + 1.23 +#if HAVE_SYS_STAT_H 1.24 +#include "sys/stat.h" 1.25 +#endif 1.26 +#ifdef S_IRUSR 1.27 +#define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 1.28 +#else 1.29 +#define MKDIR_UMASK 0755 1.30 +#endif 1.31 + 1.32 +/* Enable extensions and modifications for ICU. */ 1.33 +#define ICU 1.34 + 1.35 +/* Continue executing after link failure. Even if ICU is undefined 1.36 + * (for vanilla zic behavior), ICU_LINKS should be defined, since zic 1.37 + * appears to fail on the 2003 data the first time through during the 1.38 + * linking phase. Running zic twice, with ICU_LINKS defined, causes 1.39 + * links to be handled correctly. */ 1.40 +#define ICU_LINKS 1.41 + 1.42 +#ifdef ICU 1.43 +#include "tz2icu.h" 1.44 +#endif 1.45 + 1.46 +/* 1.47 +** On some ancient hosts, predicates like `isspace(C)' are defined 1.48 +** only if isascii(C) || C == EOF. Modern hosts obey the C Standard, 1.49 +** which says they are defined only if C == ((unsigned char) C) || C == EOF. 1.50 +** Neither the C Standard nor Posix require that `isascii' exist. 1.51 +** For portability, we check both ancient and modern requirements. 1.52 +** If isascii is not defined, the isascii check succeeds trivially. 1.53 +*/ 1.54 +#include "ctype.h" 1.55 +#ifndef isascii 1.56 +#define isascii(x) 1 1.57 +#endif 1.58 + 1.59 +#define OFFSET_STRLEN_MAXIMUM (7 + INT_STRLEN_MAXIMUM(long)) 1.60 +#define RULE_STRLEN_MAXIMUM 8 /* "Mdd.dd.d" */ 1.61 + 1.62 +#define end(cp) (strchr((cp), '\0')) 1.63 + 1.64 +struct rule { 1.65 + const char * r_filename; 1.66 + int r_linenum; 1.67 + const char * r_name; 1.68 + 1.69 + int r_loyear; /* for example, 1986 */ 1.70 + int r_hiyear; /* for example, 1986 */ 1.71 + const char * r_yrtype; 1.72 + int r_lowasnum; 1.73 + int r_hiwasnum; 1.74 + 1.75 + int r_month; /* 0..11 */ 1.76 + 1.77 + int r_dycode; /* see below */ 1.78 + int r_dayofmonth; 1.79 + int r_wday; 1.80 + 1.81 + long r_tod; /* time from midnight */ 1.82 + int r_todisstd; /* above is standard time if TRUE */ 1.83 + /* or wall clock time if FALSE */ 1.84 + int r_todisgmt; /* above is GMT if TRUE */ 1.85 + /* or local time if FALSE */ 1.86 + long r_stdoff; /* offset from standard time */ 1.87 + const char * r_abbrvar; /* variable part of abbreviation */ 1.88 + 1.89 + int r_todo; /* a rule to do (used in outzone) */ 1.90 + zic_t r_temp; /* used in outzone */ 1.91 +}; 1.92 + 1.93 +/* 1.94 +** r_dycode r_dayofmonth r_wday 1.95 +*/ 1.96 + 1.97 +#define DC_DOM 0 /* 1..31 */ /* unused */ 1.98 +#define DC_DOWGEQ 1 /* 1..31 */ /* 0..6 (Sun..Sat) */ 1.99 +#define DC_DOWLEQ 2 /* 1..31 */ /* 0..6 (Sun..Sat) */ 1.100 + 1.101 +struct zone { 1.102 + const char * z_filename; 1.103 + int z_linenum; 1.104 + 1.105 + const char * z_name; 1.106 + long z_gmtoff; 1.107 + const char * z_rule; 1.108 + const char * z_format; 1.109 + 1.110 + long z_stdoff; 1.111 + 1.112 + struct rule * z_rules; 1.113 + int z_nrules; 1.114 + 1.115 + struct rule z_untilrule; 1.116 + zic_t z_untiltime; 1.117 +}; 1.118 + 1.119 +extern int getopt(int argc, char * const argv[], 1.120 + const char * options); 1.121 +extern int link(const char * fromname, const char * toname); 1.122 +extern char * optarg; 1.123 +extern int optind; 1.124 + 1.125 +static void addtt(zic_t starttime, int type); 1.126 +#ifdef ICU 1.127 +static int addtype(long gmtoff, long rawoff, long dstoff, 1.128 + const char * abbr, int isdst, 1.129 + int ttisstd, int ttisgmt); 1.130 +#else 1.131 +static int addtype(long gmtoff, const char * abbr, int isdst, 1.132 + int ttisstd, int ttisgmt); 1.133 +#endif 1.134 +static void leapadd(zic_t t, int positive, int rolling, int count); 1.135 +static void adjleap(void); 1.136 +static void associate(void); 1.137 +static int ciequal(const char * ap, const char * bp); 1.138 +static void convert(long val, char * buf); 1.139 +static void convert64(zic_t val, char * buf); 1.140 +static void dolink(const char * fromfield, const char * tofield); 1.141 +static void doabbr(char * abbr, const char * format, 1.142 + const char * letters, int isdst, int doquotes); 1.143 +static void eat(const char * name, int num); 1.144 +static void eats(const char * name, int num, 1.145 + const char * rname, int rnum); 1.146 +static long eitol(int i); 1.147 +static void error(const char * message); 1.148 +static char ** getfields(char * buf); 1.149 +static long gethms(const char * string, const char * errstrng, 1.150 + int signable); 1.151 +static void infile(const char * filename); 1.152 +static void inleap(char ** fields, int nfields); 1.153 +static void inlink(char ** fields, int nfields); 1.154 +static void inrule(char ** fields, int nfields); 1.155 +static int inzcont(char ** fields, int nfields); 1.156 +static int inzone(char ** fields, int nfields); 1.157 +static int inzsub(char ** fields, int nfields, int iscont); 1.158 +static int is32(zic_t x); 1.159 +static int itsabbr(const char * abbr, const char * word); 1.160 +static int itsdir(const char * name); 1.161 +static int lowerit(int c); 1.162 +static char * memcheck(char * tocheck); 1.163 +static int mkdirs(char * filename); 1.164 +static void newabbr(const char * abbr); 1.165 +static long oadd(long t1, long t2); 1.166 +static void outzone(const struct zone * zp, int ntzones); 1.167 +static void puttzcode(long code, FILE * fp); 1.168 +static void puttzcode64(zic_t code, FILE * fp); 1.169 +static int rcomp(const void * leftp, const void * rightp); 1.170 +static zic_t rpytime(const struct rule * rp, int wantedy); 1.171 +static void rulesub(struct rule * rp, 1.172 + const char * loyearp, const char * hiyearp, 1.173 + const char * typep, const char * monthp, 1.174 + const char * dayp, const char * timep); 1.175 +static int stringoffset(char * result, long offset); 1.176 +static int stringrule(char * result, const struct rule * rp, 1.177 + long dstoff, long gmtoff); 1.178 +static void stringzone(char * result, 1.179 + const struct zone * zp, int ntzones); 1.180 +static void setboundaries(void); 1.181 +static zic_t tadd(zic_t t1, long t2); 1.182 +static void usage(FILE *stream, int status); 1.183 +static void writezone(const char * name, const char * string); 1.184 +static int yearistype(int year, const char * type); 1.185 +#ifdef ICU 1.186 +static void emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset, 1.187 + const struct rule* rule, 1.188 + int ruleIndex, int startYear); 1.189 +static void emit_icu_link(FILE* f, const char* from, const char* to); 1.190 +static void emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex); 1.191 +static int add_icu_final_rules(const struct rule* r1, const struct rule* r2); 1.192 +#endif 1.193 + 1.194 +static int charcnt; 1.195 +static int errors; 1.196 +static const char * filename; 1.197 +static int leapcnt; 1.198 +static int leapseen; 1.199 +static int leapminyear; 1.200 +static int leapmaxyear; 1.201 +static int linenum; 1.202 +static int max_abbrvar_len; 1.203 +static int max_format_len; 1.204 +static zic_t max_time; 1.205 +static int max_year; 1.206 +static zic_t min_time; 1.207 +static int min_year; 1.208 +static int noise; 1.209 +static const char * rfilename; 1.210 +static int rlinenum; 1.211 +static const char * progname; 1.212 +static int timecnt; 1.213 +static int typecnt; 1.214 + 1.215 +/* 1.216 +** Line codes. 1.217 +*/ 1.218 + 1.219 +#define LC_RULE 0 1.220 +#define LC_ZONE 1 1.221 +#define LC_LINK 2 1.222 +#define LC_LEAP 3 1.223 + 1.224 +/* 1.225 +** Which fields are which on a Zone line. 1.226 +*/ 1.227 + 1.228 +#define ZF_NAME 1 1.229 +#define ZF_GMTOFF 2 1.230 +#define ZF_RULE 3 1.231 +#define ZF_FORMAT 4 1.232 +#define ZF_TILYEAR 5 1.233 +#define ZF_TILMONTH 6 1.234 +#define ZF_TILDAY 7 1.235 +#define ZF_TILTIME 8 1.236 +#define ZONE_MINFIELDS 5 1.237 +#define ZONE_MAXFIELDS 9 1.238 + 1.239 +/* 1.240 +** Which fields are which on a Zone continuation line. 1.241 +*/ 1.242 + 1.243 +#define ZFC_GMTOFF 0 1.244 +#define ZFC_RULE 1 1.245 +#define ZFC_FORMAT 2 1.246 +#define ZFC_TILYEAR 3 1.247 +#define ZFC_TILMONTH 4 1.248 +#define ZFC_TILDAY 5 1.249 +#define ZFC_TILTIME 6 1.250 +#define ZONEC_MINFIELDS 3 1.251 +#define ZONEC_MAXFIELDS 7 1.252 + 1.253 +/* 1.254 +** Which files are which on a Rule line. 1.255 +*/ 1.256 + 1.257 +#define RF_NAME 1 1.258 +#define RF_LOYEAR 2 1.259 +#define RF_HIYEAR 3 1.260 +#define RF_COMMAND 4 1.261 +#define RF_MONTH 5 1.262 +#define RF_DAY 6 1.263 +#define RF_TOD 7 1.264 +#define RF_STDOFF 8 1.265 +#define RF_ABBRVAR 9 1.266 +#define RULE_FIELDS 10 1.267 + 1.268 +/* 1.269 +** Which fields are which on a Link line. 1.270 +*/ 1.271 + 1.272 +#define LF_FROM 1 1.273 +#define LF_TO 2 1.274 +#define LINK_FIELDS 3 1.275 + 1.276 +/* 1.277 +** Which fields are which on a Leap line. 1.278 +*/ 1.279 + 1.280 +#define LP_YEAR 1 1.281 +#define LP_MONTH 2 1.282 +#define LP_DAY 3 1.283 +#define LP_TIME 4 1.284 +#define LP_CORR 5 1.285 +#define LP_ROLL 6 1.286 +#define LEAP_FIELDS 7 1.287 + 1.288 +/* 1.289 +** Year synonyms. 1.290 +*/ 1.291 + 1.292 +#define YR_MINIMUM 0 1.293 +#define YR_MAXIMUM 1 1.294 +#define YR_ONLY 2 1.295 + 1.296 +static struct rule * rules; 1.297 +static int nrules; /* number of rules */ 1.298 + 1.299 +static struct zone * zones; 1.300 +static int nzones; /* number of zones */ 1.301 + 1.302 +struct link { 1.303 + const char * l_filename; 1.304 + int l_linenum; 1.305 + const char * l_from; 1.306 + const char * l_to; 1.307 +}; 1.308 + 1.309 +static struct link * links; 1.310 +static int nlinks; 1.311 + 1.312 +struct lookup { 1.313 + const char * l_word; 1.314 + const int l_value; 1.315 +}; 1.316 + 1.317 +#ifdef ICU 1.318 +/* Indices into rules[] for final rules. They will occur in pairs, 1.319 + * with finalRules[i] occurring before finalRules[i+1] in the year. 1.320 + * Each zone need only store a start year, a standard offset, and an 1.321 + * index into finalRules[]. FinalRules[] are aliases into rules[]. */ 1.322 +static const struct rule ** finalRules; 1.323 +static int finalRulesCount; 1.324 +#endif 1.325 + 1.326 +static struct lookup const * byword(const char * string, 1.327 + const struct lookup * lp); 1.328 + 1.329 +static struct lookup const line_codes[] = { 1.330 + { "Rule", LC_RULE }, 1.331 + { "Zone", LC_ZONE }, 1.332 + { "Link", LC_LINK }, 1.333 + { "Leap", LC_LEAP }, 1.334 + { NULL, 0} 1.335 +}; 1.336 + 1.337 +static struct lookup const mon_names[] = { 1.338 + { "January", TM_JANUARY }, 1.339 + { "February", TM_FEBRUARY }, 1.340 + { "March", TM_MARCH }, 1.341 + { "April", TM_APRIL }, 1.342 + { "May", TM_MAY }, 1.343 + { "June", TM_JUNE }, 1.344 + { "July", TM_JULY }, 1.345 + { "August", TM_AUGUST }, 1.346 + { "September", TM_SEPTEMBER }, 1.347 + { "October", TM_OCTOBER }, 1.348 + { "November", TM_NOVEMBER }, 1.349 + { "December", TM_DECEMBER }, 1.350 + { NULL, 0 } 1.351 +}; 1.352 + 1.353 +static struct lookup const wday_names[] = { 1.354 + { "Sunday", TM_SUNDAY }, 1.355 + { "Monday", TM_MONDAY }, 1.356 + { "Tuesday", TM_TUESDAY }, 1.357 + { "Wednesday", TM_WEDNESDAY }, 1.358 + { "Thursday", TM_THURSDAY }, 1.359 + { "Friday", TM_FRIDAY }, 1.360 + { "Saturday", TM_SATURDAY }, 1.361 + { NULL, 0 } 1.362 +}; 1.363 + 1.364 +static struct lookup const lasts[] = { 1.365 + { "last-Sunday", TM_SUNDAY }, 1.366 + { "last-Monday", TM_MONDAY }, 1.367 + { "last-Tuesday", TM_TUESDAY }, 1.368 + { "last-Wednesday", TM_WEDNESDAY }, 1.369 + { "last-Thursday", TM_THURSDAY }, 1.370 + { "last-Friday", TM_FRIDAY }, 1.371 + { "last-Saturday", TM_SATURDAY }, 1.372 + { NULL, 0 } 1.373 +}; 1.374 + 1.375 +static struct lookup const begin_years[] = { 1.376 + { "minimum", YR_MINIMUM }, 1.377 + { "maximum", YR_MAXIMUM }, 1.378 + { NULL, 0 } 1.379 +}; 1.380 + 1.381 +static struct lookup const end_years[] = { 1.382 + { "minimum", YR_MINIMUM }, 1.383 + { "maximum", YR_MAXIMUM }, 1.384 + { "only", YR_ONLY }, 1.385 + { NULL, 0 } 1.386 +}; 1.387 + 1.388 +static struct lookup const leap_types[] = { 1.389 + { "Rolling", TRUE }, 1.390 + { "Stationary", FALSE }, 1.391 + { NULL, 0 } 1.392 +}; 1.393 + 1.394 +static const int len_months[2][MONSPERYEAR] = { 1.395 + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 1.396 + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 1.397 +}; 1.398 + 1.399 +static const int len_years[2] = { 1.400 + DAYSPERNYEAR, DAYSPERLYEAR 1.401 +}; 1.402 + 1.403 +static struct attype { 1.404 + zic_t at; 1.405 + unsigned char type; 1.406 +} attypes[TZ_MAX_TIMES]; 1.407 +static long gmtoffs[TZ_MAX_TYPES]; 1.408 +#ifdef ICU 1.409 +/* gmtoffs[i] = rawoffs[i] + dstoffs[i] */ 1.410 +static long rawoffs[TZ_MAX_TYPES]; 1.411 +static long dstoffs[TZ_MAX_TYPES]; 1.412 +#endif 1.413 +static char isdsts[TZ_MAX_TYPES]; 1.414 +static unsigned char abbrinds[TZ_MAX_TYPES]; 1.415 +static char ttisstds[TZ_MAX_TYPES]; 1.416 +static char ttisgmts[TZ_MAX_TYPES]; 1.417 +static char chars[TZ_MAX_CHARS]; 1.418 +static zic_t trans[TZ_MAX_LEAPS]; 1.419 +static long corr[TZ_MAX_LEAPS]; 1.420 +static char roll[TZ_MAX_LEAPS]; 1.421 + 1.422 +/* 1.423 +** Memory allocation. 1.424 +*/ 1.425 + 1.426 +static char * 1.427 +memcheck(ptr) 1.428 +char * const ptr; 1.429 +{ 1.430 + if (ptr == NULL) { 1.431 + const char *e = strerror(errno); 1.432 + 1.433 + (void) fprintf(stderr, _("%s: Memory exhausted: %s\n"), 1.434 + progname, e); 1.435 + exit(EXIT_FAILURE); 1.436 + } 1.437 + return ptr; 1.438 +} 1.439 + 1.440 +#define emalloc(size) memcheck(imalloc(size)) 1.441 +#define erealloc(ptr, size) memcheck(irealloc((ptr), (size))) 1.442 +#define ecpyalloc(ptr) memcheck(icpyalloc(ptr)) 1.443 +#define ecatalloc(oldp, newp) memcheck(icatalloc((oldp), (newp))) 1.444 + 1.445 +/* 1.446 +** Error handling. 1.447 +*/ 1.448 + 1.449 +static void 1.450 +eats(name, num, rname, rnum) 1.451 +const char * const name; 1.452 +const int num; 1.453 +const char * const rname; 1.454 +const int rnum; 1.455 +{ 1.456 + filename = name; 1.457 + linenum = num; 1.458 + rfilename = rname; 1.459 + rlinenum = rnum; 1.460 +} 1.461 + 1.462 +static void 1.463 +eat(name, num) 1.464 +const char * const name; 1.465 +const int num; 1.466 +{ 1.467 + eats(name, num, (char *) NULL, -1); 1.468 +} 1.469 + 1.470 +static void 1.471 +error(string) 1.472 +const char * const string; 1.473 +{ 1.474 + /* 1.475 + ** Match the format of "cc" to allow sh users to 1.476 + ** zic ... 2>&1 | error -t "*" -v 1.477 + ** on BSD systems. 1.478 + */ 1.479 + (void) fprintf(stderr, _("\"%s\", line %d: %s"), 1.480 + filename, linenum, string); 1.481 + if (rfilename != NULL) 1.482 + (void) fprintf(stderr, _(" (rule from \"%s\", line %d)"), 1.483 + rfilename, rlinenum); 1.484 + (void) fprintf(stderr, "\n"); 1.485 + ++errors; 1.486 +} 1.487 + 1.488 +static void 1.489 +warning(string) 1.490 +const char * const string; 1.491 +{ 1.492 + char * cp; 1.493 + 1.494 + cp = ecpyalloc(_("warning: ")); 1.495 + cp = ecatalloc(cp, string); 1.496 + error(cp); 1.497 + ifree(cp); 1.498 + --errors; 1.499 +} 1.500 + 1.501 +static void 1.502 +usage(FILE *stream, int status) 1.503 +{ 1.504 + (void) fprintf(stream, _("%s: usage is %s \ 1.505 +[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\ 1.506 +\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\ 1.507 +\n\ 1.508 +Report bugs to tz@elsie.nci.nih.gov.\n"), 1.509 + progname, progname); 1.510 + exit(status); 1.511 +} 1.512 + 1.513 +#ifdef ICU 1.514 +/* File into which we will write supplemental ICU data. */ 1.515 +static FILE * icuFile; 1.516 + 1.517 +static void 1.518 +emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset, 1.519 + const struct rule* rule, 1.520 + int ruleIndex, int startYear) { 1.521 + /* machine-readable section */ 1.522 + fprintf(f, "zone %s %d %d %s", zoneName, zoneOffset, startYear, rule->r_name); 1.523 + 1.524 + /* human-readable section */ 1.525 + fprintf(f, " # zone %s, offset %d, year >= %d, rule %s (%d)\n", 1.526 + zoneName, zoneOffset, startYear, 1.527 + rule->r_name, ruleIndex); 1.528 +} 1.529 + 1.530 +static void 1.531 +emit_icu_link(FILE* f, const char* from, const char* to) { 1.532 + /* machine-readable section */ 1.533 + fprintf(f, "link %s %s\n", from, to); 1.534 +} 1.535 + 1.536 +static const char* DYCODE[] = {"DOM", "DOWGEQ", "DOWLEQ"}; 1.537 + 1.538 +static void 1.539 +emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex) { 1.540 + if (r->r_yrtype != NULL) { 1.541 + warning("year types not supported by ICU"); 1.542 + fprintf(stderr, "rule %s, file %s, line %d\n", 1.543 + r->r_name, r->r_filename, r->r_linenum); 1.544 + } 1.545 + 1.546 + /* machine-readable section */ 1.547 + fprintf(f, "rule %s %s %d %d %d %ld %d %d %ld", 1.548 + r->r_name, DYCODE[r->r_dycode], 1.549 + r->r_month, r->r_dayofmonth, 1.550 + (r->r_dycode == DC_DOM ? -1 : r->r_wday), 1.551 + r->r_tod, r->r_todisstd, r->r_todisgmt, r->r_stdoff 1.552 + ); 1.553 + 1.554 + /* human-readable section */ 1.555 + fprintf(f, " # %d: %s, file %s, line %d", 1.556 + ruleIndex, r->r_name, r->r_filename, r->r_linenum); 1.557 + fprintf(f, ", mode %s", DYCODE[r->r_dycode]); 1.558 + fprintf(f, ", %s, dom %d", mon_names[r->r_month].l_word, r->r_dayofmonth); 1.559 + if (r->r_dycode != DC_DOM) { 1.560 + fprintf(f, ", %s", wday_names[r->r_wday].l_word); 1.561 + } 1.562 + fprintf(f, ", time %ld", r->r_tod); 1.563 + fprintf(f, ", isstd %d", r->r_todisstd); 1.564 + fprintf(f, ", isgmt %d", r->r_todisgmt); 1.565 + fprintf(f, ", offset %ld", r->r_stdoff); 1.566 + fprintf(f, "\n"); 1.567 +} 1.568 + 1.569 +static int 1.570 +add_icu_final_rules(const struct rule* r1, const struct rule* r2) { 1.571 + int i; 1.572 + 1.573 + for (i=0; i<finalRulesCount; ++i) { /* i+=2 should work too */ 1.574 + if (r1==finalRules[i]) return i; /* [sic] pointer comparison */ 1.575 + } 1.576 + 1.577 + finalRules = (const struct rule**) (void*) erealloc((char *) finalRules, 1.578 + (finalRulesCount + 2) * sizeof(*finalRules)); 1.579 + finalRules[finalRulesCount++] = r1; 1.580 + finalRules[finalRulesCount++] = r2; 1.581 + return finalRulesCount - 2; 1.582 +} 1.583 +#endif 1.584 + 1.585 +static const char * psxrules; 1.586 +static const char * lcltime; 1.587 +static const char * directory; 1.588 +static const char * leapsec; 1.589 +static const char * yitcommand; 1.590 + 1.591 +int 1.592 +main(argc, argv) 1.593 +int argc; 1.594 +char * argv[]; 1.595 +{ 1.596 + register int i; 1.597 + register int j; 1.598 + register int c; 1.599 + 1.600 +#ifdef unix 1.601 + (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH)); 1.602 +#endif /* defined unix */ 1.603 +#if HAVE_GETTEXT 1.604 + (void) setlocale(LC_ALL, ""); 1.605 +#ifdef TZ_DOMAINDIR 1.606 + (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); 1.607 +#endif /* defined TEXTDOMAINDIR */ 1.608 + (void) textdomain(TZ_DOMAIN); 1.609 +#endif /* HAVE_GETTEXT */ 1.610 + progname = argv[0]; 1.611 + if (TYPE_BIT(zic_t) < 64) { 1.612 + (void) fprintf(stderr, "%s: %s\n", progname, 1.613 + _("wild compilation-time specification of zic_t")); 1.614 + exit(EXIT_FAILURE); 1.615 + } 1.616 + for (i = 1; i < argc; ++i) 1.617 + if (strcmp(argv[i], "--version") == 0) { 1.618 + (void) printf("%s\n", elsieid); 1.619 + exit(EXIT_SUCCESS); 1.620 + } else if (strcmp(argv[i], "--help") == 0) { 1.621 + usage(stdout, EXIT_SUCCESS); 1.622 + } 1.623 + while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1) 1.624 + switch (c) { 1.625 + default: 1.626 + usage(stderr, EXIT_FAILURE); 1.627 + case 'd': 1.628 + if (directory == NULL) 1.629 + directory = optarg; 1.630 + else { 1.631 + (void) fprintf(stderr, 1.632 +_("%s: More than one -d option specified\n"), 1.633 + progname); 1.634 + exit(EXIT_FAILURE); 1.635 + } 1.636 + break; 1.637 + case 'l': 1.638 + if (lcltime == NULL) 1.639 + lcltime = optarg; 1.640 + else { 1.641 + (void) fprintf(stderr, 1.642 +_("%s: More than one -l option specified\n"), 1.643 + progname); 1.644 + exit(EXIT_FAILURE); 1.645 + } 1.646 + break; 1.647 + case 'p': 1.648 + if (psxrules == NULL) 1.649 + psxrules = optarg; 1.650 + else { 1.651 + (void) fprintf(stderr, 1.652 +_("%s: More than one -p option specified\n"), 1.653 + progname); 1.654 + exit(EXIT_FAILURE); 1.655 + } 1.656 + break; 1.657 + case 'y': 1.658 + if (yitcommand == NULL) 1.659 + yitcommand = optarg; 1.660 + else { 1.661 + (void) fprintf(stderr, 1.662 +_("%s: More than one -y option specified\n"), 1.663 + progname); 1.664 + exit(EXIT_FAILURE); 1.665 + } 1.666 + break; 1.667 + case 'L': 1.668 + if (leapsec == NULL) 1.669 + leapsec = optarg; 1.670 + else { 1.671 + (void) fprintf(stderr, 1.672 +_("%s: More than one -L option specified\n"), 1.673 + progname); 1.674 + exit(EXIT_FAILURE); 1.675 + } 1.676 + break; 1.677 + case 'v': 1.678 + noise = TRUE; 1.679 + break; 1.680 + case 's': 1.681 + (void) printf("%s: -s ignored\n", progname); 1.682 + break; 1.683 + } 1.684 + if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) 1.685 + usage(stderr, EXIT_FAILURE); /* usage message by request */ 1.686 + if (directory == NULL) 1.687 + directory = TZDIR; 1.688 + if (yitcommand == NULL) 1.689 + yitcommand = "yearistype"; 1.690 + 1.691 + setboundaries(); 1.692 + 1.693 + if (optind < argc && leapsec != NULL) { 1.694 + infile(leapsec); 1.695 + adjleap(); 1.696 + } 1.697 + 1.698 +#ifdef ICU 1.699 + if ((icuFile = fopen(ICU_ZONE_FILE, "w")) == NULL) { 1.700 + const char *e = strerror(errno); 1.701 + (void) fprintf(stderr, _("%s: Can't open %s: %s\n"), 1.702 + progname, ICU_ZONE_FILE, e); 1.703 + (void) exit(EXIT_FAILURE); 1.704 + } 1.705 +#endif 1.706 + for (i = optind; i < argc; ++i) 1.707 + infile(argv[i]); 1.708 + if (errors) 1.709 + exit(EXIT_FAILURE); 1.710 + associate(); 1.711 + for (i = 0; i < nzones; i = j) { 1.712 + /* 1.713 + ** Find the next non-continuation zone entry. 1.714 + */ 1.715 + for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j) 1.716 + continue; 1.717 + outzone(&zones[i], j - i); 1.718 + } 1.719 + /* 1.720 + ** Make links. 1.721 + */ 1.722 + for (i = 0; i < nlinks; ++i) { 1.723 + eat(links[i].l_filename, links[i].l_linenum); 1.724 + dolink(links[i].l_from, links[i].l_to); 1.725 +#ifdef ICU 1.726 + emit_icu_link(icuFile, links[i].l_from, links[i].l_to); 1.727 +#endif 1.728 + if (noise) 1.729 + for (j = 0; j < nlinks; ++j) 1.730 + if (strcmp(links[i].l_to, 1.731 + links[j].l_from) == 0) 1.732 + warning(_("link to link")); 1.733 + } 1.734 + if (lcltime != NULL) { 1.735 + eat("command line", 1); 1.736 + dolink(lcltime, TZDEFAULT); 1.737 + } 1.738 + if (psxrules != NULL) { 1.739 + eat("command line", 1); 1.740 + dolink(psxrules, TZDEFRULES); 1.741 + } 1.742 +#ifdef ICU 1.743 + for (i=0; i<finalRulesCount; ++i) { 1.744 + emit_icu_rule(icuFile, finalRules[i], i); 1.745 + } 1.746 +#endif /*ICU*/ 1.747 + return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 1.748 +} 1.749 + 1.750 +static void 1.751 +dolink(fromfield, tofield) 1.752 +const char * const fromfield; 1.753 +const char * const tofield; 1.754 +{ 1.755 + register char * fromname; 1.756 + register char * toname; 1.757 + 1.758 + if (fromfield[0] == '/') 1.759 + fromname = ecpyalloc(fromfield); 1.760 + else { 1.761 + fromname = ecpyalloc(directory); 1.762 + fromname = ecatalloc(fromname, "/"); 1.763 + fromname = ecatalloc(fromname, fromfield); 1.764 + } 1.765 + if (tofield[0] == '/') 1.766 + toname = ecpyalloc(tofield); 1.767 + else { 1.768 + toname = ecpyalloc(directory); 1.769 + toname = ecatalloc(toname, "/"); 1.770 + toname = ecatalloc(toname, tofield); 1.771 + } 1.772 + /* 1.773 + ** We get to be careful here since 1.774 + ** there's a fair chance of root running us. 1.775 + */ 1.776 + if (!itsdir(toname)) 1.777 + (void) remove(toname); 1.778 + if (link(fromname, toname) != 0) { 1.779 + int result; 1.780 + 1.781 + if (mkdirs(toname) != 0) 1.782 + exit(EXIT_FAILURE); 1.783 + 1.784 + result = link(fromname, toname); 1.785 +#if HAVE_SYMLINK 1.786 + if (result != 0 && 1.787 + access(fromname, F_OK) == 0 && 1.788 + !itsdir(fromname)) { 1.789 + const char *s = tofield; 1.790 + register char * symlinkcontents = NULL; 1.791 + 1.792 + while ((s = strchr(s+1, '/')) != NULL) 1.793 + symlinkcontents = 1.794 + ecatalloc(symlinkcontents, 1.795 + "../"); 1.796 + symlinkcontents = 1.797 + ecatalloc(symlinkcontents, 1.798 + fromname); 1.799 + result = symlink(symlinkcontents, 1.800 + toname); 1.801 + if (result == 0) 1.802 +warning(_("hard link failed, symbolic link used")); 1.803 + ifree(symlinkcontents); 1.804 + } 1.805 +#endif /* HAVE_SYMLINK */ 1.806 + if (result != 0) { 1.807 + const char *e = strerror(errno); 1.808 + 1.809 + (void) fprintf(stderr, 1.810 + _("%s: Can't link from %s to %s: %s\n"), 1.811 + progname, fromname, toname, e); 1.812 +#ifndef ICU_LINKS 1.813 + exit(EXIT_FAILURE); 1.814 +#endif 1.815 + } 1.816 + } 1.817 + ifree(fromname); 1.818 + ifree(toname); 1.819 +} 1.820 + 1.821 +#define TIME_T_BITS_IN_FILE 64 1.822 + 1.823 +static void 1.824 +setboundaries(void) 1.825 +{ 1.826 + register int i; 1.827 + 1.828 + min_time = -1; 1.829 + for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i) 1.830 + min_time *= 2; 1.831 + max_time = -(min_time + 1); 1.832 +} 1.833 + 1.834 +static int 1.835 +itsdir(name) 1.836 +const char * const name; 1.837 +{ 1.838 + register char * myname; 1.839 + register int accres; 1.840 + 1.841 + myname = ecpyalloc(name); 1.842 + myname = ecatalloc(myname, "/."); 1.843 + accres = access(myname, F_OK); 1.844 + ifree(myname); 1.845 + return accres == 0; 1.846 +} 1.847 + 1.848 +/* 1.849 +** Associate sets of rules with zones. 1.850 +*/ 1.851 + 1.852 +/* 1.853 +** Sort by rule name. 1.854 +*/ 1.855 + 1.856 +static int 1.857 +rcomp(cp1, cp2) 1.858 +const void * cp1; 1.859 +const void * cp2; 1.860 +{ 1.861 + return strcmp(((const struct rule *) cp1)->r_name, 1.862 + ((const struct rule *) cp2)->r_name); 1.863 +} 1.864 + 1.865 +static void 1.866 +associate(void) 1.867 +{ 1.868 + register struct zone * zp; 1.869 + register struct rule * rp; 1.870 + register int base, out; 1.871 + register int i, j; 1.872 + 1.873 + if (nrules != 0) { 1.874 + (void) qsort((void *) rules, (size_t) nrules, 1.875 + (size_t) sizeof *rules, rcomp); 1.876 + for (i = 0; i < nrules - 1; ++i) { 1.877 + if (strcmp(rules[i].r_name, 1.878 + rules[i + 1].r_name) != 0) 1.879 + continue; 1.880 + if (strcmp(rules[i].r_filename, 1.881 + rules[i + 1].r_filename) == 0) 1.882 + continue; 1.883 + eat(rules[i].r_filename, rules[i].r_linenum); 1.884 + warning(_("same rule name in multiple files")); 1.885 + eat(rules[i + 1].r_filename, rules[i + 1].r_linenum); 1.886 + warning(_("same rule name in multiple files")); 1.887 + for (j = i + 2; j < nrules; ++j) { 1.888 + if (strcmp(rules[i].r_name, 1.889 + rules[j].r_name) != 0) 1.890 + break; 1.891 + if (strcmp(rules[i].r_filename, 1.892 + rules[j].r_filename) == 0) 1.893 + continue; 1.894 + if (strcmp(rules[i + 1].r_filename, 1.895 + rules[j].r_filename) == 0) 1.896 + continue; 1.897 + break; 1.898 + } 1.899 + i = j - 1; 1.900 + } 1.901 + } 1.902 + for (i = 0; i < nzones; ++i) { 1.903 + zp = &zones[i]; 1.904 + zp->z_rules = NULL; 1.905 + zp->z_nrules = 0; 1.906 + } 1.907 + for (base = 0; base < nrules; base = out) { 1.908 + rp = &rules[base]; 1.909 + for (out = base + 1; out < nrules; ++out) 1.910 + if (strcmp(rp->r_name, rules[out].r_name) != 0) 1.911 + break; 1.912 + for (i = 0; i < nzones; ++i) { 1.913 + zp = &zones[i]; 1.914 + if (strcmp(zp->z_rule, rp->r_name) != 0) 1.915 + continue; 1.916 + zp->z_rules = rp; 1.917 + zp->z_nrules = out - base; 1.918 + } 1.919 + } 1.920 + for (i = 0; i < nzones; ++i) { 1.921 + zp = &zones[i]; 1.922 + if (zp->z_nrules == 0) { 1.923 + /* 1.924 + ** Maybe we have a local standard time offset. 1.925 + */ 1.926 + eat(zp->z_filename, zp->z_linenum); 1.927 + zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"), 1.928 + TRUE); 1.929 + /* 1.930 + ** Note, though, that if there's no rule, 1.931 + ** a '%s' in the format is a bad thing. 1.932 + */ 1.933 + if (strchr(zp->z_format, '%') != 0) 1.934 + error(_("%s in ruleless zone")); 1.935 + } 1.936 + } 1.937 + if (errors) 1.938 + exit(EXIT_FAILURE); 1.939 +} 1.940 + 1.941 +static void 1.942 +infile(name) 1.943 +const char * name; 1.944 +{ 1.945 + register FILE * fp; 1.946 + register char ** fields; 1.947 + register char * cp; 1.948 + register const struct lookup * lp; 1.949 + register int nfields; 1.950 + register int wantcont; 1.951 + register int num; 1.952 + char buf[BUFSIZ]; 1.953 + 1.954 + if (strcmp(name, "-") == 0) { 1.955 + name = _("standard input"); 1.956 + fp = stdin; 1.957 + } else if ((fp = fopen(name, "r")) == NULL) { 1.958 + const char *e = strerror(errno); 1.959 + 1.960 + (void) fprintf(stderr, _("%s: Can't open %s: %s\n"), 1.961 + progname, name, e); 1.962 + exit(EXIT_FAILURE); 1.963 + } 1.964 + wantcont = FALSE; 1.965 + for (num = 1; ; ++num) { 1.966 + eat(name, num); 1.967 + if (fgets(buf, (int) sizeof buf, fp) != buf) 1.968 + break; 1.969 + cp = strchr(buf, '\n'); 1.970 + if (cp == NULL) { 1.971 + error(_("line too long")); 1.972 + exit(EXIT_FAILURE); 1.973 + } 1.974 + *cp = '\0'; 1.975 + fields = getfields(buf); 1.976 + nfields = 0; 1.977 + while (fields[nfields] != NULL) { 1.978 + static char nada; 1.979 + 1.980 + if (strcmp(fields[nfields], "-") == 0) 1.981 + fields[nfields] = &nada; 1.982 + ++nfields; 1.983 + } 1.984 + if (nfields == 0) { 1.985 + /* nothing to do */ 1.986 + } else if (wantcont) { 1.987 + wantcont = inzcont(fields, nfields); 1.988 + } else { 1.989 + lp = byword(fields[0], line_codes); 1.990 + if (lp == NULL) 1.991 + error(_("input line of unknown type")); 1.992 + else switch ((int) (lp->l_value)) { 1.993 + case LC_RULE: 1.994 + inrule(fields, nfields); 1.995 + wantcont = FALSE; 1.996 + break; 1.997 + case LC_ZONE: 1.998 + wantcont = inzone(fields, nfields); 1.999 + break; 1.1000 + case LC_LINK: 1.1001 + inlink(fields, nfields); 1.1002 + wantcont = FALSE; 1.1003 + break; 1.1004 + case LC_LEAP: 1.1005 + if (name != leapsec) 1.1006 + (void) fprintf(stderr, 1.1007 +_("%s: Leap line in non leap seconds file %s\n"), 1.1008 + progname, name); 1.1009 + else inleap(fields, nfields); 1.1010 + wantcont = FALSE; 1.1011 + break; 1.1012 + default: /* "cannot happen" */ 1.1013 + (void) fprintf(stderr, 1.1014 +_("%s: panic: Invalid l_value %d\n"), 1.1015 + progname, lp->l_value); 1.1016 + exit(EXIT_FAILURE); 1.1017 + } 1.1018 + } 1.1019 + ifree((char *) fields); 1.1020 + } 1.1021 + if (ferror(fp)) { 1.1022 + (void) fprintf(stderr, _("%s: Error reading %s\n"), 1.1023 + progname, filename); 1.1024 + exit(EXIT_FAILURE); 1.1025 + } 1.1026 + if (fp != stdin && fclose(fp)) { 1.1027 + const char *e = strerror(errno); 1.1028 + 1.1029 + (void) fprintf(stderr, _("%s: Error closing %s: %s\n"), 1.1030 + progname, filename, e); 1.1031 + exit(EXIT_FAILURE); 1.1032 + } 1.1033 + if (wantcont) 1.1034 + error(_("expected continuation line not found")); 1.1035 +} 1.1036 + 1.1037 +/* 1.1038 +** Convert a string of one of the forms 1.1039 +** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss 1.1040 +** into a number of seconds. 1.1041 +** A null string maps to zero. 1.1042 +** Call error with errstring and return zero on errors. 1.1043 +*/ 1.1044 + 1.1045 +static long 1.1046 +gethms(string, errstring, signable) 1.1047 +const char * string; 1.1048 +const char * const errstring; 1.1049 +const int signable; 1.1050 +{ 1.1051 + long hh; 1.1052 + int mm, ss, sign; 1.1053 + 1.1054 + if (string == NULL || *string == '\0') 1.1055 + return 0; 1.1056 + if (!signable) 1.1057 + sign = 1; 1.1058 + else if (*string == '-') { 1.1059 + sign = -1; 1.1060 + ++string; 1.1061 + } else sign = 1; 1.1062 + if (sscanf(string, scheck(string, "%ld"), &hh) == 1) 1.1063 + mm = ss = 0; 1.1064 + else if (sscanf(string, scheck(string, "%ld:%d"), &hh, &mm) == 2) 1.1065 + ss = 0; 1.1066 + else if (sscanf(string, scheck(string, "%ld:%d:%d"), 1.1067 + &hh, &mm, &ss) != 3) { 1.1068 + error(errstring); 1.1069 + return 0; 1.1070 + } 1.1071 + if (hh < 0 || 1.1072 + mm < 0 || mm >= MINSPERHOUR || 1.1073 + ss < 0 || ss > SECSPERMIN) { 1.1074 + error(errstring); 1.1075 + return 0; 1.1076 + } 1.1077 + if (LONG_MAX / SECSPERHOUR < hh) { 1.1078 + error(_("time overflow")); 1.1079 + return 0; 1.1080 + } 1.1081 + if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0) 1.1082 + warning(_("24:00 not handled by pre-1998 versions of zic")); 1.1083 + if (noise && (hh > HOURSPERDAY || 1.1084 + (hh == HOURSPERDAY && (mm != 0 || ss != 0)))) 1.1085 +warning(_("values over 24 hours not handled by pre-2007 versions of zic")); 1.1086 + return oadd(eitol(sign) * hh * eitol(SECSPERHOUR), 1.1087 + eitol(sign) * (eitol(mm) * eitol(SECSPERMIN) + eitol(ss))); 1.1088 +} 1.1089 + 1.1090 +static void 1.1091 +inrule(fields, nfields) 1.1092 +register char ** const fields; 1.1093 +const int nfields; 1.1094 +{ 1.1095 + static struct rule r; 1.1096 + 1.1097 + if (nfields != RULE_FIELDS) { 1.1098 + error(_("wrong number of fields on Rule line")); 1.1099 + return; 1.1100 + } 1.1101 + if (*fields[RF_NAME] == '\0') { 1.1102 + error(_("nameless rule")); 1.1103 + return; 1.1104 + } 1.1105 + r.r_filename = filename; 1.1106 + r.r_linenum = linenum; 1.1107 + r.r_stdoff = gethms(fields[RF_STDOFF], _("invalid saved time"), TRUE); 1.1108 + rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND], 1.1109 + fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); 1.1110 + r.r_name = ecpyalloc(fields[RF_NAME]); 1.1111 + r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); 1.1112 + if (max_abbrvar_len < strlen(r.r_abbrvar)) 1.1113 + max_abbrvar_len = strlen(r.r_abbrvar); 1.1114 + rules = (struct rule *) (void *) erealloc((char *) rules, 1.1115 + (int) ((nrules + 1) * sizeof *rules)); 1.1116 + rules[nrules++] = r; 1.1117 +} 1.1118 + 1.1119 +static int 1.1120 +inzone(fields, nfields) 1.1121 +register char ** const fields; 1.1122 +const int nfields; 1.1123 +{ 1.1124 + register int i; 1.1125 + static char * buf; 1.1126 + 1.1127 + if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) { 1.1128 + error(_("wrong number of fields on Zone line")); 1.1129 + return FALSE; 1.1130 + } 1.1131 + if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) { 1.1132 + buf = erealloc(buf, (int) (132 + strlen(TZDEFAULT))); 1.1133 + (void) sprintf(buf, 1.1134 +_("\"Zone %s\" line and -l option are mutually exclusive"), 1.1135 + TZDEFAULT); 1.1136 + error(buf); 1.1137 + return FALSE; 1.1138 + } 1.1139 + if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) { 1.1140 + buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES))); 1.1141 + (void) sprintf(buf, 1.1142 +_("\"Zone %s\" line and -p option are mutually exclusive"), 1.1143 + TZDEFRULES); 1.1144 + error(buf); 1.1145 + return FALSE; 1.1146 + } 1.1147 + for (i = 0; i < nzones; ++i) 1.1148 + if (zones[i].z_name != NULL && 1.1149 + strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) { 1.1150 + buf = erealloc(buf, (int) (132 + 1.1151 + strlen(fields[ZF_NAME]) + 1.1152 + strlen(zones[i].z_filename))); 1.1153 + (void) sprintf(buf, 1.1154 +_("duplicate zone name %s (file \"%s\", line %d)"), 1.1155 + fields[ZF_NAME], 1.1156 + zones[i].z_filename, 1.1157 + zones[i].z_linenum); 1.1158 + error(buf); 1.1159 + return FALSE; 1.1160 + } 1.1161 + return inzsub(fields, nfields, FALSE); 1.1162 +} 1.1163 + 1.1164 +static int 1.1165 +inzcont(fields, nfields) 1.1166 +register char ** const fields; 1.1167 +const int nfields; 1.1168 +{ 1.1169 + if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) { 1.1170 + error(_("wrong number of fields on Zone continuation line")); 1.1171 + return FALSE; 1.1172 + } 1.1173 + return inzsub(fields, nfields, TRUE); 1.1174 +} 1.1175 + 1.1176 +static int 1.1177 +inzsub(fields, nfields, iscont) 1.1178 +register char ** const fields; 1.1179 +const int nfields; 1.1180 +const int iscont; 1.1181 +{ 1.1182 + register char * cp; 1.1183 + static struct zone z; 1.1184 + register int i_gmtoff, i_rule, i_format; 1.1185 + register int i_untilyear, i_untilmonth; 1.1186 + register int i_untilday, i_untiltime; 1.1187 + register int hasuntil; 1.1188 + 1.1189 + if (iscont) { 1.1190 + i_gmtoff = ZFC_GMTOFF; 1.1191 + i_rule = ZFC_RULE; 1.1192 + i_format = ZFC_FORMAT; 1.1193 + i_untilyear = ZFC_TILYEAR; 1.1194 + i_untilmonth = ZFC_TILMONTH; 1.1195 + i_untilday = ZFC_TILDAY; 1.1196 + i_untiltime = ZFC_TILTIME; 1.1197 + z.z_name = NULL; 1.1198 + } else { 1.1199 + i_gmtoff = ZF_GMTOFF; 1.1200 + i_rule = ZF_RULE; 1.1201 + i_format = ZF_FORMAT; 1.1202 + i_untilyear = ZF_TILYEAR; 1.1203 + i_untilmonth = ZF_TILMONTH; 1.1204 + i_untilday = ZF_TILDAY; 1.1205 + i_untiltime = ZF_TILTIME; 1.1206 + z.z_name = ecpyalloc(fields[ZF_NAME]); 1.1207 + } 1.1208 + z.z_filename = filename; 1.1209 + z.z_linenum = linenum; 1.1210 + z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UTC offset"), TRUE); 1.1211 + if ((cp = strchr(fields[i_format], '%')) != 0) { 1.1212 + if (*++cp != 's' || strchr(cp, '%') != 0) { 1.1213 + error(_("invalid abbreviation format")); 1.1214 + return FALSE; 1.1215 + } 1.1216 + } 1.1217 + z.z_rule = ecpyalloc(fields[i_rule]); 1.1218 + z.z_format = ecpyalloc(fields[i_format]); 1.1219 + if (max_format_len < strlen(z.z_format)) 1.1220 + max_format_len = strlen(z.z_format); 1.1221 + hasuntil = nfields > i_untilyear; 1.1222 + if (hasuntil) { 1.1223 + z.z_untilrule.r_filename = filename; 1.1224 + z.z_untilrule.r_linenum = linenum; 1.1225 + rulesub(&z.z_untilrule, 1.1226 + fields[i_untilyear], 1.1227 + "only", 1.1228 + "", 1.1229 + (nfields > i_untilmonth) ? 1.1230 + fields[i_untilmonth] : "Jan", 1.1231 + (nfields > i_untilday) ? fields[i_untilday] : "1", 1.1232 + (nfields > i_untiltime) ? fields[i_untiltime] : "0"); 1.1233 + z.z_untiltime = rpytime(&z.z_untilrule, 1.1234 + z.z_untilrule.r_loyear); 1.1235 + if (iscont && nzones > 0 && 1.1236 + z.z_untiltime > min_time && 1.1237 + z.z_untiltime < max_time && 1.1238 + zones[nzones - 1].z_untiltime > min_time && 1.1239 + zones[nzones - 1].z_untiltime < max_time && 1.1240 + zones[nzones - 1].z_untiltime >= z.z_untiltime) { 1.1241 + error(_( 1.1242 +"Zone continuation line end time is not after end time of previous line" 1.1243 + )); 1.1244 + return FALSE; 1.1245 + } 1.1246 + } 1.1247 + zones = (struct zone *) (void *) erealloc((char *) zones, 1.1248 + (int) ((nzones + 1) * sizeof *zones)); 1.1249 + zones[nzones++] = z; 1.1250 + /* 1.1251 + ** If there was an UNTIL field on this line, 1.1252 + ** there's more information about the zone on the next line. 1.1253 + */ 1.1254 + return hasuntil; 1.1255 +} 1.1256 + 1.1257 +static void 1.1258 +inleap(fields, nfields) 1.1259 +register char ** const fields; 1.1260 +const int nfields; 1.1261 +{ 1.1262 + register const char * cp; 1.1263 + register const struct lookup * lp; 1.1264 + register int i, j; 1.1265 + int year, month, day; 1.1266 + long dayoff, tod; 1.1267 + zic_t t; 1.1268 + 1.1269 + if (nfields != LEAP_FIELDS) { 1.1270 + error(_("wrong number of fields on Leap line")); 1.1271 + return; 1.1272 + } 1.1273 + dayoff = 0; 1.1274 + cp = fields[LP_YEAR]; 1.1275 + if (sscanf(cp, scheck(cp, "%d"), &year) != 1) { 1.1276 + /* 1.1277 + ** Leapin' Lizards! 1.1278 + */ 1.1279 + error(_("invalid leaping year")); 1.1280 + return; 1.1281 + } 1.1282 + if (!leapseen || leapmaxyear < year) 1.1283 + leapmaxyear = year; 1.1284 + if (!leapseen || leapminyear > year) 1.1285 + leapminyear = year; 1.1286 + leapseen = TRUE; 1.1287 + j = EPOCH_YEAR; 1.1288 + while (j != year) { 1.1289 + if (year > j) { 1.1290 + i = len_years[isleap(j)]; 1.1291 + ++j; 1.1292 + } else { 1.1293 + --j; 1.1294 + i = -len_years[isleap(j)]; 1.1295 + } 1.1296 + dayoff = oadd(dayoff, eitol(i)); 1.1297 + } 1.1298 + if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) { 1.1299 + error(_("invalid month name")); 1.1300 + return; 1.1301 + } 1.1302 + month = lp->l_value; 1.1303 + j = TM_JANUARY; 1.1304 + while (j != month) { 1.1305 + i = len_months[isleap(year)][j]; 1.1306 + dayoff = oadd(dayoff, eitol(i)); 1.1307 + ++j; 1.1308 + } 1.1309 + cp = fields[LP_DAY]; 1.1310 + if (sscanf(cp, scheck(cp, "%d"), &day) != 1 || 1.1311 + day <= 0 || day > len_months[isleap(year)][month]) { 1.1312 + error(_("invalid day of month")); 1.1313 + return; 1.1314 + } 1.1315 + dayoff = oadd(dayoff, eitol(day - 1)); 1.1316 + if (dayoff < 0 && !TYPE_SIGNED(zic_t)) { 1.1317 + error(_("time before zero")); 1.1318 + return; 1.1319 + } 1.1320 + if (dayoff < min_time / SECSPERDAY) { 1.1321 + error(_("time too small")); 1.1322 + return; 1.1323 + } 1.1324 + if (dayoff > max_time / SECSPERDAY) { 1.1325 + error(_("time too large")); 1.1326 + return; 1.1327 + } 1.1328 + t = (zic_t) dayoff * SECSPERDAY; 1.1329 + tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE); 1.1330 + cp = fields[LP_CORR]; 1.1331 + { 1.1332 + register int positive; 1.1333 + int count; 1.1334 + 1.1335 + if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */ 1.1336 + positive = FALSE; 1.1337 + count = 1; 1.1338 + } else if (strcmp(cp, "--") == 0) { 1.1339 + positive = FALSE; 1.1340 + count = 2; 1.1341 + } else if (strcmp(cp, "+") == 0) { 1.1342 + positive = TRUE; 1.1343 + count = 1; 1.1344 + } else if (strcmp(cp, "++") == 0) { 1.1345 + positive = TRUE; 1.1346 + count = 2; 1.1347 + } else { 1.1348 + error(_("illegal CORRECTION field on Leap line")); 1.1349 + return; 1.1350 + } 1.1351 + if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) { 1.1352 + error(_( 1.1353 + "illegal Rolling/Stationary field on Leap line" 1.1354 + )); 1.1355 + return; 1.1356 + } 1.1357 + leapadd(tadd(t, tod), positive, lp->l_value, count); 1.1358 + } 1.1359 +} 1.1360 + 1.1361 +static void 1.1362 +inlink(fields, nfields) 1.1363 +register char ** const fields; 1.1364 +const int nfields; 1.1365 +{ 1.1366 + struct link l; 1.1367 + 1.1368 + if (nfields != LINK_FIELDS) { 1.1369 + error(_("wrong number of fields on Link line")); 1.1370 + return; 1.1371 + } 1.1372 + if (*fields[LF_FROM] == '\0') { 1.1373 + error(_("blank FROM field on Link line")); 1.1374 + return; 1.1375 + } 1.1376 + if (*fields[LF_TO] == '\0') { 1.1377 + error(_("blank TO field on Link line")); 1.1378 + return; 1.1379 + } 1.1380 + l.l_filename = filename; 1.1381 + l.l_linenum = linenum; 1.1382 + l.l_from = ecpyalloc(fields[LF_FROM]); 1.1383 + l.l_to = ecpyalloc(fields[LF_TO]); 1.1384 + links = (struct link *) (void *) erealloc((char *) links, 1.1385 + (int) ((nlinks + 1) * sizeof *links)); 1.1386 + links[nlinks++] = l; 1.1387 +} 1.1388 + 1.1389 +static void 1.1390 +rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep) 1.1391 +register struct rule * const rp; 1.1392 +const char * const loyearp; 1.1393 +const char * const hiyearp; 1.1394 +const char * const typep; 1.1395 +const char * const monthp; 1.1396 +const char * const dayp; 1.1397 +const char * const timep; 1.1398 +{ 1.1399 + register const struct lookup * lp; 1.1400 + register const char * cp; 1.1401 + register char * dp; 1.1402 + register char * ep; 1.1403 + 1.1404 + if ((lp = byword(monthp, mon_names)) == NULL) { 1.1405 + error(_("invalid month name")); 1.1406 + return; 1.1407 + } 1.1408 + rp->r_month = lp->l_value; 1.1409 + rp->r_todisstd = FALSE; 1.1410 + rp->r_todisgmt = FALSE; 1.1411 + dp = ecpyalloc(timep); 1.1412 + if (*dp != '\0') { 1.1413 + ep = dp + strlen(dp) - 1; 1.1414 + switch (lowerit(*ep)) { 1.1415 + case 's': /* Standard */ 1.1416 + rp->r_todisstd = TRUE; 1.1417 + rp->r_todisgmt = FALSE; 1.1418 + *ep = '\0'; 1.1419 + break; 1.1420 + case 'w': /* Wall */ 1.1421 + rp->r_todisstd = FALSE; 1.1422 + rp->r_todisgmt = FALSE; 1.1423 + *ep = '\0'; 1.1424 + break; 1.1425 + case 'g': /* Greenwich */ 1.1426 + case 'u': /* Universal */ 1.1427 + case 'z': /* Zulu */ 1.1428 + rp->r_todisstd = TRUE; 1.1429 + rp->r_todisgmt = TRUE; 1.1430 + *ep = '\0'; 1.1431 + break; 1.1432 + } 1.1433 + } 1.1434 + rp->r_tod = gethms(dp, _("invalid time of day"), FALSE); 1.1435 + ifree(dp); 1.1436 + /* 1.1437 + ** Year work. 1.1438 + */ 1.1439 + cp = loyearp; 1.1440 + lp = byword(cp, begin_years); 1.1441 + rp->r_lowasnum = lp == NULL; 1.1442 + if (!rp->r_lowasnum) switch ((int) lp->l_value) { 1.1443 + case YR_MINIMUM: 1.1444 + rp->r_loyear = INT_MIN; 1.1445 + break; 1.1446 + case YR_MAXIMUM: 1.1447 + rp->r_loyear = INT_MAX; 1.1448 + break; 1.1449 + default: /* "cannot happen" */ 1.1450 + (void) fprintf(stderr, 1.1451 + _("%s: panic: Invalid l_value %d\n"), 1.1452 + progname, lp->l_value); 1.1453 + exit(EXIT_FAILURE); 1.1454 + } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) { 1.1455 + error(_("invalid starting year")); 1.1456 + return; 1.1457 + } 1.1458 + cp = hiyearp; 1.1459 + lp = byword(cp, end_years); 1.1460 + rp->r_hiwasnum = lp == NULL; 1.1461 + if (!rp->r_hiwasnum) switch ((int) lp->l_value) { 1.1462 + case YR_MINIMUM: 1.1463 + rp->r_hiyear = INT_MIN; 1.1464 + break; 1.1465 + case YR_MAXIMUM: 1.1466 + rp->r_hiyear = INT_MAX; 1.1467 + break; 1.1468 + case YR_ONLY: 1.1469 + rp->r_hiyear = rp->r_loyear; 1.1470 + break; 1.1471 + default: /* "cannot happen" */ 1.1472 + (void) fprintf(stderr, 1.1473 + _("%s: panic: Invalid l_value %d\n"), 1.1474 + progname, lp->l_value); 1.1475 + exit(EXIT_FAILURE); 1.1476 + } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) { 1.1477 + error(_("invalid ending year")); 1.1478 + return; 1.1479 + } 1.1480 + if (rp->r_loyear > rp->r_hiyear) { 1.1481 + error(_("starting year greater than ending year")); 1.1482 + return; 1.1483 + } 1.1484 + if (*typep == '\0') 1.1485 + rp->r_yrtype = NULL; 1.1486 + else { 1.1487 + if (rp->r_loyear == rp->r_hiyear) { 1.1488 + error(_("typed single year")); 1.1489 + return; 1.1490 + } 1.1491 + rp->r_yrtype = ecpyalloc(typep); 1.1492 + } 1.1493 + /* 1.1494 + ** Day work. 1.1495 + ** Accept things such as: 1.1496 + ** 1 1.1497 + ** last-Sunday 1.1498 + ** Sun<=20 1.1499 + ** Sun>=7 1.1500 + */ 1.1501 + dp = ecpyalloc(dayp); 1.1502 + if ((lp = byword(dp, lasts)) != NULL) { 1.1503 + rp->r_dycode = DC_DOWLEQ; 1.1504 + rp->r_wday = lp->l_value; 1.1505 + rp->r_dayofmonth = len_months[1][rp->r_month]; 1.1506 + } else { 1.1507 + if ((ep = strchr(dp, '<')) != 0) 1.1508 + rp->r_dycode = DC_DOWLEQ; 1.1509 + else if ((ep = strchr(dp, '>')) != 0) 1.1510 + rp->r_dycode = DC_DOWGEQ; 1.1511 + else { 1.1512 + ep = dp; 1.1513 + rp->r_dycode = DC_DOM; 1.1514 + } 1.1515 + if (rp->r_dycode != DC_DOM) { 1.1516 + *ep++ = 0; 1.1517 + if (*ep++ != '=') { 1.1518 + error(_("invalid day of month")); 1.1519 + ifree(dp); 1.1520 + return; 1.1521 + } 1.1522 + if ((lp = byword(dp, wday_names)) == NULL) { 1.1523 + error(_("invalid weekday name")); 1.1524 + ifree(dp); 1.1525 + return; 1.1526 + } 1.1527 + rp->r_wday = lp->l_value; 1.1528 + } 1.1529 + if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 || 1.1530 + rp->r_dayofmonth <= 0 || 1.1531 + (rp->r_dayofmonth > len_months[1][rp->r_month])) { 1.1532 + error(_("invalid day of month")); 1.1533 + ifree(dp); 1.1534 + return; 1.1535 + } 1.1536 + } 1.1537 + ifree(dp); 1.1538 +} 1.1539 + 1.1540 +static void 1.1541 +convert(val, buf) 1.1542 +const long val; 1.1543 +char * const buf; 1.1544 +{ 1.1545 + register int i; 1.1546 + register int shift; 1.1547 + 1.1548 + for (i = 0, shift = 24; i < 4; ++i, shift -= 8) 1.1549 + buf[i] = val >> shift; 1.1550 +} 1.1551 + 1.1552 +static void 1.1553 +convert64(val, buf) 1.1554 +const zic_t val; 1.1555 +char * const buf; 1.1556 +{ 1.1557 + register int i; 1.1558 + register int shift; 1.1559 + 1.1560 + for (i = 0, shift = 56; i < 8; ++i, shift -= 8) 1.1561 + buf[i] = val >> shift; 1.1562 +} 1.1563 + 1.1564 +static void 1.1565 +puttzcode(val, fp) 1.1566 +const long val; 1.1567 +FILE * const fp; 1.1568 +{ 1.1569 + char buf[4]; 1.1570 + 1.1571 + convert(val, buf); 1.1572 + (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); 1.1573 +} 1.1574 + 1.1575 +static void 1.1576 +puttzcode64(val, fp) 1.1577 +const zic_t val; 1.1578 +FILE * const fp; 1.1579 +{ 1.1580 + char buf[8]; 1.1581 + 1.1582 + convert64(val, buf); 1.1583 + (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); 1.1584 +} 1.1585 + 1.1586 +static int 1.1587 +atcomp(avp, bvp) 1.1588 +const void * avp; 1.1589 +const void * bvp; 1.1590 +{ 1.1591 + const zic_t a = ((const struct attype *) avp)->at; 1.1592 + const zic_t b = ((const struct attype *) bvp)->at; 1.1593 + 1.1594 + return (a < b) ? -1 : (a > b); 1.1595 +} 1.1596 + 1.1597 +static int 1.1598 +is32(x) 1.1599 +const zic_t x; 1.1600 +{ 1.1601 + return INT32_MIN <= x && x <= INT32_MAX; 1.1602 +} 1.1603 + 1.1604 +static void 1.1605 +writezone(name, string) 1.1606 +const char * const name; 1.1607 +const char * const string; 1.1608 +{ 1.1609 + register FILE * fp; 1.1610 + register int i, j; 1.1611 + register int leapcnt32, leapi32; 1.1612 + register int timecnt32, timei32; 1.1613 + register int pass; 1.1614 + static char * fullname; 1.1615 + static const struct tzhead tzh0; 1.1616 + static struct tzhead tzh; 1.1617 + zic_t ats[TZ_MAX_TIMES]; 1.1618 + unsigned char types[TZ_MAX_TIMES]; 1.1619 + 1.1620 + /* 1.1621 + ** Sort. 1.1622 + */ 1.1623 + if (timecnt > 1) 1.1624 + (void) qsort((void *) attypes, (size_t) timecnt, 1.1625 + (size_t) sizeof *attypes, atcomp); 1.1626 + /* 1.1627 + ** Optimize. 1.1628 + */ 1.1629 + { 1.1630 + int fromi; 1.1631 + int toi; 1.1632 + 1.1633 + toi = 0; 1.1634 + fromi = 0; 1.1635 + while (fromi < timecnt && attypes[fromi].at < min_time) 1.1636 + ++fromi; 1.1637 + if (isdsts[0] == 0) 1.1638 + while (fromi < timecnt && attypes[fromi].type == 0) 1.1639 + ++fromi; /* handled by default rule */ 1.1640 + for ( ; fromi < timecnt; ++fromi) { 1.1641 + if (toi != 0 && ((attypes[fromi].at + 1.1642 + gmtoffs[attypes[toi - 1].type]) <= 1.1643 + (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0 1.1644 + : attypes[toi - 2].type]))) { 1.1645 + attypes[toi - 1].type = 1.1646 + attypes[fromi].type; 1.1647 + continue; 1.1648 + } 1.1649 + if (toi == 0 || 1.1650 + attypes[toi - 1].type != attypes[fromi].type) 1.1651 + attypes[toi++] = attypes[fromi]; 1.1652 + } 1.1653 + timecnt = toi; 1.1654 + } 1.1655 + /* 1.1656 + ** Transfer. 1.1657 + */ 1.1658 + for (i = 0; i < timecnt; ++i) { 1.1659 + ats[i] = attypes[i].at; 1.1660 + types[i] = attypes[i].type; 1.1661 + } 1.1662 + /* 1.1663 + ** Correct for leap seconds. 1.1664 + */ 1.1665 + for (i = 0; i < timecnt; ++i) { 1.1666 + j = leapcnt; 1.1667 + while (--j >= 0) 1.1668 + if (ats[i] > trans[j] - corr[j]) { 1.1669 + ats[i] = tadd(ats[i], corr[j]); 1.1670 + break; 1.1671 + } 1.1672 + } 1.1673 + /* 1.1674 + ** Figure out 32-bit-limited starts and counts. 1.1675 + */ 1.1676 + timecnt32 = timecnt; 1.1677 + timei32 = 0; 1.1678 + leapcnt32 = leapcnt; 1.1679 + leapi32 = 0; 1.1680 + while (timecnt32 > 0 && !is32(ats[timecnt32 - 1])) 1.1681 + --timecnt32; 1.1682 + while (timecnt32 > 0 && !is32(ats[timei32])) { 1.1683 + --timecnt32; 1.1684 + ++timei32; 1.1685 + } 1.1686 + while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1])) 1.1687 + --leapcnt32; 1.1688 + while (leapcnt32 > 0 && !is32(trans[leapi32])) { 1.1689 + --leapcnt32; 1.1690 + ++leapi32; 1.1691 + } 1.1692 + fullname = erealloc(fullname, 1.1693 + (int) (strlen(directory) + 1 + strlen(name) + 1)); 1.1694 + (void) sprintf(fullname, "%s/%s", directory, name); 1.1695 + /* 1.1696 + ** Remove old file, if any, to snap links. 1.1697 + */ 1.1698 + if (!itsdir(fullname) && remove(fullname) != 0 && errno != ENOENT) { 1.1699 + const char *e = strerror(errno); 1.1700 + 1.1701 + (void) fprintf(stderr, _("%s: Can't remove %s: %s\n"), 1.1702 + progname, fullname, e); 1.1703 + exit(EXIT_FAILURE); 1.1704 + } 1.1705 + if ((fp = fopen(fullname, "wb")) == NULL) { 1.1706 + if (mkdirs(fullname) != 0) 1.1707 + exit(EXIT_FAILURE); 1.1708 + if ((fp = fopen(fullname, "wb")) == NULL) { 1.1709 + const char *e = strerror(errno); 1.1710 + 1.1711 + (void) fprintf(stderr, _("%s: Can't create %s: %s\n"), 1.1712 + progname, fullname, e); 1.1713 + exit(EXIT_FAILURE); 1.1714 + } 1.1715 + } 1.1716 + for (pass = 1; pass <= 2; ++pass) { 1.1717 + register int thistimei, thistimecnt; 1.1718 + register int thisleapi, thisleapcnt; 1.1719 + register int thistimelim, thisleaplim; 1.1720 + int writetype[TZ_MAX_TIMES]; 1.1721 + int typemap[TZ_MAX_TYPES]; 1.1722 + register int thistypecnt; 1.1723 + char thischars[TZ_MAX_CHARS]; 1.1724 + char thischarcnt; 1.1725 + int indmap[TZ_MAX_CHARS]; 1.1726 + 1.1727 + if (pass == 1) { 1.1728 + thistimei = timei32; 1.1729 + thistimecnt = timecnt32; 1.1730 + thisleapi = leapi32; 1.1731 + thisleapcnt = leapcnt32; 1.1732 + } else { 1.1733 + thistimei = 0; 1.1734 + thistimecnt = timecnt; 1.1735 + thisleapi = 0; 1.1736 + thisleapcnt = leapcnt; 1.1737 + } 1.1738 + thistimelim = thistimei + thistimecnt; 1.1739 + thisleaplim = thisleapi + thisleapcnt; 1.1740 + for (i = 0; i < typecnt; ++i) 1.1741 + writetype[i] = thistimecnt == timecnt; 1.1742 + if (thistimecnt == 0) { 1.1743 + /* 1.1744 + ** No transition times fall in the current 1.1745 + ** (32- or 64-bit) window. 1.1746 + */ 1.1747 + if (typecnt != 0) 1.1748 + writetype[typecnt - 1] = TRUE; 1.1749 + } else { 1.1750 + for (i = thistimei - 1; i < thistimelim; ++i) 1.1751 + if (i >= 0) 1.1752 + writetype[types[i]] = TRUE; 1.1753 + /* 1.1754 + ** For America/Godthab and Antarctica/Palmer 1.1755 + */ 1.1756 + if (thistimei == 0) 1.1757 + writetype[0] = TRUE; 1.1758 + } 1.1759 + thistypecnt = 0; 1.1760 + for (i = 0; i < typecnt; ++i) 1.1761 + typemap[i] = writetype[i] ? thistypecnt++ : -1; 1.1762 + for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i) 1.1763 + indmap[i] = -1; 1.1764 + thischarcnt = 0; 1.1765 + for (i = 0; i < typecnt; ++i) { 1.1766 + register char * thisabbr; 1.1767 + 1.1768 + if (!writetype[i]) 1.1769 + continue; 1.1770 + if (indmap[abbrinds[i]] >= 0) 1.1771 + continue; 1.1772 + thisabbr = &chars[abbrinds[i]]; 1.1773 + for (j = 0; j < thischarcnt; ++j) 1.1774 + if (strcmp(&thischars[j], thisabbr) == 0) 1.1775 + break; 1.1776 + if (j == thischarcnt) { 1.1777 + (void) strcpy(&thischars[(int) thischarcnt], 1.1778 + thisabbr); 1.1779 + thischarcnt += strlen(thisabbr) + 1; 1.1780 + } 1.1781 + indmap[abbrinds[i]] = j; 1.1782 + } 1.1783 +#define DO(field) (void) fwrite((void *) tzh.field, \ 1.1784 + (size_t) sizeof tzh.field, (size_t) 1, fp) 1.1785 + tzh = tzh0; 1.1786 +#ifdef ICU 1.1787 + * (ICUZoneinfoVersion*) &tzh.tzh_reserved = TZ_ICU_VERSION; 1.1788 + (void) strncpy(tzh.tzh_magic, TZ_ICU_MAGIC, sizeof tzh.tzh_magic); 1.1789 +#else 1.1790 + (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); 1.1791 +#endif 1.1792 + tzh.tzh_version[0] = ZIC_VERSION; 1.1793 + convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt); 1.1794 + convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt); 1.1795 + convert(eitol(thisleapcnt), tzh.tzh_leapcnt); 1.1796 + convert(eitol(thistimecnt), tzh.tzh_timecnt); 1.1797 + convert(eitol(thistypecnt), tzh.tzh_typecnt); 1.1798 + convert(eitol(thischarcnt), tzh.tzh_charcnt); 1.1799 + DO(tzh_magic); 1.1800 + DO(tzh_version); 1.1801 + DO(tzh_reserved); 1.1802 + DO(tzh_ttisgmtcnt); 1.1803 + DO(tzh_ttisstdcnt); 1.1804 + DO(tzh_leapcnt); 1.1805 + DO(tzh_timecnt); 1.1806 + DO(tzh_typecnt); 1.1807 + DO(tzh_charcnt); 1.1808 +#undef DO 1.1809 + for (i = thistimei; i < thistimelim; ++i) 1.1810 + if (pass == 1) 1.1811 + puttzcode((long) ats[i], fp); 1.1812 + else puttzcode64(ats[i], fp); 1.1813 + for (i = thistimei; i < thistimelim; ++i) { 1.1814 + unsigned char uc; 1.1815 + 1.1816 + uc = typemap[types[i]]; 1.1817 + (void) fwrite((void *) &uc, 1.1818 + (size_t) sizeof uc, 1.1819 + (size_t) 1, 1.1820 + fp); 1.1821 + } 1.1822 + for (i = 0; i < typecnt; ++i) 1.1823 + if (writetype[i]) { 1.1824 +#ifdef ICU 1.1825 + puttzcode((long) rawoffs[i], fp); 1.1826 + puttzcode((long) dstoffs[i], fp); 1.1827 +#else 1.1828 + puttzcode(gmtoffs[i], fp); 1.1829 +#endif 1.1830 + (void) putc(isdsts[i], fp); 1.1831 + (void) putc((unsigned char) indmap[abbrinds[i]], fp); 1.1832 + } 1.1833 + if (thischarcnt != 0) 1.1834 + (void) fwrite((void *) thischars, 1.1835 + (size_t) sizeof thischars[0], 1.1836 + (size_t) thischarcnt, fp); 1.1837 + for (i = thisleapi; i < thisleaplim; ++i) { 1.1838 + register zic_t todo; 1.1839 + 1.1840 + if (roll[i]) { 1.1841 + if (timecnt == 0 || trans[i] < ats[0]) { 1.1842 + j = 0; 1.1843 + while (isdsts[j]) 1.1844 + if (++j >= typecnt) { 1.1845 + j = 0; 1.1846 + break; 1.1847 + } 1.1848 + } else { 1.1849 + j = 1; 1.1850 + while (j < timecnt && 1.1851 + trans[i] >= ats[j]) 1.1852 + ++j; 1.1853 + j = types[j - 1]; 1.1854 + } 1.1855 + todo = tadd(trans[i], -gmtoffs[j]); 1.1856 + } else todo = trans[i]; 1.1857 + if (pass == 1) 1.1858 + puttzcode((long) todo, fp); 1.1859 + else puttzcode64(todo, fp); 1.1860 + puttzcode(corr[i], fp); 1.1861 + } 1.1862 + for (i = 0; i < typecnt; ++i) 1.1863 + if (writetype[i]) 1.1864 + (void) putc(ttisstds[i], fp); 1.1865 + for (i = 0; i < typecnt; ++i) 1.1866 + if (writetype[i]) 1.1867 + (void) putc(ttisgmts[i], fp); 1.1868 + } 1.1869 + (void) fprintf(fp, "\n%s\n", string); 1.1870 + if (ferror(fp) || fclose(fp)) { 1.1871 + (void) fprintf(stderr, _("%s: Error writing %s\n"), 1.1872 + progname, fullname); 1.1873 + exit(EXIT_FAILURE); 1.1874 + } 1.1875 +} 1.1876 + 1.1877 +static void 1.1878 +doabbr(abbr, format, letters, isdst, doquotes) 1.1879 +char * const abbr; 1.1880 +const char * const format; 1.1881 +const char * const letters; 1.1882 +const int isdst; 1.1883 +const int doquotes; 1.1884 +{ 1.1885 + register char * cp; 1.1886 + register char * slashp; 1.1887 + register int len; 1.1888 + 1.1889 + slashp = strchr(format, '/'); 1.1890 + if (slashp == NULL) { 1.1891 + if (letters == NULL) 1.1892 + (void) strcpy(abbr, format); 1.1893 + else (void) sprintf(abbr, format, letters); 1.1894 + } else if (isdst) { 1.1895 + (void) strcpy(abbr, slashp + 1); 1.1896 + } else { 1.1897 + if (slashp > format) 1.1898 + (void) strncpy(abbr, format, 1.1899 + (unsigned) (slashp - format)); 1.1900 + abbr[slashp - format] = '\0'; 1.1901 + } 1.1902 + if (!doquotes) 1.1903 + return; 1.1904 + for (cp = abbr; *cp != '\0'; ++cp) 1.1905 + if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", *cp) == NULL && 1.1906 + strchr("abcdefghijklmnopqrstuvwxyz", *cp) == NULL) 1.1907 + break; 1.1908 + len = strlen(abbr); 1.1909 + if (len > 0 && *cp == '\0') 1.1910 + return; 1.1911 + abbr[len + 2] = '\0'; 1.1912 + abbr[len + 1] = '>'; 1.1913 + for ( ; len > 0; --len) 1.1914 + abbr[len] = abbr[len - 1]; 1.1915 + abbr[0] = '<'; 1.1916 +} 1.1917 + 1.1918 +static void 1.1919 +updateminmax(x) 1.1920 +const int x; 1.1921 +{ 1.1922 + if (min_year > x) 1.1923 + min_year = x; 1.1924 + if (max_year < x) 1.1925 + max_year = x; 1.1926 +} 1.1927 + 1.1928 +static int 1.1929 +stringoffset(result, offset) 1.1930 +char * result; 1.1931 +long offset; 1.1932 +{ 1.1933 + register int hours; 1.1934 + register int minutes; 1.1935 + register int seconds; 1.1936 + 1.1937 + result[0] = '\0'; 1.1938 + if (offset < 0) { 1.1939 + (void) strcpy(result, "-"); 1.1940 + offset = -offset; 1.1941 + } 1.1942 + seconds = offset % SECSPERMIN; 1.1943 + offset /= SECSPERMIN; 1.1944 + minutes = offset % MINSPERHOUR; 1.1945 + offset /= MINSPERHOUR; 1.1946 + hours = offset; 1.1947 + if (hours >= HOURSPERDAY) { 1.1948 + result[0] = '\0'; 1.1949 + return -1; 1.1950 + } 1.1951 + (void) sprintf(end(result), "%d", hours); 1.1952 + if (minutes != 0 || seconds != 0) { 1.1953 + (void) sprintf(end(result), ":%02d", minutes); 1.1954 + if (seconds != 0) 1.1955 + (void) sprintf(end(result), ":%02d", seconds); 1.1956 + } 1.1957 + return 0; 1.1958 +} 1.1959 + 1.1960 +static int 1.1961 +stringrule(result, rp, dstoff, gmtoff) 1.1962 +char * result; 1.1963 +const struct rule * const rp; 1.1964 +const long dstoff; 1.1965 +const long gmtoff; 1.1966 +{ 1.1967 + register long tod; 1.1968 + 1.1969 + result = end(result); 1.1970 + if (rp->r_dycode == DC_DOM) { 1.1971 + register int month, total; 1.1972 + 1.1973 + if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY) 1.1974 + return -1; 1.1975 + total = 0; 1.1976 + for (month = 0; month < rp->r_month; ++month) 1.1977 + total += len_months[0][month]; 1.1978 + (void) sprintf(result, "J%d", total + rp->r_dayofmonth); 1.1979 + } else { 1.1980 + register int week; 1.1981 + 1.1982 + if (rp->r_dycode == DC_DOWGEQ) { 1.1983 + week = 1 + rp->r_dayofmonth / DAYSPERWEEK; 1.1984 + if ((week - 1) * DAYSPERWEEK + 1 != rp->r_dayofmonth) 1.1985 + return -1; 1.1986 + } else if (rp->r_dycode == DC_DOWLEQ) { 1.1987 + if (rp->r_dayofmonth == len_months[1][rp->r_month]) 1.1988 + week = 5; 1.1989 + else { 1.1990 + week = 1 + rp->r_dayofmonth / DAYSPERWEEK; 1.1991 + if (week * DAYSPERWEEK - 1 != rp->r_dayofmonth) 1.1992 + return -1; 1.1993 + } 1.1994 + } else return -1; /* "cannot happen" */ 1.1995 + (void) sprintf(result, "M%d.%d.%d", 1.1996 + rp->r_month + 1, week, rp->r_wday); 1.1997 + } 1.1998 + tod = rp->r_tod; 1.1999 + if (rp->r_todisgmt) 1.2000 + tod += gmtoff; 1.2001 + if (rp->r_todisstd && rp->r_stdoff == 0) 1.2002 + tod += dstoff; 1.2003 + if (tod < 0) { 1.2004 + result[0] = '\0'; 1.2005 + return -1; 1.2006 + } 1.2007 + if (tod != 2 * SECSPERMIN * MINSPERHOUR) { 1.2008 + (void) strcat(result, "/"); 1.2009 + if (stringoffset(end(result), tod) != 0) 1.2010 + return -1; 1.2011 + } 1.2012 + return 0; 1.2013 +} 1.2014 + 1.2015 +static void 1.2016 +stringzone(result, zpfirst, zonecount) 1.2017 +char * result; 1.2018 +const struct zone * const zpfirst; 1.2019 +const int zonecount; 1.2020 +{ 1.2021 + register const struct zone * zp; 1.2022 + register struct rule * rp; 1.2023 + register struct rule * stdrp; 1.2024 + register struct rule * dstrp; 1.2025 + register int i; 1.2026 + register const char * abbrvar; 1.2027 + 1.2028 + result[0] = '\0'; 1.2029 + zp = zpfirst + zonecount - 1; 1.2030 + stdrp = dstrp = NULL; 1.2031 + for (i = 0; i < zp->z_nrules; ++i) { 1.2032 + rp = &zp->z_rules[i]; 1.2033 + if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX) 1.2034 + continue; 1.2035 + if (rp->r_yrtype != NULL) 1.2036 + continue; 1.2037 + if (rp->r_stdoff == 0) { 1.2038 + if (stdrp == NULL) 1.2039 + stdrp = rp; 1.2040 + else return; 1.2041 + } else { 1.2042 + if (dstrp == NULL) 1.2043 + dstrp = rp; 1.2044 + else return; 1.2045 + } 1.2046 + } 1.2047 + if (stdrp == NULL && dstrp == NULL) { 1.2048 + /* 1.2049 + ** There are no rules running through "max". 1.2050 + ** Let's find the latest rule. 1.2051 + */ 1.2052 + for (i = 0; i < zp->z_nrules; ++i) { 1.2053 + rp = &zp->z_rules[i]; 1.2054 + if (stdrp == NULL || rp->r_hiyear > stdrp->r_hiyear || 1.2055 + (rp->r_hiyear == stdrp->r_hiyear && 1.2056 + rp->r_month > stdrp->r_month)) 1.2057 + stdrp = rp; 1.2058 + } 1.2059 + if (stdrp != NULL && stdrp->r_stdoff != 0) 1.2060 + return; /* We end up in DST (a POSIX no-no). */ 1.2061 + /* 1.2062 + ** Horrid special case: if year is 2037, 1.2063 + ** presume this is a zone handled on a year-by-year basis; 1.2064 + ** do not try to apply a rule to the zone. 1.2065 + */ 1.2066 + if (stdrp != NULL && stdrp->r_hiyear == 2037) 1.2067 + return; 1.2068 + } 1.2069 + if (stdrp == NULL && zp->z_nrules != 0) 1.2070 + return; 1.2071 + abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; 1.2072 + doabbr(result, zp->z_format, abbrvar, FALSE, TRUE); 1.2073 + if (stringoffset(end(result), -zp->z_gmtoff) != 0) { 1.2074 + result[0] = '\0'; 1.2075 + return; 1.2076 + } 1.2077 + if (dstrp == NULL) 1.2078 + return; 1.2079 + doabbr(end(result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE); 1.2080 + if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) 1.2081 + if (stringoffset(end(result), 1.2082 + -(zp->z_gmtoff + dstrp->r_stdoff)) != 0) { 1.2083 + result[0] = '\0'; 1.2084 + return; 1.2085 + } 1.2086 + (void) strcat(result, ","); 1.2087 + if (stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { 1.2088 + result[0] = '\0'; 1.2089 + return; 1.2090 + } 1.2091 + (void) strcat(result, ","); 1.2092 + if (stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { 1.2093 + result[0] = '\0'; 1.2094 + return; 1.2095 + } 1.2096 +} 1.2097 + 1.2098 +static void 1.2099 +outzone(zpfirst, zonecount) 1.2100 +const struct zone * const zpfirst; 1.2101 +const int zonecount; 1.2102 +{ 1.2103 + register const struct zone * zp; 1.2104 + register struct rule * rp; 1.2105 + register int i, j; 1.2106 + register int usestart, useuntil; 1.2107 + register zic_t starttime, untiltime; 1.2108 + register long gmtoff; 1.2109 + register long stdoff; 1.2110 + register int year; 1.2111 + register long startoff; 1.2112 + register int startttisstd; 1.2113 + register int startttisgmt; 1.2114 + register int type; 1.2115 + register char * startbuf; 1.2116 + register char * ab; 1.2117 + register char * envvar; 1.2118 + register int max_abbr_len; 1.2119 + register int max_envvar_len; 1.2120 +#ifdef ICU 1.2121 + int finalRuleYear, finalRuleIndex; 1.2122 + const struct rule* finalRule1; 1.2123 + const struct rule* finalRule2; 1.2124 +#endif 1.2125 + 1.2126 + max_abbr_len = 2 + max_format_len + max_abbrvar_len; 1.2127 + max_envvar_len = 2 * max_abbr_len + 5 * 9; 1.2128 + startbuf = emalloc(max_abbr_len + 1); 1.2129 + ab = emalloc(max_abbr_len + 1); 1.2130 + envvar = emalloc(max_envvar_len + 1); 1.2131 + INITIALIZE(untiltime); 1.2132 + INITIALIZE(starttime); 1.2133 + /* 1.2134 + ** Now. . .finally. . .generate some useful data! 1.2135 + */ 1.2136 + timecnt = 0; 1.2137 + typecnt = 0; 1.2138 + charcnt = 0; 1.2139 + /* 1.2140 + ** Thanks to Earl Chew 1.2141 + ** for noting the need to unconditionally initialize startttisstd. 1.2142 + */ 1.2143 + startttisstd = FALSE; 1.2144 + startttisgmt = FALSE; 1.2145 + min_year = max_year = EPOCH_YEAR; 1.2146 + if (leapseen) { 1.2147 + updateminmax(leapminyear); 1.2148 + updateminmax(leapmaxyear); 1.2149 + } 1.2150 + for (i = 0; i < zonecount; ++i) { 1.2151 + zp = &zpfirst[i]; 1.2152 + if (i < zonecount - 1) 1.2153 + updateminmax(zp->z_untilrule.r_loyear); 1.2154 + for (j = 0; j < zp->z_nrules; ++j) { 1.2155 + rp = &zp->z_rules[j]; 1.2156 + if (rp->r_lowasnum) 1.2157 + updateminmax(rp->r_loyear); 1.2158 + if (rp->r_hiwasnum) 1.2159 + updateminmax(rp->r_hiyear); 1.2160 + } 1.2161 + } 1.2162 + /* 1.2163 + ** Generate lots of data if a rule can't cover all future times. 1.2164 + */ 1.2165 + stringzone(envvar, zpfirst, zonecount); 1.2166 + if (noise && envvar[0] == '\0') { 1.2167 + register char * wp; 1.2168 + 1.2169 +wp = ecpyalloc(_("no POSIX environment variable for zone")); 1.2170 + wp = ecatalloc(wp, " "); 1.2171 + wp = ecatalloc(wp, zpfirst->z_name); 1.2172 + warning(wp); 1.2173 + ifree(wp); 1.2174 + } 1.2175 + if (envvar[0] == '\0') { 1.2176 + if (min_year >= INT_MIN + YEARSPERREPEAT) 1.2177 + min_year -= YEARSPERREPEAT; 1.2178 + else min_year = INT_MIN; 1.2179 + if (max_year <= INT_MAX - YEARSPERREPEAT) 1.2180 + max_year += YEARSPERREPEAT; 1.2181 + else max_year = INT_MAX; 1.2182 + } 1.2183 + /* 1.2184 + ** For the benefit of older systems, 1.2185 + ** generate data from 1900 through 2037. 1.2186 + */ 1.2187 + if (min_year > 1900) 1.2188 + min_year = 1900; 1.2189 + if (max_year < 2037) 1.2190 + max_year = 2037; 1.2191 + for (i = 0; i < zonecount; ++i) { 1.2192 + /* 1.2193 + ** A guess that may well be corrected later. 1.2194 + */ 1.2195 + stdoff = 0; 1.2196 + zp = &zpfirst[i]; 1.2197 + usestart = i > 0 && (zp - 1)->z_untiltime > min_time; 1.2198 + useuntil = i < (zonecount - 1); 1.2199 + if (useuntil && zp->z_untiltime <= min_time) 1.2200 + continue; 1.2201 + gmtoff = zp->z_gmtoff; 1.2202 + eat(zp->z_filename, zp->z_linenum); 1.2203 + *startbuf = '\0'; 1.2204 + startoff = zp->z_gmtoff; 1.2205 +#ifdef ICU 1.2206 + finalRuleYear = finalRuleIndex = -1; 1.2207 + finalRule1 = finalRule2 = NULL; 1.2208 + if (i == (zonecount - 1)) { /* !useuntil */ 1.2209 + /* Look for exactly 2 rules that end at 'max' and 1.2210 + * note them. Determine max(r_loyear) for the 2 of 1.2211 + * them. */ 1.2212 + for (j=0; j<zp->z_nrules; ++j) { 1.2213 + rp = &zp->z_rules[j]; 1.2214 + if (rp->r_hiyear == INT_MAX) { 1.2215 + if (rp->r_loyear > finalRuleYear) { 1.2216 + finalRuleYear = rp->r_loyear; 1.2217 + } 1.2218 + if (finalRule1 == NULL) { 1.2219 + finalRule1 = rp; 1.2220 + } else if (finalRule2 == NULL) { 1.2221 + finalRule2 = rp; 1.2222 + } else { 1.2223 + error("more than two max rules found (ICU)"); 1.2224 + exit(EXIT_FAILURE); 1.2225 + } 1.2226 + } else if (rp->r_hiyear >= finalRuleYear) { 1.2227 + /* There might be an overriding non-max rule 1.2228 + * to be applied to a specific year after one of 1.2229 + * max rule's start year. For example, 1.2230 + * 1.2231 + * Rule Foo 2010 max ... 1.2232 + * Rule Foo 2015 only ... 1.2233 + * 1.2234 + * In this case, we need to change the start year of 1.2235 + * the final (max) rules to the next year. */ 1.2236 + finalRuleYear = rp->r_hiyear + 1; 1.2237 + 1.2238 + /* When above adjustment is done, max_year might need 1.2239 + * to be adjusted, so the final rule will be properly 1.2240 + * evaluated and emitted by the later code block. 1.2241 + * 1.2242 + * Note: This may push the start year of the final 1.2243 + * rules ahead by 1 year unnecessarily. For example, 1.2244 + * If there are two rules, non-max rule and max rule 1.2245 + * starting in the same year, such as 1.2246 + * 1.2247 + * Rule Foo 2010 only .... 1.2248 + * Rule Foo 2010 max .... 1.2249 + * 1.2250 + * In this case, the final (max) rule actually starts 1.2251 + * in 2010, instead of 2010. We could make this tool 1.2252 + * more intelligent to detect such situation. But pushing 1.2253 + * final rule start year to 1 year ahead (in the worst case) 1.2254 + * will just populate a few extra transitions, and it still 1.2255 + * works fine. So for now, we're not trying to put additional 1.2256 + * logic to optimize the case. 1.2257 + */ 1.2258 + if (max_year < finalRuleYear) { 1.2259 + max_year = finalRuleYear; 1.2260 + } 1.2261 + } 1.2262 + } 1.2263 + if (finalRule1 != NULL) { 1.2264 + if (finalRule2 == NULL) { 1.2265 + warning("only one max rule found (ICU)"); 1.2266 + finalRuleYear = finalRuleIndex = -1; 1.2267 + finalRule1 = NULL; 1.2268 + } else { 1.2269 + if (finalRule1->r_stdoff == finalRule2->r_stdoff) { 1.2270 + /* America/Resolute in 2009a uses a pair of rules 1.2271 + * which does not change the offset. ICU ignores 1.2272 + * such rules without actual time transitions. */ 1.2273 + finalRuleYear = finalRuleIndex = -1; 1.2274 + finalRule1 = finalRule2 = NULL; 1.2275 + } else { 1.2276 + /* Swap if necessary so finalRule1 occurs before 1.2277 + * finalRule2 */ 1.2278 + if (finalRule1->r_month > finalRule2->r_month) { 1.2279 + const struct rule* t = finalRule1; 1.2280 + finalRule1 = finalRule2; 1.2281 + finalRule2 = t; 1.2282 + } 1.2283 + /* Add final rule to our list */ 1.2284 + finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2); 1.2285 + } 1.2286 + } 1.2287 + } 1.2288 + } 1.2289 +#endif 1.2290 + 1.2291 + if (zp->z_nrules == 0) { 1.2292 + stdoff = zp->z_stdoff; 1.2293 + doabbr(startbuf, zp->z_format, 1.2294 + (char *) NULL, stdoff != 0, FALSE); 1.2295 + type = addtype(oadd(zp->z_gmtoff, stdoff), 1.2296 +#ifdef ICU 1.2297 + zp->z_gmtoff, stdoff, 1.2298 +#endif 1.2299 + startbuf, stdoff != 0, startttisstd, 1.2300 + startttisgmt); 1.2301 + if (usestart) { 1.2302 + addtt(starttime, type); 1.2303 + usestart = FALSE; 1.2304 + } else if (stdoff != 0) 1.2305 + addtt(min_time, type); 1.2306 + } else for (year = min_year; year <= max_year; ++year) { 1.2307 + if (useuntil && year > zp->z_untilrule.r_hiyear) 1.2308 + break; 1.2309 + /* 1.2310 + ** Mark which rules to do in the current year. 1.2311 + ** For those to do, calculate rpytime(rp, year); 1.2312 + */ 1.2313 + for (j = 0; j < zp->z_nrules; ++j) { 1.2314 + rp = &zp->z_rules[j]; 1.2315 + eats(zp->z_filename, zp->z_linenum, 1.2316 + rp->r_filename, rp->r_linenum); 1.2317 + rp->r_todo = year >= rp->r_loyear && 1.2318 + year <= rp->r_hiyear && 1.2319 + yearistype(year, rp->r_yrtype); 1.2320 + if (rp->r_todo) 1.2321 + rp->r_temp = rpytime(rp, year); 1.2322 + } 1.2323 + for ( ; ; ) { 1.2324 + register int k; 1.2325 + register zic_t jtime, ktime; 1.2326 + register long offset; 1.2327 + 1.2328 + INITIALIZE(ktime); 1.2329 + if (useuntil) { 1.2330 + /* 1.2331 + ** Turn untiltime into UTC 1.2332 + ** assuming the current gmtoff and 1.2333 + ** stdoff values. 1.2334 + */ 1.2335 + untiltime = zp->z_untiltime; 1.2336 + if (!zp->z_untilrule.r_todisgmt) 1.2337 + untiltime = tadd(untiltime, 1.2338 + -gmtoff); 1.2339 + if (!zp->z_untilrule.r_todisstd) 1.2340 + untiltime = tadd(untiltime, 1.2341 + -stdoff); 1.2342 + } 1.2343 + /* 1.2344 + ** Find the rule (of those to do, if any) 1.2345 + ** that takes effect earliest in the year. 1.2346 + */ 1.2347 + k = -1; 1.2348 + for (j = 0; j < zp->z_nrules; ++j) { 1.2349 + rp = &zp->z_rules[j]; 1.2350 + if (!rp->r_todo) 1.2351 + continue; 1.2352 + eats(zp->z_filename, zp->z_linenum, 1.2353 + rp->r_filename, rp->r_linenum); 1.2354 + offset = rp->r_todisgmt ? 0 : gmtoff; 1.2355 + if (!rp->r_todisstd) 1.2356 + offset = oadd(offset, stdoff); 1.2357 + jtime = rp->r_temp; 1.2358 + if (jtime == min_time || 1.2359 + jtime == max_time) 1.2360 + continue; 1.2361 + jtime = tadd(jtime, -offset); 1.2362 + if (k < 0 || jtime < ktime) { 1.2363 + k = j; 1.2364 + ktime = jtime; 1.2365 + } 1.2366 + } 1.2367 + if (k < 0) 1.2368 + break; /* go on to next year */ 1.2369 + rp = &zp->z_rules[k]; 1.2370 + rp->r_todo = FALSE; 1.2371 + if (useuntil && ktime >= untiltime) 1.2372 + break; 1.2373 + stdoff = rp->r_stdoff; 1.2374 + if (usestart && ktime == starttime) 1.2375 + usestart = FALSE; 1.2376 + if (usestart) { 1.2377 + if (ktime < starttime) { 1.2378 + startoff = oadd(zp->z_gmtoff, 1.2379 + stdoff); 1.2380 + doabbr(startbuf, zp->z_format, 1.2381 + rp->r_abbrvar, 1.2382 + rp->r_stdoff != 0, 1.2383 + FALSE); 1.2384 + continue; 1.2385 + } 1.2386 + if (*startbuf == '\0' && 1.2387 + startoff == oadd(zp->z_gmtoff, 1.2388 + stdoff)) { 1.2389 + doabbr(startbuf, 1.2390 + zp->z_format, 1.2391 + rp->r_abbrvar, 1.2392 + rp->r_stdoff != 1.2393 + 0, 1.2394 + FALSE); 1.2395 + } 1.2396 + } 1.2397 +#ifdef ICU 1.2398 + if (year >= finalRuleYear && rp == finalRule1) { 1.2399 + /* We want to shift final year 1 year after 1.2400 + * the actual final rule takes effect (year + 1), 1.2401 + * because the previous type is valid until the first 1.2402 + * transition defined by the final rule. Otherwise 1.2403 + * we may see unexpected offset shift at the 1.2404 + * begining of the year when the final rule takes 1.2405 + * effect. 1.2406 + * 1.2407 + * Note: This may results some 64bit second transitions 1.2408 + * at the very end (year 2038). ICU 4.2 or older releases 1.2409 + * cannot handle 64bit second transitions and they are 1.2410 + * dropped from zoneinfo.txt. */ 1.2411 + emit_icu_zone(icuFile, 1.2412 + zpfirst->z_name, zp->z_gmtoff, 1.2413 + rp, finalRuleIndex, year + 1); 1.2414 + /* only emit this for the first year */ 1.2415 + finalRule1 = NULL; 1.2416 + } 1.2417 +#endif 1.2418 + eats(zp->z_filename, zp->z_linenum, 1.2419 + rp->r_filename, rp->r_linenum); 1.2420 + doabbr(ab, zp->z_format, rp->r_abbrvar, 1.2421 + rp->r_stdoff != 0, FALSE); 1.2422 + offset = oadd(zp->z_gmtoff, rp->r_stdoff); 1.2423 +#ifdef ICU 1.2424 + type = addtype(offset, zp->z_gmtoff, rp->r_stdoff, 1.2425 + ab, rp->r_stdoff != 0, 1.2426 + rp->r_todisstd, rp->r_todisgmt); 1.2427 +#else 1.2428 + type = addtype(offset, ab, rp->r_stdoff != 0, 1.2429 + rp->r_todisstd, rp->r_todisgmt); 1.2430 +#endif 1.2431 + addtt(ktime, type); 1.2432 + } 1.2433 + } 1.2434 + if (usestart) { 1.2435 + if (*startbuf == '\0' && 1.2436 + zp->z_format != NULL && 1.2437 + strchr(zp->z_format, '%') == NULL && 1.2438 + strchr(zp->z_format, '/') == NULL) 1.2439 + (void) strcpy(startbuf, zp->z_format); 1.2440 + eat(zp->z_filename, zp->z_linenum); 1.2441 + if (*startbuf == '\0') 1.2442 +error(_("can't determine time zone abbreviation to use just after until time")); 1.2443 + else addtt(starttime, 1.2444 +#ifdef ICU 1.2445 + addtype(startoff, 1.2446 + zp->z_gmtoff, startoff - zp->z_gmtoff, 1.2447 + startbuf, 1.2448 + startoff != zp->z_gmtoff, 1.2449 + startttisstd, 1.2450 + startttisgmt)); 1.2451 +#else 1.2452 + addtype(startoff, startbuf, 1.2453 + startoff != zp->z_gmtoff, 1.2454 + startttisstd, 1.2455 + startttisgmt)); 1.2456 +#endif 1.2457 + } 1.2458 + /* 1.2459 + ** Now we may get to set starttime for the next zone line. 1.2460 + */ 1.2461 + if (useuntil) { 1.2462 + startttisstd = zp->z_untilrule.r_todisstd; 1.2463 + startttisgmt = zp->z_untilrule.r_todisgmt; 1.2464 + starttime = zp->z_untiltime; 1.2465 + if (!startttisstd) 1.2466 + starttime = tadd(starttime, -stdoff); 1.2467 + if (!startttisgmt) 1.2468 + starttime = tadd(starttime, -gmtoff); 1.2469 + } 1.2470 + } 1.2471 + writezone(zpfirst->z_name, envvar); 1.2472 + ifree(startbuf); 1.2473 + ifree(ab); 1.2474 + ifree(envvar); 1.2475 +} 1.2476 + 1.2477 +static void 1.2478 +addtt(starttime, type) 1.2479 +const zic_t starttime; 1.2480 +int type; 1.2481 +{ 1.2482 + if (starttime <= min_time || 1.2483 + (timecnt == 1 && attypes[0].at < min_time)) { 1.2484 + gmtoffs[0] = gmtoffs[type]; 1.2485 +#ifdef ICU 1.2486 + rawoffs[0] = rawoffs[type]; 1.2487 + dstoffs[0] = dstoffs[type]; 1.2488 +#endif 1.2489 + isdsts[0] = isdsts[type]; 1.2490 + ttisstds[0] = ttisstds[type]; 1.2491 + ttisgmts[0] = ttisgmts[type]; 1.2492 + if (abbrinds[type] != 0) 1.2493 + (void) strcpy(chars, &chars[abbrinds[type]]); 1.2494 + abbrinds[0] = 0; 1.2495 + charcnt = strlen(chars) + 1; 1.2496 + typecnt = 1; 1.2497 + timecnt = 0; 1.2498 + type = 0; 1.2499 + } 1.2500 + if (timecnt >= TZ_MAX_TIMES) { 1.2501 + error(_("too many transitions?!")); 1.2502 + exit(EXIT_FAILURE); 1.2503 + } 1.2504 + attypes[timecnt].at = starttime; 1.2505 + attypes[timecnt].type = type; 1.2506 + ++timecnt; 1.2507 +} 1.2508 + 1.2509 +static int 1.2510 +#ifdef ICU 1.2511 +addtype(gmtoff, rawoff, dstoff, abbr, isdst, ttisstd, ttisgmt) 1.2512 +const long gmtoff; 1.2513 +const long rawoff; 1.2514 +const long dstoff; 1.2515 +#else 1.2516 +addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt) 1.2517 +const long gmtoff; 1.2518 +#endif 1.2519 +const char * const abbr; 1.2520 +const int isdst; 1.2521 +const int ttisstd; 1.2522 +const int ttisgmt; 1.2523 +{ 1.2524 + register int i, j; 1.2525 + 1.2526 + if (isdst != TRUE && isdst != FALSE) { 1.2527 + error(_("internal error - addtype called with bad isdst")); 1.2528 + exit(EXIT_FAILURE); 1.2529 + } 1.2530 + if (ttisstd != TRUE && ttisstd != FALSE) { 1.2531 + error(_("internal error - addtype called with bad ttisstd")); 1.2532 + exit(EXIT_FAILURE); 1.2533 + } 1.2534 + if (ttisgmt != TRUE && ttisgmt != FALSE) { 1.2535 + error(_("internal error - addtype called with bad ttisgmt")); 1.2536 + exit(EXIT_FAILURE); 1.2537 + } 1.2538 +#ifdef ICU 1.2539 + if (isdst != (dstoff != 0)) { 1.2540 + error(_("internal error - addtype called with bad isdst/dstoff")); 1.2541 + (void) exit(EXIT_FAILURE); 1.2542 + } 1.2543 + if (gmtoff != (rawoff + dstoff)) { 1.2544 + error(_("internal error - addtype called with bad gmt/raw/dstoff")); 1.2545 + (void) exit(EXIT_FAILURE); 1.2546 + } 1.2547 +#endif 1.2548 + /* 1.2549 + ** See if there's already an entry for this zone type. 1.2550 + ** If so, just return its index. 1.2551 + */ 1.2552 + for (i = 0; i < typecnt; ++i) { 1.2553 + if (gmtoff == gmtoffs[i] && isdst == isdsts[i] && 1.2554 +#ifdef ICU 1.2555 + rawoff == rawoffs[i] && dstoff == dstoffs[i] && 1.2556 +#endif 1.2557 + strcmp(abbr, &chars[abbrinds[i]]) == 0 && 1.2558 + ttisstd == ttisstds[i] && 1.2559 + ttisgmt == ttisgmts[i]) 1.2560 + return i; 1.2561 + } 1.2562 + /* 1.2563 + ** There isn't one; add a new one, unless there are already too 1.2564 + ** many. 1.2565 + */ 1.2566 + if (typecnt >= TZ_MAX_TYPES) { 1.2567 + error(_("too many local time types")); 1.2568 + exit(EXIT_FAILURE); 1.2569 + } 1.2570 + if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) { 1.2571 + error(_("UTC offset out of range")); 1.2572 + exit(EXIT_FAILURE); 1.2573 + } 1.2574 + gmtoffs[i] = gmtoff; 1.2575 +#ifdef ICU 1.2576 + rawoffs[i] = rawoff; 1.2577 + dstoffs[i] = dstoff; 1.2578 +#endif 1.2579 + isdsts[i] = isdst; 1.2580 + ttisstds[i] = ttisstd; 1.2581 + ttisgmts[i] = ttisgmt; 1.2582 + 1.2583 + for (j = 0; j < charcnt; ++j) 1.2584 + if (strcmp(&chars[j], abbr) == 0) 1.2585 + break; 1.2586 + if (j == charcnt) 1.2587 + newabbr(abbr); 1.2588 + abbrinds[i] = j; 1.2589 + ++typecnt; 1.2590 + return i; 1.2591 +} 1.2592 + 1.2593 +static void 1.2594 +leapadd(t, positive, rolling, count) 1.2595 +const zic_t t; 1.2596 +const int positive; 1.2597 +const int rolling; 1.2598 +int count; 1.2599 +{ 1.2600 + register int i, j; 1.2601 + 1.2602 + if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { 1.2603 + error(_("too many leap seconds")); 1.2604 + exit(EXIT_FAILURE); 1.2605 + } 1.2606 + for (i = 0; i < leapcnt; ++i) 1.2607 + if (t <= trans[i]) { 1.2608 + if (t == trans[i]) { 1.2609 + error(_("repeated leap second moment")); 1.2610 + exit(EXIT_FAILURE); 1.2611 + } 1.2612 + break; 1.2613 + } 1.2614 + do { 1.2615 + for (j = leapcnt; j > i; --j) { 1.2616 + trans[j] = trans[j - 1]; 1.2617 + corr[j] = corr[j - 1]; 1.2618 + roll[j] = roll[j - 1]; 1.2619 + } 1.2620 + trans[i] = t; 1.2621 + corr[i] = positive ? 1L : eitol(-count); 1.2622 + roll[i] = rolling; 1.2623 + ++leapcnt; 1.2624 + } while (positive && --count != 0); 1.2625 +} 1.2626 + 1.2627 +static void 1.2628 +adjleap(void) 1.2629 +{ 1.2630 + register int i; 1.2631 + register long last = 0; 1.2632 + 1.2633 + /* 1.2634 + ** propagate leap seconds forward 1.2635 + */ 1.2636 + for (i = 0; i < leapcnt; ++i) { 1.2637 + trans[i] = tadd(trans[i], last); 1.2638 + last = corr[i] += last; 1.2639 + } 1.2640 +} 1.2641 + 1.2642 +static int 1.2643 +yearistype(year, type) 1.2644 +const int year; 1.2645 +const char * const type; 1.2646 +{ 1.2647 + static char * buf; 1.2648 + int result; 1.2649 + 1.2650 + if (type == NULL || *type == '\0') 1.2651 + return TRUE; 1.2652 + buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type))); 1.2653 + (void) sprintf(buf, "%s %d %s", yitcommand, year, type); 1.2654 + result = system(buf); 1.2655 + if (WIFEXITED(result)) switch (WEXITSTATUS(result)) { 1.2656 + case 0: 1.2657 + return TRUE; 1.2658 + case 1: 1.2659 + return FALSE; 1.2660 + } 1.2661 + error(_("Wild result from command execution")); 1.2662 + (void) fprintf(stderr, _("%s: command was '%s', result was %d\n"), 1.2663 + progname, buf, result); 1.2664 + for ( ; ; ) 1.2665 + exit(EXIT_FAILURE); 1.2666 +} 1.2667 + 1.2668 +static int 1.2669 +lowerit(a) 1.2670 +int a; 1.2671 +{ 1.2672 + a = (unsigned char) a; 1.2673 + return (isascii(a) && isupper(a)) ? tolower(a) : a; 1.2674 +} 1.2675 + 1.2676 +static int 1.2677 +ciequal(ap, bp) /* case-insensitive equality */ 1.2678 +register const char * ap; 1.2679 +register const char * bp; 1.2680 +{ 1.2681 + while (lowerit(*ap) == lowerit(*bp++)) 1.2682 + if (*ap++ == '\0') 1.2683 + return TRUE; 1.2684 + return FALSE; 1.2685 +} 1.2686 + 1.2687 +static int 1.2688 +itsabbr(abbr, word) 1.2689 +register const char * abbr; 1.2690 +register const char * word; 1.2691 +{ 1.2692 + if (lowerit(*abbr) != lowerit(*word)) 1.2693 + return FALSE; 1.2694 + ++word; 1.2695 + while (*++abbr != '\0') 1.2696 + do { 1.2697 + if (*word == '\0') 1.2698 + return FALSE; 1.2699 + } while (lowerit(*word++) != lowerit(*abbr)); 1.2700 + return TRUE; 1.2701 +} 1.2702 + 1.2703 +static const struct lookup * 1.2704 +byword(word, table) 1.2705 +register const char * const word; 1.2706 +register const struct lookup * const table; 1.2707 +{ 1.2708 + register const struct lookup * foundlp; 1.2709 + register const struct lookup * lp; 1.2710 + 1.2711 + if (word == NULL || table == NULL) 1.2712 + return NULL; 1.2713 + /* 1.2714 + ** Look for exact match. 1.2715 + */ 1.2716 + for (lp = table; lp->l_word != NULL; ++lp) 1.2717 + if (ciequal(word, lp->l_word)) 1.2718 + return lp; 1.2719 + /* 1.2720 + ** Look for inexact match. 1.2721 + */ 1.2722 + foundlp = NULL; 1.2723 + for (lp = table; lp->l_word != NULL; ++lp) 1.2724 + if (itsabbr(word, lp->l_word)) { 1.2725 + if (foundlp == NULL) 1.2726 + foundlp = lp; 1.2727 + else return NULL; /* multiple inexact matches */ 1.2728 + } 1.2729 + return foundlp; 1.2730 +} 1.2731 + 1.2732 +static char ** 1.2733 +getfields(cp) 1.2734 +register char * cp; 1.2735 +{ 1.2736 + register char * dp; 1.2737 + register char ** array; 1.2738 + register int nsubs; 1.2739 + 1.2740 + if (cp == NULL) 1.2741 + return NULL; 1.2742 + array = (char **) (void *) 1.2743 + emalloc((int) ((strlen(cp) + 1) * sizeof *array)); 1.2744 + nsubs = 0; 1.2745 + for ( ; ; ) { 1.2746 + while (isascii((unsigned char) *cp) && 1.2747 + isspace((unsigned char) *cp)) 1.2748 + ++cp; 1.2749 + if (*cp == '\0' || *cp == '#') 1.2750 + break; 1.2751 + array[nsubs++] = dp = cp; 1.2752 + do { 1.2753 + if ((*dp = *cp++) != '"') 1.2754 + ++dp; 1.2755 + else while ((*dp = *cp++) != '"') 1.2756 + if (*dp != '\0') 1.2757 + ++dp; 1.2758 + else { 1.2759 + error(_( 1.2760 + "Odd number of quotation marks" 1.2761 + )); 1.2762 + exit(1); 1.2763 + } 1.2764 + } while (*cp != '\0' && *cp != '#' && 1.2765 + (!isascii(*cp) || !isspace((unsigned char) *cp))); 1.2766 + if (isascii(*cp) && isspace((unsigned char) *cp)) 1.2767 + ++cp; 1.2768 + *dp = '\0'; 1.2769 + } 1.2770 + array[nsubs] = NULL; 1.2771 + return array; 1.2772 +} 1.2773 + 1.2774 +static long 1.2775 +oadd(t1, t2) 1.2776 +const long t1; 1.2777 +const long t2; 1.2778 +{ 1.2779 + register long t; 1.2780 + 1.2781 + t = t1 + t2; 1.2782 + if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { 1.2783 + error(_("time overflow")); 1.2784 + exit(EXIT_FAILURE); 1.2785 + } 1.2786 + return t; 1.2787 +} 1.2788 + 1.2789 +static zic_t 1.2790 +tadd(t1, t2) 1.2791 +const zic_t t1; 1.2792 +const long t2; 1.2793 +{ 1.2794 + register zic_t t; 1.2795 + 1.2796 + if (t1 == max_time && t2 > 0) 1.2797 + return max_time; 1.2798 + if (t1 == min_time && t2 < 0) 1.2799 + return min_time; 1.2800 + t = t1 + t2; 1.2801 + if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { 1.2802 + error(_("time overflow")); 1.2803 + exit(EXIT_FAILURE); 1.2804 + } 1.2805 + return t; 1.2806 +} 1.2807 + 1.2808 +/* 1.2809 +** Given a rule, and a year, compute the date - in seconds since January 1, 1.2810 +** 1970, 00:00 LOCAL time - in that year that the rule refers to. 1.2811 +*/ 1.2812 + 1.2813 +static zic_t 1.2814 +rpytime(rp, wantedy) 1.2815 +register const struct rule * const rp; 1.2816 +register const int wantedy; 1.2817 +{ 1.2818 + register int y, m, i; 1.2819 + register long dayoff; /* with a nod to Margaret O. */ 1.2820 + register zic_t t; 1.2821 + 1.2822 + if (wantedy == INT_MIN) 1.2823 + return min_time; 1.2824 + if (wantedy == INT_MAX) 1.2825 + return max_time; 1.2826 + dayoff = 0; 1.2827 + m = TM_JANUARY; 1.2828 + y = EPOCH_YEAR; 1.2829 + while (wantedy != y) { 1.2830 + if (wantedy > y) { 1.2831 + i = len_years[isleap(y)]; 1.2832 + ++y; 1.2833 + } else { 1.2834 + --y; 1.2835 + i = -len_years[isleap(y)]; 1.2836 + } 1.2837 + dayoff = oadd(dayoff, eitol(i)); 1.2838 + } 1.2839 + while (m != rp->r_month) { 1.2840 + i = len_months[isleap(y)][m]; 1.2841 + dayoff = oadd(dayoff, eitol(i)); 1.2842 + ++m; 1.2843 + } 1.2844 + i = rp->r_dayofmonth; 1.2845 + if (m == TM_FEBRUARY && i == 29 && !isleap(y)) { 1.2846 + if (rp->r_dycode == DC_DOWLEQ) 1.2847 + --i; 1.2848 + else { 1.2849 + error(_("use of 2/29 in non leap-year")); 1.2850 + exit(EXIT_FAILURE); 1.2851 + } 1.2852 + } 1.2853 + --i; 1.2854 + dayoff = oadd(dayoff, eitol(i)); 1.2855 + if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) { 1.2856 + register long wday; 1.2857 + 1.2858 +#define LDAYSPERWEEK ((long) DAYSPERWEEK) 1.2859 + wday = eitol(EPOCH_WDAY); 1.2860 + /* 1.2861 + ** Don't trust mod of negative numbers. 1.2862 + */ 1.2863 + if (dayoff >= 0) 1.2864 + wday = (wday + dayoff) % LDAYSPERWEEK; 1.2865 + else { 1.2866 + wday -= ((-dayoff) % LDAYSPERWEEK); 1.2867 + if (wday < 0) 1.2868 + wday += LDAYSPERWEEK; 1.2869 + } 1.2870 + while (wday != eitol(rp->r_wday)) 1.2871 + if (rp->r_dycode == DC_DOWGEQ) { 1.2872 + dayoff = oadd(dayoff, (long) 1); 1.2873 + if (++wday >= LDAYSPERWEEK) 1.2874 + wday = 0; 1.2875 + ++i; 1.2876 + } else { 1.2877 + dayoff = oadd(dayoff, (long) -1); 1.2878 + if (--wday < 0) 1.2879 + wday = LDAYSPERWEEK - 1; 1.2880 + --i; 1.2881 + } 1.2882 + if (i < 0 || i >= len_months[isleap(y)][m]) { 1.2883 + if (noise) 1.2884 + warning(_("rule goes past start/end of month--\ 1.2885 +will not work with pre-2004 versions of zic")); 1.2886 + } 1.2887 + } 1.2888 + if (dayoff < min_time / SECSPERDAY) 1.2889 + return min_time; 1.2890 + if (dayoff > max_time / SECSPERDAY) 1.2891 + return max_time; 1.2892 + t = (zic_t) dayoff * SECSPERDAY; 1.2893 + return tadd(t, rp->r_tod); 1.2894 +} 1.2895 + 1.2896 +static void 1.2897 +newabbr(string) 1.2898 +const char * const string; 1.2899 +{ 1.2900 + register int i; 1.2901 + 1.2902 + if (strcmp(string, GRANDPARENTED) != 0) { 1.2903 + register const char * cp; 1.2904 + register char * wp; 1.2905 + 1.2906 + /* 1.2907 + ** Want one to ZIC_MAX_ABBR_LEN_WO_WARN alphabetics 1.2908 + ** optionally followed by a + or - and a number from 1 to 14. 1.2909 + */ 1.2910 + cp = string; 1.2911 + wp = NULL; 1.2912 + while (isascii((unsigned char) *cp) && 1.2913 + isalpha((unsigned char) *cp)) 1.2914 + ++cp; 1.2915 + if (cp - string == 0) 1.2916 +wp = _("time zone abbreviation lacks alphabetic at start"); 1.2917 + if (noise && cp - string > 3) 1.2918 +wp = _("time zone abbreviation has more than 3 alphabetics"); 1.2919 + if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN) 1.2920 +wp = _("time zone abbreviation has too many alphabetics"); 1.2921 + if (wp == NULL && (*cp == '+' || *cp == '-')) { 1.2922 + ++cp; 1.2923 + if (isascii((unsigned char) *cp) && 1.2924 + isdigit((unsigned char) *cp)) 1.2925 + if (*cp++ == '1' && 1.2926 + *cp >= '0' && *cp <= '4') 1.2927 + ++cp; 1.2928 + } 1.2929 + if (*cp != '\0') 1.2930 +wp = _("time zone abbreviation differs from POSIX standard"); 1.2931 + if (wp != NULL) { 1.2932 + wp = ecpyalloc(wp); 1.2933 + wp = ecatalloc(wp, " ("); 1.2934 + wp = ecatalloc(wp, string); 1.2935 + wp = ecatalloc(wp, ")"); 1.2936 + warning(wp); 1.2937 + ifree(wp); 1.2938 + } 1.2939 + } 1.2940 + i = strlen(string) + 1; 1.2941 + if (charcnt + i > TZ_MAX_CHARS) { 1.2942 + error(_("too many, or too long, time zone abbreviations")); 1.2943 + exit(EXIT_FAILURE); 1.2944 + } 1.2945 + (void) strcpy(&chars[charcnt], string); 1.2946 + charcnt += eitol(i); 1.2947 +} 1.2948 + 1.2949 +static int 1.2950 +mkdirs(argname) 1.2951 +char * argname; 1.2952 +{ 1.2953 + register char * name; 1.2954 + register char * cp; 1.2955 + 1.2956 + if (argname == NULL || *argname == '\0') 1.2957 + return 0; 1.2958 + cp = name = ecpyalloc(argname); 1.2959 + while ((cp = strchr(cp + 1, '/')) != 0) { 1.2960 + *cp = '\0'; 1.2961 +#ifndef unix 1.2962 + /* 1.2963 + ** DOS drive specifier? 1.2964 + */ 1.2965 + if (isalpha((unsigned char) name[0]) && 1.2966 + name[1] == ':' && name[2] == '\0') { 1.2967 + *cp = '/'; 1.2968 + continue; 1.2969 + } 1.2970 +#endif /* !defined unix */ 1.2971 + if (!itsdir(name)) { 1.2972 + /* 1.2973 + ** It doesn't seem to exist, so we try to create it. 1.2974 + ** Creation may fail because of the directory being 1.2975 + ** created by some other multiprocessor, so we get 1.2976 + ** to do extra checking. 1.2977 + */ 1.2978 + if (mkdir(name, MKDIR_UMASK) != 0) { 1.2979 + const char *e = strerror(errno); 1.2980 + 1.2981 + if (errno != EEXIST || !itsdir(name)) { 1.2982 + (void) fprintf(stderr, 1.2983 +_("%s: Can't create directory %s: %s\n"), 1.2984 + progname, name, e); 1.2985 + ifree(name); 1.2986 + return -1; 1.2987 + } 1.2988 + } 1.2989 + } 1.2990 + *cp = '/'; 1.2991 + } 1.2992 + ifree(name); 1.2993 + return 0; 1.2994 +} 1.2995 + 1.2996 +static long 1.2997 +eitol(i) 1.2998 +const int i; 1.2999 +{ 1.3000 + long l; 1.3001 + 1.3002 + l = i; 1.3003 + if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) { 1.3004 + (void) fprintf(stderr, 1.3005 + _("%s: %d did not sign extend correctly\n"), 1.3006 + progname, i); 1.3007 + exit(EXIT_FAILURE); 1.3008 + } 1.3009 + return l; 1.3010 +} 1.3011 + 1.3012 +/* 1.3013 +** UNIX was a registered trademark of The Open Group in 2003. 1.3014 +*/