X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/729e4ab9bc6618bc3d8a898e575df7f4019e29ca..HEAD:/icuSources/tools/tzcode/zic.c diff --git a/icuSources/tools/tzcode/zic.c b/icuSources/tools/tzcode/zic.c index 5dc9db01..0d95a002 100644 --- a/icuSources/tools/tzcode/zic.c +++ b/icuSources/tools/tzcode/zic.c @@ -3,15 +3,43 @@ ** 2006-07-17 by Arthur David Olson. */ -static char elsieid[] = "@(#)zic.c 8.18"; +/* Enable extensions and modifications for ICU. */ +#define ICU +/* Continue executing after link failure. Even if ICU is undefined + * (for vanilla zic behavior), ICU_LINKS should be defined, since zic + * appears to fail on the 2003 data the first time through during the + * linking phase. Running zic twice, with ICU_LINKS defined, causes + * links to be handled correctly. */ +#define ICU_LINKS + +#define LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH + +#ifdef ICU +/* These constants are embedded in dynamically generated header + * version.h in the standard tzcode distribution. */ +static char const PKGVERSION[]="N/A"; +static char const TZVERSION[]="N/A"; +static char const REPORT_BUGS_TO[]="N/A"; +#else +#include "version.h" +#endif #include "private.h" #include "locale.h" #include "tzfile.h" -#define ZIC_VERSION '2' +#include +#if U_PLATFORM_IS_DARWIN_BASED || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD || U_PLATFORM == U_PF_SOLARIS +#include +#endif + +#define ZIC_VERSION_PRE_2013 '2' +#define ZIC_VERSION '3' typedef int_fast64_t zic_t; +#define ZIC_MIN INT_FAST64_MIN +#define ZIC_MAX INT_FAST64_MAX +#define SCNdZIC SCNdFAST64 #ifndef ZIC_MAX_ABBR_LEN_WO_WARN #define ZIC_MAX_ABBR_LEN_WO_WARN 6 @@ -26,16 +54,6 @@ typedef int_fast64_t zic_t; #define MKDIR_UMASK 0755 #endif -/* Enable extensions and modifications for ICU. */ -#define ICU - -/* Continue executing after link failure. Even if ICU is undefined - * (for vanilla zic behavior), ICU_LINKS should be defined, since zic - * appears to fail on the 2003 data the first time through during the - * linking phase. Running zic twice, with ICU_LINKS defined, causes - * links to be handled correctly. */ -#define ICU_LINKS - #ifdef ICU #include "tz2icu.h" #endif @@ -53,9 +71,6 @@ typedef int_fast64_t zic_t; #define isascii(x) 1 #endif -#define OFFSET_STRLEN_MAXIMUM (7 + INT_STRLEN_MAXIMUM(long)) -#define RULE_STRLEN_MAXIMUM 8 /* "Mdd.dd.d" */ - #define end(cp) (strchr((cp), '\0')) struct rule { @@ -63,8 +78,8 @@ struct rule { int r_linenum; const char * r_name; - int r_loyear; /* for example, 1986 */ - int r_hiyear; /* for example, 1986 */ + zic_t r_loyear; /* for example, 1986 */ + zic_t r_hiyear; /* for example, 1986 */ const char * r_yrtype; int r_lowasnum; int r_hiwasnum; @@ -75,12 +90,12 @@ struct rule { int r_dayofmonth; int r_wday; - long r_tod; /* time from midnight */ + zic_t r_tod; /* time from midnight */ int r_todisstd; /* above is standard time if TRUE */ /* or wall clock time if FALSE */ int r_todisgmt; /* above is GMT if TRUE */ /* or local time if FALSE */ - long r_stdoff; /* offset from standard time */ + zic_t r_stdoff; /* offset from standard time */ const char * r_abbrvar; /* variable part of abbreviation */ int r_todo; /* a rule to do (used in outzone) */ @@ -100,11 +115,11 @@ struct zone { int z_linenum; const char * z_name; - long z_gmtoff; + zic_t z_gmtoff; const char * z_rule; const char * z_format; - long z_stdoff; + zic_t z_stdoff; struct rule * z_rules; int z_nrules; @@ -119,32 +134,29 @@ extern int link(const char * fromname, const char * toname); extern char * optarg; extern int optind; +#if ! HAVE_LINK +# define link(from, to) (-1) +#endif +#if ! HAVE_SYMLINK +# define symlink(from, to) (-1) +#endif + static void addtt(zic_t starttime, int type); #ifdef ICU -static int addtype(long gmtoff, long rawoff, long dstoff, - const char * abbr, int isdst, +static int addtype(const zic_t gmtoff, const zic_t rawoff, const zic_t dstoff, + char *const abbr, int isdst, int ttisstd, int ttisgmt); #else -static int addtype(long gmtoff, const char * abbr, int isdst, +static int addtype(zic_t gmtoff, const char * abbr, int isdst, int ttisstd, int ttisgmt); #endif static void leapadd(zic_t t, int positive, int rolling, int count); static void adjleap(void); static void associate(void); -static int ciequal(const char * ap, const char * bp); -static void convert(long val, char * buf); -static void convert64(zic_t val, char * buf); static void dolink(const char * fromfield, const char * tofield); -static void doabbr(char * abbr, const char * format, - const char * letters, int isdst, int doquotes); -static void eat(const char * name, int num); -static void eats(const char * name, int num, - const char * rname, int rnum); -static long eitol(int i); -static void error(const char * message); static char ** getfields(char * buf); -static long gethms(const char * string, const char * errstrng, - int signable); +static zic_t gethms(const char * string, const char * errstrng, + int signable); static void infile(const char * filename); static void inleap(char ** fields, int nfields); static void inlink(char ** fields, int nfields); @@ -152,32 +164,18 @@ static void inrule(char ** fields, int nfields); static int inzcont(char ** fields, int nfields); static int inzone(char ** fields, int nfields); static int inzsub(char ** fields, int nfields, int iscont); -static int is32(zic_t x); -static int itsabbr(const char * abbr, const char * word); static int itsdir(const char * name); static int lowerit(int c); -static char * memcheck(char * tocheck); static int mkdirs(char * filename); static void newabbr(const char * abbr); -static long oadd(long t1, long t2); +static zic_t oadd(zic_t t1, zic_t t2); static void outzone(const struct zone * zp, int ntzones); -static void puttzcode(long code, FILE * fp); -static void puttzcode64(zic_t code, FILE * fp); -static int rcomp(const void * leftp, const void * rightp); -static zic_t rpytime(const struct rule * rp, int wantedy); +static zic_t rpytime(const struct rule * rp, zic_t wantedy); static void rulesub(struct rule * rp, const char * loyearp, const char * hiyearp, const char * typep, const char * monthp, const char * dayp, const char * timep); -static int stringoffset(char * result, long offset); -static int stringrule(char * result, const struct rule * rp, - long dstoff, long gmtoff); -static void stringzone(char * result, - const struct zone * zp, int ntzones); -static void setboundaries(void); -static zic_t tadd(zic_t t1, long t2); -static void usage(FILE *stream, int status); -static void writezone(const char * name, const char * string); +static zic_t tadd(zic_t t1, zic_t t2); static int yearistype(int year, const char * type); #ifdef ICU static void emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset, @@ -193,20 +191,19 @@ static int errors; static const char * filename; static int leapcnt; static int leapseen; -static int leapminyear; -static int leapmaxyear; +static zic_t leapminyear; +static zic_t leapmaxyear; static int linenum; static int max_abbrvar_len; static int max_format_len; -static zic_t max_time; -static int max_year; -static zic_t min_time; -static int min_year; +static zic_t max_year; +static zic_t min_year; static int noise; static const char * rfilename; static int rlinenum; static const char * progname; static int timecnt; +static int timecnt_alloc; static int typecnt; /* @@ -292,9 +289,11 @@ static int typecnt; static struct rule * rules; static int nrules; /* number of rules */ +static int nrules_alloc; static struct zone * zones; static int nzones; /* number of zones */ +static int nzones_alloc; struct link { const char * l_filename; @@ -305,6 +304,7 @@ struct link { static struct link * links; static int nlinks; +static int nlinks_alloc; struct lookup { const char * l_word; @@ -316,8 +316,8 @@ struct lookup { * with finalRules[i] occurring before finalRules[i+1] in the year. * Each zone need only store a start year, a standard offset, and an * index into finalRules[]. FinalRules[] are aliases into rules[]. */ -static const struct rule ** finalRules; -static int finalRulesCount; +static const struct rule ** finalRules = NULL; +static int finalRulesCount = 0; #endif static struct lookup const * byword(const char * string, @@ -400,12 +400,12 @@ static const int len_years[2] = { static struct attype { zic_t at; unsigned char type; -} attypes[TZ_MAX_TIMES]; -static long gmtoffs[TZ_MAX_TYPES]; +} * attypes; +static zic_t gmtoffs[TZ_MAX_TYPES]; #ifdef ICU /* gmtoffs[i] = rawoffs[i] + dstoffs[i] */ -static long rawoffs[TZ_MAX_TYPES]; -static long dstoffs[TZ_MAX_TYPES]; +static zic_t rawoffs[TZ_MAX_TYPES]; +static zic_t dstoffs[TZ_MAX_TYPES]; #endif static char isdsts[TZ_MAX_TYPES]; static unsigned char abbrinds[TZ_MAX_TYPES]; @@ -413,42 +413,62 @@ static char ttisstds[TZ_MAX_TYPES]; static char ttisgmts[TZ_MAX_TYPES]; static char chars[TZ_MAX_CHARS]; static zic_t trans[TZ_MAX_LEAPS]; -static long corr[TZ_MAX_LEAPS]; +static zic_t corr[TZ_MAX_LEAPS]; static char roll[TZ_MAX_LEAPS]; /* ** Memory allocation. */ -static char * -memcheck(ptr) -char * const ptr; +static _Noreturn void +memory_exhausted(const char *msg) { - if (ptr == NULL) { - const char *e = strerror(errno); + fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg); + exit(EXIT_FAILURE); +} - (void) fprintf(stderr, _("%s: Memory exhausted: %s\n"), - progname, e); - exit(EXIT_FAILURE); - } +static ATTRIBUTE_PURE size_t +size_product(size_t nitems, size_t itemsize) +{ + if (SIZE_MAX / itemsize < nitems) + memory_exhausted("size overflow"); + return nitems * itemsize; +} + +static ATTRIBUTE_PURE void * +memcheck(void *const ptr) +{ + if (ptr == NULL) + memory_exhausted(strerror(errno)); return ptr; } -#define emalloc(size) memcheck(imalloc(size)) -#define erealloc(ptr, size) memcheck(irealloc((ptr), (size))) +#define emalloc(size) memcheck(malloc(size)) +#define erealloc(ptr, size) memcheck(realloc(ptr, size)) #define ecpyalloc(ptr) memcheck(icpyalloc(ptr)) #define ecatalloc(oldp, newp) memcheck(icatalloc((oldp), (newp))) +static void * +growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc) +{ + if (nitems < *nitems_alloc) + return ptr; + else { + int amax = INT_MAX < SIZE_MAX ? INT_MAX : SIZE_MAX; + if ((amax - 1) / 3 * 2 < *nitems_alloc) + memory_exhausted("int overflow"); + *nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1; + return erealloc(ptr, size_product(*nitems_alloc, itemsize)); + } +} + /* ** Error handling. */ static void -eats(name, num, rname, rnum) -const char * const name; -const int num; -const char * const rname; -const int rnum; +eats(const char *const name, const int num, const char *const rname, + const int rnum) { filename = name; linenum = num; @@ -457,24 +477,21 @@ const int rnum; } static void -eat(name, num) -const char * const name; -const int num; +eat(const char *const name, const int num) { - eats(name, num, (char *) NULL, -1); + eats(name, num, NULL, -1); } -static void -error(string) -const char * const string; +static void ATTRIBUTE_FORMAT((printf, 1, 0)) +verror(const char *const string, va_list args) { /* ** Match the format of "cc" to allow sh users to ** zic ... 2>&1 | error -t "*" -v ** on BSD systems. */ - (void) fprintf(stderr, _("\"%s\", line %d: %s"), - filename, linenum, string); + fprintf(stderr, _("\"%s\", line %d: "), filename, linenum); + vfprintf(stderr, string, args); if (rfilename != NULL) (void) fprintf(stderr, _(" (rule from \"%s\", line %d)"), rfilename, rlinenum); @@ -482,28 +499,35 @@ const char * const string; ++errors; } -static void -warning(string) -const char * const string; +static void ATTRIBUTE_FORMAT((printf, 1, 2)) +error(const char *const string, ...) { - char * cp; + va_list args; + va_start(args, string); + verror(string, args); + va_end(args); +} - cp = ecpyalloc(_("warning: ")); - cp = ecatalloc(cp, string); - error(cp); - ifree(cp); +static void ATTRIBUTE_FORMAT((printf, 1, 2)) +warning(const char *const string, ...) +{ + va_list args; + fprintf(stderr, _("warning: ")); + va_start(args, string); + verror(string, args); + va_end(args); --errors; } -static void +static _Noreturn void usage(FILE *stream, int status) { (void) fprintf(stream, _("%s: usage is %s \ [ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\ \t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\ \n\ -Report bugs to tz@elsie.nci.nih.gov.\n"), - progname, progname); +Report bugs to %s.\n"), + progname, progname, REPORT_BUGS_TO); exit(status); } @@ -541,7 +565,7 @@ emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex) { } /* machine-readable section */ - fprintf(f, "rule %s %s %d %d %d %ld %d %d %ld", + fprintf(f, "rule %s %s %d %d %d %lld %d %d %lld", r->r_name, DYCODE[r->r_dycode], r->r_month, r->r_dayofmonth, (r->r_dycode == DC_DOM ? -1 : r->r_wday), @@ -556,10 +580,10 @@ emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex) { if (r->r_dycode != DC_DOM) { fprintf(f, ", %s", wday_names[r->r_wday].l_word); } - fprintf(f, ", time %ld", r->r_tod); + fprintf(f, ", time %lld", r->r_tod); fprintf(f, ", isstd %d", r->r_todisstd); fprintf(f, ", isgmt %d", r->r_todisgmt); - fprintf(f, ", offset %ld", r->r_stdoff); + fprintf(f, ", offset %lld", r->r_stdoff); fprintf(f, "\n"); } @@ -586,17 +610,15 @@ static const char * leapsec; static const char * yitcommand; int -main(argc, argv) -int argc; -char * argv[]; +main(int argc, char **argv) { register int i; register int j; register int c; -#ifdef unix +#ifdef S_IWGRP (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH)); -#endif /* defined unix */ +#endif #if HAVE_GETTEXT (void) setlocale(LC_ALL, ""); #ifdef TZ_DOMAINDIR @@ -612,7 +634,7 @@ char * argv[]; } for (i = 1; i < argc; ++i) if (strcmp(argv[i], "--version") == 0) { - (void) printf("%s\n", elsieid); + (void) printf("zic %s%s\n", PKGVERSION, TZVERSION); exit(EXIT_SUCCESS); } else if (strcmp(argv[i], "--help") == 0) { usage(stdout, EXIT_SUCCESS); @@ -685,8 +707,6 @@ _("%s: More than one -L option specified\n"), if (yitcommand == NULL) yitcommand = "yearistype"; - setboundaries(); - if (optind < argc && leapsec != NULL) { infile(leapsec); adjleap(); @@ -745,9 +765,7 @@ _("%s: More than one -L option specified\n"), } static void -dolink(fromfield, tofield) -const char * const fromfield; -const char * const tofield; +dolink(const char *const fromfield, const char *const tofield) { register char * fromname; register char * toname; @@ -772,65 +790,87 @@ const char * const tofield; */ if (!itsdir(toname)) (void) remove(toname); - if (link(fromname, toname) != 0) { + if (link(fromname, toname) != 0 + && access(fromname, F_OK) == 0 && !itsdir(fromname)) { int result; if (mkdirs(toname) != 0) exit(EXIT_FAILURE); result = link(fromname, toname); -#if HAVE_SYMLINK - if (result != 0 && - access(fromname, F_OK) == 0 && - !itsdir(fromname)) { - const char *s = tofield; + if (result != 0) { + const char *s = fromfield; + const char *t; register char * symlinkcontents = NULL; - while ((s = strchr(s+1, '/')) != NULL) + do + t = s; + while ((s = strchr(s, '/')) + && ! strncmp (fromfield, tofield, + ++s - fromfield)); + + for (s = tofield + (t - fromfield); + (s = strchr(s, '/')); + s++) symlinkcontents = ecatalloc(symlinkcontents, "../"); - symlinkcontents = - ecatalloc(symlinkcontents, - fromname); - result = symlink(symlinkcontents, - toname); + symlinkcontents = ecatalloc(symlinkcontents, t); + result = symlink(symlinkcontents, toname); if (result == 0) warning(_("hard link failed, symbolic link used")); - ifree(symlinkcontents); + free(symlinkcontents); } -#endif /* HAVE_SYMLINK */ if (result != 0) { - const char *e = strerror(errno); - - (void) fprintf(stderr, - _("%s: Can't link from %s to %s: %s\n"), - progname, fromname, toname, e); + FILE *fp, *tp; + int c; + fp = fopen(fromname, "rb"); + if (!fp) { + const char *e = strerror(errno); + (void) fprintf(stderr, + _("%s: Can't read %s: %s\n"), + progname, fromname, e); + exit(EXIT_FAILURE); + } + tp = fopen(toname, "wb"); + if (!tp) { + const char *e = strerror(errno); + (void) fprintf(stderr, + _("%s: Can't create %s: %s\n"), + progname, toname, e); + exit(EXIT_FAILURE); + } + while ((c = getc(fp)) != EOF) + putc(c, tp); + if (ferror(fp) || fclose(fp)) { + (void) fprintf(stderr, + _("%s: Error reading %s\n"), + progname, fromname); + exit(EXIT_FAILURE); + } + if (ferror(tp) || fclose(tp)) { + (void) fprintf(stderr, + _("%s: Error writing %s\n"), + progname, toname); + exit(EXIT_FAILURE); + } + warning(_("link failed, copy used")); #ifndef ICU_LINKS exit(EXIT_FAILURE); #endif } } - ifree(fromname); - ifree(toname); + free(fromname); + free(toname); } #define TIME_T_BITS_IN_FILE 64 -static void -setboundaries(void) -{ - register int i; - - min_time = -1; - for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i) - min_time *= 2; - max_time = -(min_time + 1); -} +static const zic_t min_time = (zic_t) -1 << (TIME_T_BITS_IN_FILE - 1); +static const zic_t max_time = -1 - ((zic_t) -1 << (TIME_T_BITS_IN_FILE - 1)); static int -itsdir(name) -const char * const name; +itsdir(const char *const name) { register char * myname; register int accres; @@ -838,7 +878,7 @@ const char * const name; myname = ecpyalloc(name); myname = ecatalloc(myname, "/."); accres = access(myname, F_OK); - ifree(myname); + free(myname); return accres == 0; } @@ -851,9 +891,7 @@ const char * const name; */ static int -rcomp(cp1, cp2) -const void * cp1; -const void * cp2; +rcomp(const void *cp1, const void *cp2) { return strcmp(((const struct rule *) cp1)->r_name, ((const struct rule *) cp2)->r_name); @@ -868,8 +906,7 @@ associate(void) register int i, j; if (nrules != 0) { - (void) qsort((void *) rules, (size_t) nrules, - (size_t) sizeof *rules, rcomp); + (void) qsort(rules, nrules, sizeof *rules, rcomp); for (i = 0; i < nrules - 1; ++i) { if (strcmp(rules[i].r_name, rules[i + 1].r_name) != 0) @@ -928,7 +965,7 @@ associate(void) ** a '%s' in the format is a bad thing. */ if (strchr(zp->z_format, '%') != 0) - error(_("%s in ruleless zone")); + error("%s", _("%s in ruleless zone")); } } if (errors) @@ -936,8 +973,7 @@ associate(void) } static void -infile(name) -const char * name; +infile(const char *name) { register FILE * fp; register char ** fields; @@ -961,7 +997,7 @@ const char * name; wantcont = FALSE; for (num = 1; ; ++num) { eat(name, num); - if (fgets(buf, (int) sizeof buf, fp) != buf) + if (fgets(buf, sizeof buf, fp) != buf) break; cp = strchr(buf, '\n'); if (cp == NULL) { @@ -1013,7 +1049,7 @@ _("%s: panic: Invalid l_value %d\n"), exit(EXIT_FAILURE); } } - ifree((char *) fields); + free(fields); } if (ferror(fp)) { (void) fprintf(stderr, _("%s: Error reading %s\n"), @@ -1039,13 +1075,10 @@ _("%s: panic: Invalid l_value %d\n"), ** Call error with errstring and return zero on errors. */ -static long -gethms(string, errstring, signable) -const char * string; -const char * const errstring; -const int signable; +static zic_t +gethms(const char *string, const char *const errstring, const int signable) { - long hh; + zic_t hh; int mm, ss, sign; if (string == NULL || *string == '\0') @@ -1056,22 +1089,22 @@ const int signable; sign = -1; ++string; } else sign = 1; - if (sscanf(string, scheck(string, "%ld"), &hh) == 1) + if (sscanf(string, scheck(string, "%"SCNdZIC), &hh) == 1) mm = ss = 0; - else if (sscanf(string, scheck(string, "%ld:%d"), &hh, &mm) == 2) + else if (sscanf(string, scheck(string, "%"SCNdZIC":%d"), &hh, &mm) == 2) ss = 0; - else if (sscanf(string, scheck(string, "%ld:%d:%d"), + else if (sscanf(string, scheck(string, "%"SCNdZIC":%d:%d"), &hh, &mm, &ss) != 3) { - error(errstring); + error("%s", errstring); return 0; } if (hh < 0 || mm < 0 || mm >= MINSPERHOUR || ss < 0 || ss > SECSPERMIN) { - error(errstring); + error("%s", errstring); return 0; } - if (LONG_MAX / SECSPERHOUR < hh) { + if (ZIC_MAX / SECSPERHOUR < hh) { error(_("time overflow")); return 0; } @@ -1080,14 +1113,12 @@ const int signable; if (noise && (hh > HOURSPERDAY || (hh == HOURSPERDAY && (mm != 0 || ss != 0)))) warning(_("values over 24 hours not handled by pre-2007 versions of zic")); - return oadd(eitol(sign) * hh * eitol(SECSPERHOUR), - eitol(sign) * (eitol(mm) * eitol(SECSPERMIN) + eitol(ss))); + return oadd(sign * hh * SECSPERHOUR, + sign * (mm * SECSPERMIN + ss)); } static void -inrule(fields, nfields) -register char ** const fields; -const int nfields; +inrule(register char **const fields, const int nfields) { static struct rule r; @@ -1108,60 +1139,46 @@ const int nfields; r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); if (max_abbrvar_len < strlen(r.r_abbrvar)) max_abbrvar_len = strlen(r.r_abbrvar); - rules = (struct rule *) (void *) erealloc((char *) rules, - (int) ((nrules + 1) * sizeof *rules)); + rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc); rules[nrules++] = r; } static int -inzone(fields, nfields) -register char ** const fields; -const int nfields; +inzone(register char **const fields, const int nfields) { register int i; - static char * buf; if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) { error(_("wrong number of fields on Zone line")); return FALSE; } if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) { - buf = erealloc(buf, (int) (132 + strlen(TZDEFAULT))); - (void) sprintf(buf, + error( _("\"Zone %s\" line and -l option are mutually exclusive"), TZDEFAULT); - error(buf); return FALSE; } if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) { - buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES))); - (void) sprintf(buf, + error( _("\"Zone %s\" line and -p option are mutually exclusive"), TZDEFRULES); - error(buf); return FALSE; } for (i = 0; i < nzones; ++i) if (zones[i].z_name != NULL && strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) { - buf = erealloc(buf, (int) (132 + - strlen(fields[ZF_NAME]) + - strlen(zones[i].z_filename))); - (void) sprintf(buf, + error( _("duplicate zone name %s (file \"%s\", line %d)"), fields[ZF_NAME], zones[i].z_filename, zones[i].z_linenum); - error(buf); return FALSE; } return inzsub(fields, nfields, FALSE); } static int -inzcont(fields, nfields) -register char ** const fields; -const int nfields; +inzcont(register char **const fields, const int nfields) { if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) { error(_("wrong number of fields on Zone continuation line")); @@ -1171,10 +1188,7 @@ const int nfields; } static int -inzsub(fields, nfields, iscont) -register char ** const fields; -const int nfields; -const int iscont; +inzsub(register char **const fields, const int nfields, const int iscont) { register char * cp; static struct zone z; @@ -1204,7 +1218,7 @@ const int iscont; } z.z_filename = filename; z.z_linenum = linenum; - z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UTC offset"), TRUE); + z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"), TRUE); if ((cp = strchr(fields[i_format], '%')) != 0) { if (*++cp != 's' || strchr(cp, '%') != 0) { error(_("invalid abbreviation format")); @@ -1241,8 +1255,7 @@ const int iscont; return FALSE; } } - zones = (struct zone *) (void *) erealloc((char *) zones, - (int) ((nzones + 1) * sizeof *zones)); + zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc); zones[nzones++] = z; /* ** If there was an UNTIL field on this line, @@ -1252,15 +1265,14 @@ const int iscont; } static void -inleap(fields, nfields) -register char ** const fields; -const int nfields; +inleap(register char ** const fields, const int nfields) { register const char * cp; register const struct lookup * lp; register int i, j; - int year, month, day; - long dayoff, tod; + zic_t year; + int month, day; + zic_t dayoff, tod; zic_t t; if (nfields != LEAP_FIELDS) { @@ -1269,7 +1281,7 @@ const int nfields; } dayoff = 0; cp = fields[LP_YEAR]; - if (sscanf(cp, scheck(cp, "%d"), &year) != 1) { + if (sscanf(cp, scheck(cp, "%"SCNdZIC), &year) != 1) { /* ** Leapin' Lizards! */ @@ -1290,7 +1302,7 @@ const int nfields; --j; i = -len_years[isleap(j)]; } - dayoff = oadd(dayoff, eitol(i)); + dayoff = oadd(dayoff, i); } if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) { error(_("invalid month name")); @@ -1300,7 +1312,7 @@ const int nfields; j = TM_JANUARY; while (j != month) { i = len_months[isleap(year)][j]; - dayoff = oadd(dayoff, eitol(i)); + dayoff = oadd(dayoff, i); ++j; } cp = fields[LP_DAY]; @@ -1309,7 +1321,7 @@ const int nfields; error(_("invalid day of month")); return; } - dayoff = oadd(dayoff, eitol(day - 1)); + dayoff = oadd(dayoff, day - 1); if (dayoff < 0 && !TYPE_SIGNED(zic_t)) { error(_("time before zero")); return; @@ -1356,9 +1368,7 @@ const int nfields; } static void -inlink(fields, nfields) -register char ** const fields; -const int nfields; +inlink(register char **const fields, const int nfields) { struct link l; @@ -1378,20 +1388,18 @@ const int nfields; l.l_linenum = linenum; l.l_from = ecpyalloc(fields[LF_FROM]); l.l_to = ecpyalloc(fields[LF_TO]); - links = (struct link *) (void *) erealloc((char *) links, - (int) ((nlinks + 1) * sizeof *links)); + links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc); links[nlinks++] = l; } static void -rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep) -register struct rule * const rp; -const char * const loyearp; -const char * const hiyearp; -const char * const typep; -const char * const monthp; -const char * const dayp; -const char * const timep; +rulesub(register struct rule *const rp, + const char *const loyearp, + const char *const hiyearp, + const char *const typep, + const char *const monthp, + const char *const dayp, + const char *const timep) { register const struct lookup * lp; register const char * cp; @@ -1429,7 +1437,7 @@ const char * const timep; } } rp->r_tod = gethms(dp, _("invalid time of day"), FALSE); - ifree(dp); + free(dp); /* ** Year work. */ @@ -1438,17 +1446,17 @@ const char * const timep; rp->r_lowasnum = lp == NULL; if (!rp->r_lowasnum) switch ((int) lp->l_value) { case YR_MINIMUM: - rp->r_loyear = INT_MIN; + rp->r_loyear = ZIC_MIN; break; case YR_MAXIMUM: - rp->r_loyear = INT_MAX; + rp->r_loyear = ZIC_MAX; break; default: /* "cannot happen" */ (void) fprintf(stderr, _("%s: panic: Invalid l_value %d\n"), progname, lp->l_value); exit(EXIT_FAILURE); - } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) { + } else if (sscanf(cp, scheck(cp, "%"SCNdZIC), &rp->r_loyear) != 1) { error(_("invalid starting year")); return; } @@ -1457,10 +1465,10 @@ const char * const timep; rp->r_hiwasnum = lp == NULL; if (!rp->r_hiwasnum) switch ((int) lp->l_value) { case YR_MINIMUM: - rp->r_hiyear = INT_MIN; + rp->r_hiyear = ZIC_MIN; break; case YR_MAXIMUM: - rp->r_hiyear = INT_MAX; + rp->r_hiyear = ZIC_MAX; break; case YR_ONLY: rp->r_hiyear = rp->r_loyear; @@ -1470,7 +1478,7 @@ const char * const timep; _("%s: panic: Invalid l_value %d\n"), progname, lp->l_value); exit(EXIT_FAILURE); - } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) { + } else if (sscanf(cp, scheck(cp, "%"SCNdZIC), &rp->r_hiyear) != 1) { error(_("invalid ending year")); return; } @@ -1513,12 +1521,12 @@ const char * const timep; *ep++ = 0; if (*ep++ != '=') { error(_("invalid day of month")); - ifree(dp); + free(dp); return; } if ((lp = byword(dp, wday_names)) == NULL) { error(_("invalid weekday name")); - ifree(dp); + free(dp); return; } rp->r_wday = lp->l_value; @@ -1527,63 +1535,55 @@ const char * const timep; rp->r_dayofmonth <= 0 || (rp->r_dayofmonth > len_months[1][rp->r_month])) { error(_("invalid day of month")); - ifree(dp); + free(dp); return; } } - ifree(dp); + free(dp); } static void -convert(val, buf) -const long val; -char * const buf; +convert(const int_fast32_t val, char *const buf) { register int i; register int shift; + unsigned char *const b = (unsigned char *) buf; for (i = 0, shift = 24; i < 4; ++i, shift -= 8) - buf[i] = val >> shift; + b[i] = val >> shift; } static void -convert64(val, buf) -const zic_t val; -char * const buf; +convert64(const zic_t val, char *const buf) { register int i; register int shift; + unsigned char *const b = (unsigned char *) buf; for (i = 0, shift = 56; i < 8; ++i, shift -= 8) - buf[i] = val >> shift; + b[i] = val >> shift; } static void -puttzcode(val, fp) -const long val; -FILE * const fp; +puttzcode(const int_fast32_t val, FILE *const fp) { char buf[4]; convert(val, buf); - (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); + (void) fwrite(buf, sizeof buf, 1, fp); } static void -puttzcode64(val, fp) -const zic_t val; -FILE * const fp; +puttzcode64(const zic_t val, FILE *const fp) { char buf[8]; convert64(val, buf); - (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); + (void) fwrite(buf, sizeof buf, 1, fp); } static int -atcomp(avp, bvp) -const void * avp; -const void * bvp; +atcomp(const void *avp, const void *bvp) { const zic_t a = ((const struct attype *) avp)->at; const zic_t b = ((const struct attype *) bvp)->at; @@ -1592,16 +1592,13 @@ const void * bvp; } static int -is32(x) -const zic_t x; +is32(const zic_t x) { return INT32_MIN <= x && x <= INT32_MAX; } static void -writezone(name, string) -const char * const name; -const char * const string; +writezone(const char *const name, const char *const string, char version) { register FILE * fp; register int i, j; @@ -1611,15 +1608,15 @@ const char * const string; static char * fullname; static const struct tzhead tzh0; static struct tzhead tzh; - zic_t ats[TZ_MAX_TIMES]; - unsigned char types[TZ_MAX_TIMES]; + zic_t *ats = emalloc(size_product(timecnt, sizeof *ats + 1)); + void *typesptr = ats + timecnt; + unsigned char *types = typesptr; /* ** Sort. */ if (timecnt > 1) - (void) qsort((void *) attypes, (size_t) timecnt, - (size_t) sizeof *attypes, atcomp); + (void) qsort(attypes, timecnt, sizeof *attypes, atcomp); /* ** Optimize. */ @@ -1631,8 +1628,11 @@ const char * const string; fromi = 0; while (fromi < timecnt && attypes[fromi].at < min_time) ++fromi; - if (isdsts[0] == 0) - while (fromi < timecnt && attypes[fromi].type == 0) + /* + ** Remember that type 0 is reserved. + */ + if (isdsts[1] == 0) + while (fromi < timecnt && attypes[fromi].type == 1) ++fromi; /* handled by default rule */ for ( ; fromi < timecnt; ++fromi) { if (toi != 0 && ((attypes[fromi].at + @@ -1687,7 +1687,7 @@ const char * const string; ++leapi32; } fullname = erealloc(fullname, - (int) (strlen(directory) + 1 + strlen(name) + 1)); + strlen(directory) + 1 + strlen(name) + 1); (void) sprintf(fullname, "%s/%s", directory, name); /* ** Remove old file, if any, to snap links. @@ -1714,7 +1714,7 @@ const char * const string; register int thistimei, thistimecnt; register int thisleapi, thisleapcnt; register int thistimelim, thisleaplim; - int writetype[TZ_MAX_TIMES]; + int writetype[TZ_MAX_TYPES]; int typemap[TZ_MAX_TYPES]; register int thistypecnt; char thischars[TZ_MAX_CHARS]; @@ -1734,7 +1734,11 @@ const char * const string; } thistimelim = thistimei + thistimecnt; thisleaplim = thisleapi + thisleapcnt; - for (i = 0; i < typecnt; ++i) + /* + ** Remember that type 0 is reserved. + */ + writetype[0] = FALSE; + for (i = 1; i < typecnt; ++i) writetype[i] = thistimecnt == timecnt; if (thistimecnt == 0) { /* @@ -1750,12 +1754,86 @@ const char * const string; /* ** For America/Godthab and Antarctica/Palmer */ + /* + ** Remember that type 0 is reserved. + */ if (thistimei == 0) - writetype[0] = TRUE; + writetype[1] = TRUE; } +#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH + /* + ** For some pre-2011 systems: if the last-to-be-written + ** standard (or daylight) type has an offset different from the + ** most recently used offset, + ** append an (unused) copy of the most recently used type + ** (to help get global "altzone" and "timezone" variables + ** set correctly). + */ + { + register int mrudst, mrustd, hidst, histd, type; + + hidst = histd = mrudst = mrustd = -1; + for (i = thistimei; i < thistimelim; ++i) + if (isdsts[types[i]]) + mrudst = types[i]; + else mrustd = types[i]; + for (i = 0; i < typecnt; ++i) + if (writetype[i]) { + if (isdsts[i]) + hidst = i; + else histd = i; + } + if (hidst >= 0 && mrudst >= 0 && hidst != mrudst && + gmtoffs[hidst] != gmtoffs[mrudst]) { + isdsts[mrudst] = -1; + type = addtype(gmtoffs[mrudst], +#ifdef ICU + rawoffs[mrudst], dstoffs[mrudst], +#endif + &chars[abbrinds[mrudst]], + TRUE, + ttisstds[mrudst], + ttisgmts[mrudst]); + isdsts[mrudst] = TRUE; + writetype[type] = TRUE; + } + if (histd >= 0 && mrustd >= 0 && histd != mrustd && + gmtoffs[histd] != gmtoffs[mrustd]) { + isdsts[mrustd] = -1; + type = addtype(gmtoffs[mrustd], +#ifdef ICU + rawoffs[mrudst], dstoffs[mrudst], +#endif + &chars[abbrinds[mrustd]], + FALSE, + ttisstds[mrustd], + ttisgmts[mrustd]); + isdsts[mrustd] = FALSE; + writetype[type] = TRUE; + } + } +#endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */ thistypecnt = 0; + /* + ** Potentially, set type 0 to that of lowest-valued time. + */ + if (thistimei > 0) { + for (i = 1; i < typecnt; ++i) + if (writetype[i] && !isdsts[i]) + break; + if (i != types[thistimei - 1]) { + i = types[thistimei - 1]; + gmtoffs[0] = gmtoffs[i]; + isdsts[0] = isdsts[i]; + ttisstds[0] = ttisstds[i]; + ttisgmts[0] = ttisgmts[i]; + abbrinds[0] = abbrinds[i]; + writetype[0] = TRUE; + writetype[i] = FALSE; + } + } for (i = 0; i < typecnt; ++i) - typemap[i] = writetype[i] ? thistypecnt++ : -1; + typemap[i] = writetype[i] ? thistypecnt++ : 0; for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i) indmap[i] = -1; thischarcnt = 0; @@ -1777,8 +1855,7 @@ const char * const string; } indmap[abbrinds[i]] = j; } -#define DO(field) (void) fwrite((void *) tzh.field, \ - (size_t) sizeof tzh.field, (size_t) 1, fp) +#define DO(field) ((void) fwrite(tzh.field, sizeof tzh.field, 1, fp)) tzh = tzh0; #ifdef ICU * (ICUZoneinfoVersion*) &tzh.tzh_reserved = TZ_ICU_VERSION; @@ -1786,13 +1863,13 @@ const char * const string; #else (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); #endif - tzh.tzh_version[0] = ZIC_VERSION; - convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt); - convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt); - convert(eitol(thisleapcnt), tzh.tzh_leapcnt); - convert(eitol(thistimecnt), tzh.tzh_timecnt); - convert(eitol(thistypecnt), tzh.tzh_typecnt); - convert(eitol(thischarcnt), tzh.tzh_charcnt); + tzh.tzh_version[0] = version; + convert(thistypecnt, tzh.tzh_ttisgmtcnt); + convert(thistypecnt, tzh.tzh_ttisstdcnt); + convert(thisleapcnt, tzh.tzh_leapcnt); + convert(thistimecnt, tzh.tzh_timecnt); + convert(thistypecnt, tzh.tzh_typecnt); + convert(thischarcnt, tzh.tzh_charcnt); DO(tzh_magic); DO(tzh_version); DO(tzh_reserved); @@ -1805,22 +1882,19 @@ const char * const string; #undef DO for (i = thistimei; i < thistimelim; ++i) if (pass == 1) - puttzcode((long) ats[i], fp); + puttzcode(ats[i], fp); else puttzcode64(ats[i], fp); for (i = thistimei; i < thistimelim; ++i) { unsigned char uc; uc = typemap[types[i]]; - (void) fwrite((void *) &uc, - (size_t) sizeof uc, - (size_t) 1, - fp); + (void) fwrite(&uc, sizeof uc, 1, fp); } for (i = 0; i < typecnt; ++i) if (writetype[i]) { #ifdef ICU - puttzcode((long) rawoffs[i], fp); - puttzcode((long) dstoffs[i], fp); + puttzcode(rawoffs[i], fp); + puttzcode(dstoffs[i], fp); #else puttzcode(gmtoffs[i], fp); #endif @@ -1828,9 +1902,8 @@ const char * const string; (void) putc((unsigned char) indmap[abbrinds[i]], fp); } if (thischarcnt != 0) - (void) fwrite((void *) thischars, - (size_t) sizeof thischars[0], - (size_t) thischarcnt, fp); + (void) fwrite(thischars, sizeof thischars[0], + thischarcnt, fp); for (i = thisleapi; i < thisleaplim; ++i) { register zic_t todo; @@ -1852,7 +1925,7 @@ const char * const string; todo = tadd(trans[i], -gmtoffs[j]); } else todo = trans[i]; if (pass == 1) - puttzcode((long) todo, fp); + puttzcode(todo, fp); else puttzcode64(todo, fp); puttzcode(corr[i], fp); } @@ -1869,15 +1942,12 @@ const char * const string; progname, fullname); exit(EXIT_FAILURE); } + free(ats); } static void -doabbr(abbr, format, letters, isdst, doquotes) -char * const abbr; -const char * const format; -const char * const letters; -const int isdst; -const int doquotes; +doabbr(char *const abbr, const char *const format, const char *const letters, + const int isdst, const int doquotes) { register char * cp; register char * slashp; @@ -1892,8 +1962,7 @@ const int doquotes; (void) strcpy(abbr, slashp + 1); } else { if (slashp > format) - (void) strncpy(abbr, format, - (unsigned) (slashp - format)); + (void) strncpy(abbr, format, slashp - format); abbr[slashp - format] = '\0'; } if (!doquotes) @@ -1913,8 +1982,7 @@ const int doquotes; } static void -updateminmax(x) -const int x; +updateminmax(const zic_t x) { if (min_year > x) min_year = x; @@ -1923,9 +1991,7 @@ const int x; } static int -stringoffset(result, offset) -char * result; -long offset; +stringoffset(char *result, zic_t offset) { register int hours; register int minutes; @@ -1941,7 +2007,7 @@ long offset; minutes = offset % MINSPERHOUR; offset /= MINSPERHOUR; hours = offset; - if (hours >= HOURSPERDAY) { + if (hours >= HOURSPERDAY * DAYSPERWEEK) { result[0] = '\0'; return -1; } @@ -1955,13 +2021,11 @@ long offset; } static int -stringrule(result, rp, dstoff, gmtoff) -char * result; -const struct rule * const rp; -const long dstoff; -const long gmtoff; +stringrule(char *result, const struct rule *const rp, const zic_t dstoff, + const zic_t gmtoff) { - register long tod; + register zic_t tod = rp->r_tod; + register int compat = 0; result = end(result); if (rp->r_dycode == DC_DOM) { @@ -1972,48 +2036,77 @@ const long gmtoff; total = 0; for (month = 0; month < rp->r_month; ++month) total += len_months[0][month]; - (void) sprintf(result, "J%d", total + rp->r_dayofmonth); + /* Omit the "J" in Jan and Feb, as that's shorter. */ + if (rp->r_month <= 1) + (void) sprintf(result, "%d", total + rp->r_dayofmonth - 1); + else + (void) sprintf(result, "J%d", total + rp->r_dayofmonth); } else { register int week; + register int wday = rp->r_wday; + register int wdayoff; if (rp->r_dycode == DC_DOWGEQ) { - week = 1 + rp->r_dayofmonth / DAYSPERWEEK; - if ((week - 1) * DAYSPERWEEK + 1 != rp->r_dayofmonth) - return -1; + wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK; + if (wdayoff) + compat = 2013; + wday -= wdayoff; + tod += wdayoff * SECSPERDAY; + week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK; } else if (rp->r_dycode == DC_DOWLEQ) { if (rp->r_dayofmonth == len_months[1][rp->r_month]) week = 5; else { - week = 1 + rp->r_dayofmonth / DAYSPERWEEK; - if (week * DAYSPERWEEK - 1 != rp->r_dayofmonth) - return -1; + wdayoff = rp->r_dayofmonth % DAYSPERWEEK; + if (wdayoff) + compat = 2013; + wday -= wdayoff; + tod += wdayoff * SECSPERDAY; + week = rp->r_dayofmonth / DAYSPERWEEK; } } else return -1; /* "cannot happen" */ + if (wday < 0) + wday += DAYSPERWEEK; (void) sprintf(result, "M%d.%d.%d", - rp->r_month + 1, week, rp->r_wday); + rp->r_month + 1, week, wday); } - tod = rp->r_tod; if (rp->r_todisgmt) tod += gmtoff; if (rp->r_todisstd && rp->r_stdoff == 0) tod += dstoff; - if (tod < 0) { - result[0] = '\0'; - return -1; - } if (tod != 2 * SECSPERMIN * MINSPERHOUR) { (void) strcat(result, "/"); if (stringoffset(end(result), tod) != 0) return -1; + if (tod < 0) { + if (compat < 2013) + compat = 2013; + } else if (SECSPERDAY <= tod) { + if (compat < 1994) + compat = 1994; + } } - return 0; + return compat; } -static void -stringzone(result, zpfirst, zonecount) -char * result; -const struct zone * const zpfirst; -const int zonecount; +static int +rule_cmp(struct rule const *a, struct rule const *b) +{ + if (!a) + return -!!b; + if (!b) + return 1; + if (a->r_hiyear != b->r_hiyear) + return a->r_hiyear < b->r_hiyear ? -1 : 1; + if (a->r_month - b->r_month != 0) + return a->r_month - b->r_month; + return a->r_dayofmonth - b->r_dayofmonth; +} + +enum { YEAR_BY_YEAR_ZONE = 1 }; + +static int +stringzone(char *result, const struct zone *const zpfirst, const int zonecount) { register const struct zone * zp; register struct rule * rp; @@ -2021,91 +2114,120 @@ const int zonecount; register struct rule * dstrp; register int i; register const char * abbrvar; + register int compat = 0; + register int c; + struct rule stdr, dstr; result[0] = '\0'; zp = zpfirst + zonecount - 1; stdrp = dstrp = NULL; for (i = 0; i < zp->z_nrules; ++i) { rp = &zp->z_rules[i]; - if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX) + if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX) continue; if (rp->r_yrtype != NULL) continue; if (rp->r_stdoff == 0) { if (stdrp == NULL) stdrp = rp; - else return; + else return -1; } else { if (dstrp == NULL) dstrp = rp; - else return; + else return -1; } } if (stdrp == NULL && dstrp == NULL) { /* ** There are no rules running through "max". - ** Let's find the latest rule. + ** Find the latest std rule in stdabbrrp + ** and latest rule of any type in stdrp. */ + register struct rule *stdabbrrp = NULL; for (i = 0; i < zp->z_nrules; ++i) { rp = &zp->z_rules[i]; - if (stdrp == NULL || rp->r_hiyear > stdrp->r_hiyear || - (rp->r_hiyear == stdrp->r_hiyear && - rp->r_month > stdrp->r_month)) - stdrp = rp; + if (rp->r_stdoff == 0 && rule_cmp(stdabbrrp, rp) < 0) + stdabbrrp = rp; + if (rule_cmp(stdrp, rp) < 0) + stdrp = rp; } - if (stdrp != NULL && stdrp->r_stdoff != 0) - return; /* We end up in DST (a POSIX no-no). */ /* ** Horrid special case: if year is 2037, ** presume this is a zone handled on a year-by-year basis; ** do not try to apply a rule to the zone. */ if (stdrp != NULL && stdrp->r_hiyear == 2037) - return; + return YEAR_BY_YEAR_ZONE; + + if (stdrp != NULL && stdrp->r_stdoff != 0) { + /* Perpetual DST. */ + dstr.r_month = TM_JANUARY; + dstr.r_dycode = DC_DOM; + dstr.r_dayofmonth = 1; + dstr.r_tod = 0; + dstr.r_todisstd = dstr.r_todisgmt = FALSE; + dstr.r_stdoff = stdrp->r_stdoff; + dstr.r_abbrvar = stdrp->r_abbrvar; + stdr.r_month = TM_DECEMBER; + stdr.r_dycode = DC_DOM; + stdr.r_dayofmonth = 31; + stdr.r_tod = SECSPERDAY + stdrp->r_stdoff; + stdr.r_todisstd = stdr.r_todisgmt = FALSE; + stdr.r_stdoff = 0; + stdr.r_abbrvar + = (stdabbrrp ? stdabbrrp->r_abbrvar : ""); + dstrp = &dstr; + stdrp = &stdr; + } } - if (stdrp == NULL && zp->z_nrules != 0) - return; + if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0)) + return -1; abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; doabbr(result, zp->z_format, abbrvar, FALSE, TRUE); if (stringoffset(end(result), -zp->z_gmtoff) != 0) { result[0] = '\0'; - return; + return -1; } if (dstrp == NULL) - return; + return compat; doabbr(end(result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE); if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) if (stringoffset(end(result), -(zp->z_gmtoff + dstrp->r_stdoff)) != 0) { result[0] = '\0'; - return; + return -1; } (void) strcat(result, ","); - if (stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { + c = stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff); + if (c < 0) { result[0] = '\0'; - return; + return -1; } + if (compat < c) + compat = c; (void) strcat(result, ","); - if (stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { + c = stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff); + if (c < 0) { result[0] = '\0'; - return; + return -1; } + if (compat < c) + compat = c; + return compat; } static void -outzone(zpfirst, zonecount) -const struct zone * const zpfirst; -const int zonecount; +outzone(const struct zone * const zpfirst, const int zonecount) { register const struct zone * zp; register struct rule * rp; register int i, j; register int usestart, useuntil; register zic_t starttime, untiltime; - register long gmtoff; - register long stdoff; - register int year; - register long startoff; + register zic_t gmtoff; + register zic_t stdoff; + register zic_t year; + register zic_t startoff; register int startttisstd; register int startttisgmt; register int type; @@ -2114,6 +2236,10 @@ const int zonecount; register char * envvar; register int max_abbr_len; register int max_envvar_len; + register int prodstic; /* all rules are min to max */ + register int compat; + register int do_extend; + register char version; #ifdef ICU int finalRuleYear, finalRuleIndex; const struct rule* finalRule1; @@ -2133,6 +2259,7 @@ const int zonecount; timecnt = 0; typecnt = 0; charcnt = 0; + prodstic = zonecount == 1; /* ** Thanks to Earl Chew ** for noting the need to unconditionally initialize startttisstd. @@ -2142,8 +2269,13 @@ const int zonecount; min_year = max_year = EPOCH_YEAR; if (leapseen) { updateminmax(leapminyear); - updateminmax(leapmaxyear); + updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX)); } + /* + ** Reserve type 0. + */ + gmtoffs[0] = isdsts[0] = ttisstds[0] = ttisgmts[0] = abbrinds[0] = -1; + typecnt = 1; for (i = 0; i < zonecount; ++i) { zp = &zpfirst[i]; if (i < zonecount - 1) @@ -2154,28 +2286,65 @@ const int zonecount; updateminmax(rp->r_loyear); if (rp->r_hiwasnum) updateminmax(rp->r_hiyear); + if (rp->r_lowasnum || rp->r_hiwasnum) + prodstic = FALSE; } } /* ** Generate lots of data if a rule can't cover all future times. */ - stringzone(envvar, zpfirst, zonecount); - if (noise && envvar[0] == '\0') { - register char * wp; - -wp = ecpyalloc(_("no POSIX environment variable for zone")); - wp = ecatalloc(wp, " "); - wp = ecatalloc(wp, zpfirst->z_name); - warning(wp); - ifree(wp); - } - if (envvar[0] == '\0') { - if (min_year >= INT_MIN + YEARSPERREPEAT) - min_year -= YEARSPERREPEAT; - else min_year = INT_MIN; - if (max_year <= INT_MAX - YEARSPERREPEAT) - max_year += YEARSPERREPEAT; - else max_year = INT_MAX; + compat = stringzone(envvar, zpfirst, zonecount); + version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION; + do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE; +#ifdef ICU + do_extend = 0; +#endif + if (noise) { + if (!*envvar) + warning("%s %s", + _("no POSIX environment variable for zone"), + zpfirst->z_name); + else if (compat != 0 && compat != YEAR_BY_YEAR_ZONE) { + /* Circa-COMPAT clients, and earlier clients, might + not work for this zone when given dates before + 1970 or after 2038. */ + warning(_("%s: pre-%d clients may mishandle" + " distant timestamps"), + zpfirst->z_name, compat); + } + } + if (do_extend) { + /* + ** Search through a couple of extra years past the obvious + ** 400, to avoid edge cases. For example, suppose a non-POSIX + ** rule applies from 2012 onwards and has transitions in March + ** and September, plus some one-off transitions in November + ** 2013. If zic looked only at the last 400 years, it would + ** set max_year=2413, with the intent that the 400 years 2014 + ** through 2413 will be repeated. The last transition listed + ** in the tzfile would be in 2413-09, less than 400 years + ** after the last one-off transition in 2013-11. Two years + ** might be overkill, but with the kind of edge cases + ** available we're not sure that one year would suffice. + */ + enum { years_of_observations = YEARSPERREPEAT + 2 }; + + if (min_year >= ZIC_MIN + years_of_observations) + min_year -= years_of_observations; + else min_year = ZIC_MIN; + if (max_year <= ZIC_MAX - years_of_observations) + max_year += years_of_observations; + else max_year = ZIC_MAX; + /* + ** Regardless of any of the above, + ** for a "proDSTic" zone which specifies that its rules + ** always have and always will be in effect, + ** we only need one cycle to define the zone. + */ + if (prodstic) { + min_year = 1900; + max_year = min_year + years_of_observations; + } } /* ** For the benefit of older systems, @@ -2208,42 +2377,78 @@ wp = ecpyalloc(_("no POSIX environment variable for zone")); * them. */ for (j=0; jz_nrules; ++j) { rp = &zp->z_rules[j]; - if (rp->r_hiyear == INT_MAX) { + if (rp->r_hiyear == ZIC_MAX) { + if (rp->r_loyear > finalRuleYear) { + finalRuleYear = rp->r_loyear; + } if (finalRule1 == NULL) { finalRule1 = rp; - finalRuleYear = rp->r_loyear; - } else if (finalRule2 == NULL) { + } else if (finalRule2 == NULL) { finalRule2 = rp; - if (rp->r_loyear > finalRuleYear) { - finalRuleYear = rp->r_loyear; - } } else { error("more than two max rules found (ICU)"); exit(EXIT_FAILURE); } + } else if (rp->r_hiyear >= finalRuleYear) { + /* There might be an overriding non-max rule + * to be applied to a specific year after one of + * max rule's start year. For example, + * + * Rule Foo 2010 max ... + * Rule Foo 2015 only ... + * + * In this case, we need to change the start year of + * the final (max) rules to the next year. */ + finalRuleYear = rp->r_hiyear + 1; + + /* When above adjustment is done, max_year might need + * to be adjusted, so the final rule will be properly + * evaluated and emitted by the later code block. + * + * Note: This may push the start year of the final + * rules ahead by 1 year unnecessarily. For example, + * If there are two rules, non-max rule and max rule + * starting in the same year, such as + * + * Rule Foo 2010 only .... + * Rule Foo 2010 max .... + * + * In this case, the final (max) rule actually starts + * in 2010, instead of 2010. We could make this tool + * more intelligent to detect such situation. But pushing + * final rule start year to 1 year ahead (in the worst case) + * will just populate a few extra transitions, and it still + * works fine. So for now, we're not trying to put additional + * logic to optimize the case. + */ + if (max_year < finalRuleYear) { + max_year = finalRuleYear; + } } } - if (finalRule1 != NULL && finalRule2 == NULL) { - error("only one max rule found (ICU)"); - exit(EXIT_FAILURE); - } if (finalRule1 != NULL) { - if (finalRule1->r_stdoff == finalRule2->r_stdoff) { - /* America/Resolute in 2009a uses a pair of rules - * which does not change the offset. ICU ignores - * such rules without actual time transitions. */ + if (finalRule2 == NULL) { + warning("only one max rule found (ICU)"); finalRuleYear = finalRuleIndex = -1; - finalRule1 = finalRule2 = NULL; + finalRule1 = NULL; } else { - /* Swap if necessary so finalRule1 occurs before - * finalRule2 */ - if (finalRule1->r_month > finalRule2->r_month) { - const struct rule* t = finalRule1; - finalRule1 = finalRule2; - finalRule2 = t; + if (finalRule1->r_stdoff == finalRule2->r_stdoff) { + /* America/Resolute in 2009a uses a pair of rules + * which does not change the offset. ICU ignores + * such rules without actual time transitions. */ + finalRuleYear = finalRuleIndex = -1; + finalRule1 = finalRule2 = NULL; + } else { + /* Swap if necessary so finalRule1 occurs before + * finalRule2 */ + if (finalRule1->r_month > finalRule2->r_month) { + const struct rule* t = finalRule1; + finalRule1 = finalRule2; + finalRule2 = t; + } + /* Add final rule to our list */ + finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2); } - /* Add final rule to our list */ - finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2); } } } @@ -2252,7 +2457,7 @@ wp = ecpyalloc(_("no POSIX environment variable for zone")); if (zp->z_nrules == 0) { stdoff = zp->z_stdoff; doabbr(startbuf, zp->z_format, - (char *) NULL, stdoff != 0, FALSE); + NULL, stdoff != 0, FALSE); type = addtype(oadd(zp->z_gmtoff, stdoff), #ifdef ICU zp->z_gmtoff, stdoff, @@ -2284,12 +2489,12 @@ wp = ecpyalloc(_("no POSIX environment variable for zone")); for ( ; ; ) { register int k; register zic_t jtime, ktime; - register long offset; + register zic_t offset; INITIALIZE(ktime); if (useuntil) { /* - ** Turn untiltime into UTC + ** Turn untiltime into UT ** assuming the current gmtoff and ** stdoff values. */ @@ -2363,16 +2568,12 @@ wp = ecpyalloc(_("no POSIX environment variable for zone")); * transition defined by the final rule. Otherwise * we may see unexpected offset shift at the * begining of the year when the final rule takes - * effect. */ - - /* ICU currently can support signed int32 transition - * times. Thus, the transitions in year 2038 may be - * truncated. At this moment (tzdata2008g), only - * Rule Brazil is impacted by this limitation, because - * the final set of rules are starting in 2038. Although - * this code put the first couple of transitions populated - * by the final rules, they might be dropped off when - * collecting transition times by tz2icu. */ + * effect. + * + * Note: This may results some 64bit second transitions + * at the very end (year 2038). ICU 4.2 or older releases + * cannot handle 64bit second transitions and they are + * dropped from zoneinfo.txt. */ emit_icu_zone(icuFile, zpfirst->z_name, zp->z_gmtoff, rp, finalRuleIndex, year + 1); @@ -2433,16 +2634,52 @@ error(_("can't determine time zone abbreviation to use just after until time")); starttime = tadd(starttime, -gmtoff); } } - writezone(zpfirst->z_name, envvar); - ifree(startbuf); - ifree(ab); - ifree(envvar); + if (do_extend) { + /* + ** If we're extending the explicitly listed observations + ** for 400 years because we can't fill the POSIX-TZ field, + ** check whether we actually ended up explicitly listing + ** observations through that period. If there aren't any + ** near the end of the 400-year period, add a redundant + ** one at the end of the final year, to make it clear + ** that we are claiming to have definite knowledge of + ** the lack of transitions up to that point. + */ + struct rule xr; + struct attype *lastat; + xr.r_month = TM_JANUARY; + xr.r_dycode = DC_DOM; + xr.r_dayofmonth = 1; + xr.r_tod = 0; + for (lastat = &attypes[0], i = 1; i < timecnt; i++) + if (attypes[i].at > lastat->at) + lastat = &attypes[i]; + if (lastat->at < rpytime(&xr, max_year - 1)) { + /* + ** Create new type code for the redundant entry, + ** to prevent it being optimised away. + */ + if (typecnt >= TZ_MAX_TYPES) { + error(_("too many local time types")); + exit(EXIT_FAILURE); + } + gmtoffs[typecnt] = gmtoffs[lastat->type]; + isdsts[typecnt] = isdsts[lastat->type]; + ttisstds[typecnt] = ttisstds[lastat->type]; + ttisgmts[typecnt] = ttisgmts[lastat->type]; + abbrinds[typecnt] = abbrinds[lastat->type]; + ++typecnt; + addtt(rpytime(&xr, max_year + 1), typecnt-1); + } + } + writezone(zpfirst->z_name, envvar, version); + free(startbuf); + free(ab); + free(envvar); } static void -addtt(starttime, type) -const zic_t starttime; -int type; +addtt(const zic_t starttime, int type) { if (starttime <= min_time || (timecnt == 1 && attypes[0].at < min_time)) { @@ -2462,10 +2699,7 @@ int type; timecnt = 0; type = 0; } - if (timecnt >= TZ_MAX_TIMES) { - error(_("too many transitions?!")); - exit(EXIT_FAILURE); - } + attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc); attypes[timecnt].at = starttime; attypes[timecnt].type = type; ++timecnt; @@ -2473,18 +2707,12 @@ int type; static int #ifdef ICU -addtype(gmtoff, rawoff, dstoff, abbr, isdst, ttisstd, ttisgmt) -const long gmtoff; -const long rawoff; -const long dstoff; +addtype(const zic_t gmtoff, const zic_t rawoff, const zic_t dstoff, char *const abbr, const int isdst, + const int ttisstd, const int ttisgmt) #else -addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt) -const long gmtoff; +addtype(const zic_t gmtoff, const char *const abbr, const int isdst, + const int ttisstd, const int ttisgmt) #endif -const char * const abbr; -const int isdst; -const int ttisstd; -const int ttisgmt; { register int i, j; @@ -2503,11 +2731,11 @@ const int ttisgmt; #ifdef ICU if (isdst != (dstoff != 0)) { error(_("internal error - addtype called with bad isdst/dstoff")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } if (gmtoff != (rawoff + dstoff)) { error(_("internal error - addtype called with bad gmt/raw/dstoff")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } #endif /* @@ -2533,7 +2761,7 @@ const int ttisgmt; exit(EXIT_FAILURE); } if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) { - error(_("UTC offset out of range")); + error(_("UT offset out of range")); exit(EXIT_FAILURE); } gmtoffs[i] = gmtoff; @@ -2556,11 +2784,7 @@ const int ttisgmt; } static void -leapadd(t, positive, rolling, count) -const zic_t t; -const int positive; -const int rolling; -int count; +leapadd(const zic_t t, const int positive, const int rolling, int count) { register int i, j; @@ -2583,7 +2807,7 @@ int count; roll[j] = roll[j - 1]; } trans[i] = t; - corr[i] = positive ? 1L : eitol(-count); + corr[i] = positive ? 1 : -count; roll[i] = rolling; ++leapcnt; } while (positive && --count != 0); @@ -2593,7 +2817,7 @@ static void adjleap(void) { register int i; - register long last = 0; + register zic_t last = 0; /* ** propagate leap seconds forward @@ -2605,16 +2829,14 @@ adjleap(void) } static int -yearistype(year, type) -const int year; -const char * const type; +yearistype(const int year, const char *const type) { static char * buf; int result; if (type == NULL || *type == '\0') return TRUE; - buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type))); + buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type)); (void) sprintf(buf, "%s %d %s", yitcommand, year, type); result = system(buf); if (WIFEXITED(result)) switch (WEXITSTATUS(result)) { @@ -2631,17 +2853,15 @@ const char * const type; } static int -lowerit(a) -int a; +lowerit(int a) { a = (unsigned char) a; return (isascii(a) && isupper(a)) ? tolower(a) : a; } -static int -ciequal(ap, bp) /* case-insensitive equality */ -register const char * ap; -register const char * bp; +/* case-insensitive equality */ +static ATTRIBUTE_PURE int +ciequal(register const char *ap, register const char *bp) { while (lowerit(*ap) == lowerit(*bp++)) if (*ap++ == '\0') @@ -2649,10 +2869,8 @@ register const char * bp; return FALSE; } -static int -itsabbr(abbr, word) -register const char * abbr; -register const char * word; +static ATTRIBUTE_PURE int +itsabbr(register const char *abbr, register const char *word) { if (lowerit(*abbr) != lowerit(*word)) return FALSE; @@ -2665,10 +2883,9 @@ register const char * word; return TRUE; } -static const struct lookup * -byword(word, table) -register const char * const word; -register const struct lookup * const table; +static ATTRIBUTE_PURE const struct lookup * +byword(register const char *const word, + register const struct lookup *const table) { register const struct lookup * foundlp; register const struct lookup * lp; @@ -2695,8 +2912,7 @@ register const struct lookup * const table; } static char ** -getfields(cp) -register char * cp; +getfields(register char *cp) { register char * dp; register char ** array; @@ -2704,8 +2920,7 @@ register char * cp; if (cp == NULL) return NULL; - array = (char **) (void *) - emalloc((int) ((strlen(cp) + 1) * sizeof *array)); + array = emalloc(size_product(strlen(cp) + 1, sizeof *array)); nsubs = 0; for ( ; ; ) { while (isascii((unsigned char) *cp) && @@ -2736,38 +2951,28 @@ register char * cp; return array; } -static long -oadd(t1, t2) -const long t1; -const long t2; +static ATTRIBUTE_PURE zic_t +oadd(const zic_t t1, const zic_t t2) { - register long t; - - t = t1 + t2; - if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { + if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2) { error(_("time overflow")); exit(EXIT_FAILURE); } - return t; + return t1 + t2; } -static zic_t -tadd(t1, t2) -const zic_t t1; -const long t2; +static ATTRIBUTE_PURE zic_t +tadd(const zic_t t1, const zic_t t2) { - register zic_t t; - if (t1 == max_time && t2 > 0) return max_time; if (t1 == min_time && t2 < 0) return min_time; - t = t1 + t2; - if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { + if (t1 < 0 ? t2 < min_time - t1 : max_time - t1 < t2) { error(_("time overflow")); exit(EXIT_FAILURE); } - return t; + return t1 + t2; } /* @@ -2776,17 +2981,15 @@ const long t2; */ static zic_t -rpytime(rp, wantedy) -register const struct rule * const rp; -register const int wantedy; +rpytime(register const struct rule *const rp, register const zic_t wantedy) { - register int y, m, i; - register long dayoff; /* with a nod to Margaret O. */ - register zic_t t; + register int m, i; + register zic_t dayoff; /* with a nod to Margaret O. */ + register zic_t t, y; - if (wantedy == INT_MIN) + if (wantedy == ZIC_MIN) return min_time; - if (wantedy == INT_MAX) + if (wantedy == ZIC_MAX) return max_time; dayoff = 0; m = TM_JANUARY; @@ -2799,11 +3002,11 @@ register const int wantedy; --y; i = -len_years[isleap(y)]; } - dayoff = oadd(dayoff, eitol(i)); + dayoff = oadd(dayoff, i); } while (m != rp->r_month) { i = len_months[isleap(y)][m]; - dayoff = oadd(dayoff, eitol(i)); + dayoff = oadd(dayoff, i); ++m; } i = rp->r_dayofmonth; @@ -2816,12 +3019,12 @@ register const int wantedy; } } --i; - dayoff = oadd(dayoff, eitol(i)); + dayoff = oadd(dayoff, i); if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) { - register long wday; + register zic_t wday; -#define LDAYSPERWEEK ((long) DAYSPERWEEK) - wday = eitol(EPOCH_WDAY); +#define LDAYSPERWEEK ((zic_t) DAYSPERWEEK) + wday = EPOCH_WDAY; /* ** Don't trust mod of negative numbers. */ @@ -2832,14 +3035,14 @@ register const int wantedy; if (wday < 0) wday += LDAYSPERWEEK; } - while (wday != eitol(rp->r_wday)) + while (wday != rp->r_wday) if (rp->r_dycode == DC_DOWGEQ) { - dayoff = oadd(dayoff, (long) 1); + dayoff = oadd(dayoff, 1); if (++wday >= LDAYSPERWEEK) wday = 0; ++i; } else { - dayoff = oadd(dayoff, (long) -1); + dayoff = oadd(dayoff, -1); if (--wday < 0) wday = LDAYSPERWEEK - 1; --i; @@ -2859,31 +3062,30 @@ will not work with pre-2004 versions of zic")); } static void -newabbr(string) -const char * const string; +newabbr(const char *const string) { register int i; if (strcmp(string, GRANDPARENTED) != 0) { register const char * cp; - register char * wp; + const char * mp; /* ** Want one to ZIC_MAX_ABBR_LEN_WO_WARN alphabetics ** optionally followed by a + or - and a number from 1 to 14. */ cp = string; - wp = NULL; + mp = NULL; while (isascii((unsigned char) *cp) && isalpha((unsigned char) *cp)) ++cp; if (cp - string == 0) -wp = _("time zone abbreviation lacks alphabetic at start"); - if (noise && cp - string > 3) -wp = _("time zone abbreviation has more than 3 alphabetics"); +mp = _("time zone abbreviation lacks alphabetic at start"); + if (noise && cp - string < 3) +mp = _("time zone abbreviation has fewer than 3 alphabetics"); if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN) -wp = _("time zone abbreviation has too many alphabetics"); - if (wp == NULL && (*cp == '+' || *cp == '-')) { +mp = _("time zone abbreviation has too many alphabetics"); + if (mp == NULL && (*cp == '+' || *cp == '-')) { ++cp; if (isascii((unsigned char) *cp) && isdigit((unsigned char) *cp)) @@ -2892,15 +3094,9 @@ wp = _("time zone abbreviation has too many alphabetics"); ++cp; } if (*cp != '\0') -wp = _("time zone abbreviation differs from POSIX standard"); - if (wp != NULL) { - wp = ecpyalloc(wp); - wp = ecatalloc(wp, " ("); - wp = ecatalloc(wp, string); - wp = ecatalloc(wp, ")"); - warning(wp); - ifree(wp); - } +mp = _("time zone abbreviation differs from POSIX standard"); + if (mp != NULL) + warning("%s (%s)", mp, string); } i = strlen(string) + 1; if (charcnt + i > TZ_MAX_CHARS) { @@ -2908,12 +3104,11 @@ wp = _("time zone abbreviation differs from POSIX standard"); exit(EXIT_FAILURE); } (void) strcpy(&chars[charcnt], string); - charcnt += eitol(i); + charcnt += i; } static int -mkdirs(argname) -char * argname; +mkdirs(char *argname) { register char * name; register char * cp; @@ -2923,7 +3118,7 @@ char * argname; cp = name = ecpyalloc(argname); while ((cp = strchr(cp + 1, '/')) != 0) { *cp = '\0'; -#ifndef unix +#ifdef HAVE_DOS_FILE_NAMES /* ** DOS drive specifier? */ @@ -2932,7 +3127,7 @@ char * argname; *cp = '/'; continue; } -#endif /* !defined unix */ +#endif if (!itsdir(name)) { /* ** It doesn't seem to exist, so we try to create it. @@ -2947,33 +3142,17 @@ char * argname; (void) fprintf(stderr, _("%s: Can't create directory %s: %s\n"), progname, name, e); - ifree(name); + free(name); return -1; } } } *cp = '/'; } - ifree(name); + free(name); return 0; } -static long -eitol(i) -const int i; -{ - long l; - - l = i; - if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) { - (void) fprintf(stderr, - _("%s: %d did not sign extend correctly\n"), - progname, i); - exit(EXIT_FAILURE); - } - return l; -} - /* ** UNIX was a registered trademark of The Open Group in 2003. */