version 1.24, 2009/04/23 01:39:47 |
version 1.25, 2009/12/31 22:49:16 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
|
/* |
|
** This file is in the public domain, so clarified as of |
|
** 2006-07-17 by Arthur David Olson. |
|
*/ |
|
|
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
#ifndef lint |
#ifndef lint |
Line 7 __RCSID("$NetBSD$"); |
|
Line 11 __RCSID("$NetBSD$"); |
|
#endif /* !defined NOID */ |
#endif /* !defined NOID */ |
#endif /* !defined lint */ |
#endif /* !defined lint */ |
|
|
static char elsieid[] = "@(#)zic.c 7.116"; |
static char elsieid[] = "@(#)zic.c 8.20"; |
|
|
#include "private.h" |
#include "private.h" |
#include "locale.h" |
#include "locale.h" |
#include "tzfile.h" |
#include "tzfile.h" |
|
|
|
#define ZIC_VERSION '2' |
|
|
|
typedef int_fast64_t zic_t; |
|
|
|
#ifndef ZIC_MAX_ABBR_LEN_WO_WARN |
|
#define ZIC_MAX_ABBR_LEN_WO_WARN 6 |
|
#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */ |
|
|
#if HAVE_SYS_STAT_H |
#if HAVE_SYS_STAT_H |
#include "sys/stat.h" |
#include "sys/stat.h" |
#endif |
#endif |
Line 26 static char elsieid[] = "@(#)zic.c 7.116 |
|
Line 38 static char elsieid[] = "@(#)zic.c 7.116 |
|
|
|
/* |
/* |
** On some ancient hosts, predicates like `isspace(C)' are defined |
** On some ancient hosts, predicates like `isspace(C)' are defined |
** only if isascii(C) || C == EOF. Modern hosts obey the C Standard, |
** only if isascii(C) || C == EOF. Modern hosts obey the C Standard, |
** which says they are defined only if C == ((unsigned char) C) || C == EOF. |
** which says they are defined only if C == ((unsigned char) C) || C == EOF. |
** Neither the C Standard nor Posix require that `isascii' exist. |
** Neither the C Standard nor Posix require that `isascii' exist. |
** For portability, we check both ancient and modern requirements. |
** For portability, we check both ancient and modern requirements. |
Line 37 static char elsieid[] = "@(#)zic.c 7.116 |
|
Line 49 static char elsieid[] = "@(#)zic.c 7.116 |
|
#define isascii(x) 1 |
#define isascii(x) 1 |
#endif |
#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 { |
struct rule { |
const char * r_filename; |
const char * r_filename; |
int r_linenum; |
int r_linenum; |
|
|
int r_loyear; /* for example, 1986 */ |
int r_loyear; /* for example, 1986 */ |
int r_hiyear; /* for example, 1986 */ |
int r_hiyear; /* for example, 1986 */ |
const char * r_yrtype; |
const char * r_yrtype; |
|
int r_lowasnum; |
|
int r_hiwasnum; |
|
|
int r_month; /* 0..11 */ |
int r_month; /* 0..11 */ |
|
|
|
|
const char * r_abbrvar; /* variable part of abbreviation */ |
const char * r_abbrvar; /* variable part of abbreviation */ |
|
|
int r_todo; /* a rule to do (used in outzone) */ |
int r_todo; /* a rule to do (used in outzone) */ |
time_t r_temp; /* used in outzone */ |
zic_t r_temp; /* used in outzone */ |
}; |
}; |
|
|
/* |
/* |
|
|
int z_nrules; |
int z_nrules; |
|
|
struct rule z_untilrule; |
struct rule z_untilrule; |
time_t z_untiltime; |
zic_t z_untiltime; |
}; |
}; |
|
|
extern int getopt P((int argc, char * const argv[], |
extern int getopt(int argc, char * const argv[], |
const char * options)); |
const char * options); |
extern int link P((const char * fromname, const char * toname)); |
extern int link(const char * fromname, const char * toname); |
extern char * optarg; |
extern char * optarg; |
extern int optind; |
extern int optind; |
|
|
static int atcomp P((const void *, const void *)); |
static void addtt(zic_t starttime, int type); |
static void addtt P((time_t starttime, int type)); |
static int addtype(long gmtoff, const char * abbr, int isdst, |
static int addtype P((long gmtoff, const char * abbr, int isdst, |
int ttisstd, int ttisgmt); |
int ttisstd, int ttisgmt)); |
static void leapadd(zic_t t, int positive, int rolling, int count); |
static void leapadd P((time_t t, int positive, int rolling, int count)); |
static void adjleap(void); |
static void adjleap P((void)); |
static void associate(void); |
static void associate P((void)); |
static int ciequal(const char * ap, const char * bp); |
static int ciequal P((const char * ap, const char * bp)); |
static void convert(long val, char * buf); |
static void convert P((long val, char * buf)); |
static void convert64(zic_t val, char * buf); |
static void dolink P((const char * fromfile, const char * tofile)); |
static void dolink(const char * fromfield, const char * tofield); |
static void doabbr P((char * abbr, int abbrlen, const char * format, |
static void doabbr(char * abbr, const int, const char * format, |
const char * letters, int isdst)); |
const char * letters, int isdst, int doquotes); |
static void eat P((const char * name, int num)); |
static void eat(const char * name, int num); |
static void eats P((const char * name, int num, |
static void eats(const char * name, int num, |
const char * rname, int rnum)); |
const char * rname, int rnum); |
static long eitol P((int i)); |
static long eitol(int i); |
static void error P((const char * message)); |
static void error(const char * message); |
static char ** getfields P((char * buf)); |
static char ** getfields(char * buf); |
static long gethms P((const char * string, const char * errstrng, |
static long gethms(const char * string, const char * errstrng, |
int signable)); |
int signable); |
static void infile P((const char * filename)); |
static void infile(const char * filename); |
static void inleap P((char ** fields, int nfields)); |
static void inleap(char ** fields, int nfields); |
static void inlink P((char ** fields, int nfields)); |
static void inlink(char ** fields, int nfields); |
static void inrule P((char ** fields, int nfields)); |
static void inrule(char ** fields, int nfields); |
static int inzcont P((char ** fields, int nfields)); |
static int inzcont(char ** fields, int nfields); |
static int inzone P((char ** fields, int nfields)); |
static int inzone(char ** fields, int nfields); |
static int inzsub P((char ** fields, int nfields, int iscont)); |
static int inzsub(char ** fields, int nfields, int iscont); |
static int itsabbr P((const char * abbr, const char * word)); |
static int is32(zic_t x); |
static int itsdir P((const char * name)); |
static int itsabbr(const char * abbr, const char * word); |
static int lowerit P((int c)); |
static int itsdir(const char * name); |
int main P((int, char **)); |
static int lowerit(int c); |
static char * memcheck P((char * tocheck)); |
int main(int, char **); |
static int mkdirs P((char * filename)); |
static char * memcheck(char * tocheck); |
static void newabbr P((const char * abbr)); |
static int mkdirs(char * filename); |
static long oadd P((long t1, long t2)); |
static void newabbr(const char * abbr); |
static void outzone P((const struct zone * zp, int ntzones)); |
static long oadd(long t1, long t2); |
static void puttzcode P((long code, FILE * fp)); |
static void outzone(const struct zone * zp, int ntzones); |
static int rcomp P((const void * leftp, const void * rightp)); |
static void puttzcode(long code, FILE * fp); |
static time_t rpytime P((const struct rule * rp, int wantedy)); |
static void puttzcode64(zic_t code, FILE * fp); |
static void rulesub P((struct rule * rp, |
static int rcomp(const void * leftp, const void * rightp); |
|
static zic_t rpytime(const struct rule * rp, int wantedy); |
|
static void rulesub(struct rule * rp, |
const char * loyearp, const char * hiyearp, |
const char * loyearp, const char * hiyearp, |
const char * typep, const char * monthp, |
const char * typep, const char * monthp, |
const char * dayp, const char * timep)); |
const char * dayp, const char * timep); |
static void setboundaries P((void)); |
static int stringoffset(char * result, long offset); |
static time_t tadd P((time_t t1, long t2)); |
static int stringrule(char * result, const struct rule * rp, |
static void usage P((void)); |
long dstoff, long gmtoff); |
static void warning P((const char * const)); |
static void stringzone(char * result, const int, |
static void writezone P((const char * name)); |
const struct zone * zp, int ntzones); |
static int yearistype P((int year, const char * type)); |
static void setboundaries(void); |
|
static zic_t tadd(zic_t t1, long t2); |
#if !(HAVE_STRERROR - 0) |
static void usage(FILE *stream, int status); |
static char * strerror P((int)); |
static void warning(const char * const); |
#endif /* !(HAVE_STRERROR - 0) */ |
static void writezone(const char * name, const char * string); |
|
static int yearistype(int year, const char * type); |
|
static int atcomp(const void *avp, const void *bvp); |
|
static void updateminmax(int x); |
|
|
static int charcnt; |
static int charcnt; |
static int errors; |
static int errors; |
static const char * filename; |
static const char * filename; |
static int leapcnt; |
static int leapcnt; |
|
static int leapseen; |
|
static int leapminyear; |
|
static int leapmaxyear; |
static int linenum; |
static int linenum; |
static time_t max_time; |
static int max_abbrvar_len; |
|
static int max_format_len; |
|
static zic_t max_time; |
static int max_year; |
static int max_year; |
static int max_year_representable; |
static zic_t min_time; |
static time_t min_time; |
|
static int min_year; |
static int min_year; |
static int min_year_representable; |
|
static int noise; |
static int noise; |
static const char * rfilename; |
static const char * rfilename; |
static int rlinenum; |
static int rlinenum; |
|
|
const int l_value; |
const int l_value; |
}; |
}; |
|
|
static struct lookup const * byword P((const char * string, |
static struct lookup const * byword(const char * string, |
const struct lookup * lp)); |
const struct lookup * lp); |
|
|
static struct lookup const line_codes[] = { |
static struct lookup const line_codes[] = { |
{ "Rule", LC_RULE }, |
{ "Rule", LC_RULE }, |
Line 348 static const int len_years[2] = { |
|
Line 375 static const int len_years[2] = { |
|
}; |
}; |
|
|
static struct attype { |
static struct attype { |
time_t at; |
zic_t at; |
unsigned char type; |
unsigned char type; |
} attypes[TZ_MAX_TIMES]; |
} attypes[TZ_MAX_TIMES]; |
static long gmtoffs[TZ_MAX_TYPES]; |
static long gmtoffs[TZ_MAX_TYPES]; |
Line 357 static unsigned char abbrinds[TZ_MAX_TYP |
|
Line 384 static unsigned char abbrinds[TZ_MAX_TYP |
|
static char ttisstds[TZ_MAX_TYPES]; |
static char ttisstds[TZ_MAX_TYPES]; |
static char ttisgmts[TZ_MAX_TYPES]; |
static char ttisgmts[TZ_MAX_TYPES]; |
static char chars[TZ_MAX_CHARS]; |
static char chars[TZ_MAX_CHARS]; |
static time_t trans[TZ_MAX_LEAPS]; |
static zic_t trans[TZ_MAX_LEAPS]; |
static long corr[TZ_MAX_LEAPS]; |
static long corr[TZ_MAX_LEAPS]; |
static char roll[TZ_MAX_LEAPS]; |
static char roll[TZ_MAX_LEAPS]; |
|
|
Line 374 char * const ptr; |
|
Line 401 char * const ptr; |
|
|
|
(void) fprintf(stderr, _("%s: Memory exhausted: %s\n"), |
(void) fprintf(stderr, _("%s: Memory exhausted: %s\n"), |
progname, e); |
progname, e); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
return ptr; |
return ptr; |
} |
} |
Line 388 char * const ptr; |
|
Line 415 char * const ptr; |
|
** Error handling. |
** Error handling. |
*/ |
*/ |
|
|
#if !(HAVE_STRERROR - 0) |
|
static char * |
|
strerror(errnum) |
|
int errnum; |
|
{ |
|
extern char * sys_errlist[]; |
|
extern int sys_nerr; |
|
|
|
return (errnum > 0 && errnum <= sys_nerr) ? |
|
sys_errlist[errnum] : _("Unknown system error"); |
|
} |
|
#endif /* !(HAVE_STRERROR - 0) */ |
|
|
|
static void |
static void |
eats(name, num, rname, rnum) |
eats(name, num, rname, rnum) |
const char * const name; |
const char * const name; |
Line 454 const char * const string; |
|
Line 468 const char * const string; |
|
} |
} |
|
|
static void |
static void |
usage P((void)) |
usage(FILE *stream, int status) |
{ |
{ |
(void) fprintf(stderr, _("%s: usage is %s [ --version ] [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"), |
(void) fprintf(stream, _("%s: usage is %s \ |
progname, progname); |
[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\ |
(void) exit(EXIT_FAILURE); |
\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\ |
|
\n\ |
|
Report bugs to tz@elsie.nci.nih.gov.\n"), |
|
progname, progname); |
|
exit(status); |
} |
} |
|
|
static const char * psxrules; |
static const char * psxrules; |
Line 466 static const char * lcltime; |
|
Line 484 static const char * lcltime; |
|
static const char * directory; |
static const char * directory; |
static const char * leapsec; |
static const char * leapsec; |
static const char * yitcommand; |
static const char * yitcommand; |
static int sflag = FALSE; |
|
|
|
int |
int |
main(argc, argv) |
main(argc, argv) |
|
|
(void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); |
(void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); |
#endif /* defined TEXTDOMAINDIR */ |
#endif /* defined TEXTDOMAINDIR */ |
(void) textdomain(TZ_DOMAIN); |
(void) textdomain(TZ_DOMAIN); |
#endif /* HAVE_GETTEXT - 0 */ |
#endif /* HAVE_GETTEXT */ |
progname = argv[0]; |
progname = argv[0]; |
|
if (TYPE_BIT(zic_t) < 64) { |
|
(void) fprintf(stderr, "%s: %s\n", progname, |
|
_("wild compilation-time specification of zic_t")); |
|
exit(EXIT_FAILURE); |
|
} |
for (i = 1; i < argc; ++i) |
for (i = 1; i < argc; ++i) |
if (strcmp(argv[i], "--version") == 0) { |
if (strcmp(argv[i], "--version") == 0) { |
(void) printf("%s\n", elsieid); |
(void) printf("%s\n", elsieid); |
(void) exit(EXIT_SUCCESS); |
exit(EXIT_SUCCESS); |
|
} else if (strcmp(argv[i], "--help") == 0) { |
|
usage(stdout, EXIT_SUCCESS); |
} |
} |
while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1) |
while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1) |
switch (c) { |
switch (c) { |
default: |
default: |
usage(); |
usage(stderr, EXIT_FAILURE); |
case 'd': |
case 'd': |
if (directory == NULL) |
if (directory == NULL) |
directory = optarg; |
directory = optarg; |
|
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: More than one -d option specified\n"), |
_("%s: More than one -d option specified\n"), |
progname); |
progname); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
break; |
break; |
case 'l': |
case 'l': |
Line 514 _("%s: More than one -d option specified |
|
Line 538 _("%s: More than one -d option specified |
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: More than one -l option specified\n"), |
_("%s: More than one -l option specified\n"), |
progname); |
progname); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
break; |
break; |
case 'p': |
case 'p': |
Line 524 _("%s: More than one -l option specified |
|
Line 548 _("%s: More than one -l option specified |
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: More than one -p option specified\n"), |
_("%s: More than one -p option specified\n"), |
progname); |
progname); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
break; |
break; |
case 'y': |
case 'y': |
Line 534 _("%s: More than one -p option specified |
|
Line 558 _("%s: More than one -p option specified |
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: More than one -y option specified\n"), |
_("%s: More than one -y option specified\n"), |
progname); |
progname); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
break; |
break; |
case 'L': |
case 'L': |
Line 544 _("%s: More than one -y option specified |
|
Line 568 _("%s: More than one -y option specified |
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: More than one -L option specified\n"), |
_("%s: More than one -L option specified\n"), |
progname); |
progname); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
break; |
break; |
case 'v': |
case 'v': |
noise = TRUE; |
noise = TRUE; |
break; |
break; |
case 's': |
case 's': |
sflag = TRUE; |
(void) printf("%s: -s ignored\n", progname); |
break; |
break; |
} |
} |
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) |
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) |
usage(); /* usage message by request */ |
usage(stderr, EXIT_FAILURE); /* usage message by request */ |
if (directory == NULL) |
if (directory == NULL) |
directory = TZDIR; |
directory = TZDIR; |
if (yitcommand == NULL) |
if (yitcommand == NULL) |
Line 571 _("%s: More than one -L option specified |
|
Line 595 _("%s: More than one -L option specified |
|
for (i = optind; i < argc; ++i) |
for (i = optind; i < argc; ++i) |
infile(argv[i]); |
infile(argv[i]); |
if (errors) |
if (errors) |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
associate(); |
associate(); |
for (i = 0; i < nzones; i = j) { |
for (i = 0; i < nzones; i = j) { |
/* |
/* |
Line 587 _("%s: More than one -L option specified |
|
Line 611 _("%s: More than one -L option specified |
|
for (i = 0; i < nlinks; ++i) { |
for (i = 0; i < nlinks; ++i) { |
eat(links[i].l_filename, links[i].l_linenum); |
eat(links[i].l_filename, links[i].l_linenum); |
dolink(links[i].l_from, links[i].l_to); |
dolink(links[i].l_from, links[i].l_to); |
|
if (noise) |
|
for (j = 0; j < nlinks; ++j) |
|
if (strcmp(links[i].l_to, |
|
links[j].l_from) == 0) |
|
warning(_("link to link")); |
} |
} |
if (lcltime != NULL) { |
if (lcltime != NULL) { |
eat("command line", 1); |
eat("command line", 1); |
Line 600 _("%s: More than one -L option specified |
|
Line 629 _("%s: More than one -L option specified |
|
} |
} |
|
|
static void |
static void |
dolink(fromfile, tofile) |
dolink(fromfield, tofield) |
const char * const fromfile; |
const char * const fromfield; |
const char * const tofile; |
const char * const tofield; |
{ |
{ |
register char * fromname; |
register char * fromname; |
register char * toname; |
register char * toname; |
|
|
if (fromfile[0] == '/') |
if (fromfield[0] == '/') |
fromname = ecpyalloc(fromfile); |
fromname = ecpyalloc(fromfield); |
else { |
else { |
fromname = ecpyalloc(directory); |
fromname = ecpyalloc(directory); |
fromname = ecatalloc(fromname, "/"); |
fromname = ecatalloc(fromname, "/"); |
fromname = ecatalloc(fromname, fromfile); |
fromname = ecatalloc(fromname, fromfield); |
} |
} |
if (tofile[0] == '/') |
if (tofield[0] == '/') |
toname = ecpyalloc(tofile); |
toname = ecpyalloc(tofield); |
else { |
else { |
toname = ecpyalloc(directory); |
toname = ecpyalloc(directory); |
toname = ecatalloc(toname, "/"); |
toname = ecatalloc(toname, "/"); |
toname = ecatalloc(toname, tofile); |
toname = ecatalloc(toname, tofield); |
} |
} |
/* |
/* |
** We get to be careful here since |
** We get to be careful here since |
Line 631 const char * const tofile; |
|
Line 660 const char * const tofile; |
|
int result; |
int result; |
|
|
if (mkdirs(toname) != 0) |
if (mkdirs(toname) != 0) |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
|
|
result = link(fromname, toname); |
result = link(fromname, toname); |
#if (HAVE_SYMLINK - 0) |
#if HAVE_SYMLINK |
if (result != 0 && |
if (result != 0 && |
access(fromname, F_OK) == 0 && |
access(fromname, F_OK) == 0 && |
!itsdir(fromname)) { |
!itsdir(fromname)) { |
const char *s = tofile; |
const char *s = tofield; |
register char * symlinkcontents = NULL; |
register char * symlinkcontents = NULL; |
while ((s = strchr(s+1, '/')) != NULL) |
|
symlinkcontents = ecatalloc(symlinkcontents, "../"); |
while ((s = strchr(s+1, '/')) != NULL) |
symlinkcontents = ecatalloc(symlinkcontents, fromfile); |
symlinkcontents = |
|
ecatalloc(symlinkcontents, |
result = symlink(symlinkcontents, toname); |
"../"); |
if (result == 0) |
symlinkcontents = |
|
ecatalloc(symlinkcontents, |
|
fromname); |
|
result = symlink(symlinkcontents, |
|
toname); |
|
if (result == 0) |
warning(_("hard link failed, symbolic link used")); |
warning(_("hard link failed, symbolic link used")); |
ifree(symlinkcontents); |
ifree(symlinkcontents); |
} |
} |
#endif |
#endif /* HAVE_SYMLINK */ |
if (result != 0) { |
if (result != 0) { |
const char *e = strerror(errno); |
const char *e = strerror(errno); |
|
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: Can't link from %s to %s: %s\n"), |
_("%s: Can't link from %s to %s: %s\n"), |
progname, fromname, toname, e); |
progname, fromname, toname, e); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
} |
} |
ifree(fromname); |
ifree(fromname); |
ifree(toname); |
ifree(toname); |
} |
} |
|
|
#ifndef INT_MAX |
#define TIME_T_BITS_IN_FILE 64 |
#define INT_MAX ((int) (((unsigned)~0)>>1)) |
|
#endif /* !defined INT_MAX */ |
|
|
|
#ifndef INT_MIN |
|
#define INT_MIN ((int) ~(((unsigned)~0)>>1)) |
|
#endif /* !defined INT_MIN */ |
|
|
|
/* |
|
** The tz file format currently allows at most 32-bit quantities. |
|
** This restriction should be removed before signed 32-bit values |
|
** wrap around in 2038, but unfortunately this will require a |
|
** change to the tz file format. |
|
*/ |
|
|
|
#define MAX_BITS_IN_FILE 32 |
|
#define TIME_T_BITS_IN_FILE ((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE) |
|
|
|
static void |
static void |
setboundaries P((void)) |
setboundaries(void) |
{ |
{ |
if (TYPE_SIGNED(time_t)) { |
register int i; |
min_time = ~ (time_t) 0; |
|
min_time <<= TIME_T_BITS_IN_FILE - 1; |
min_time = -1; |
max_time = ~ (time_t) 0 - min_time; |
for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i) |
if (sflag) |
min_time *= 2; |
min_time = 0; |
max_time = -(min_time + 1); |
} else { |
|
min_time = 0; |
|
max_time = 2 - sflag; |
|
max_time <<= TIME_T_BITS_IN_FILE - 1; |
|
--max_time; |
|
} |
|
min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year; |
|
max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year; |
|
min_year_representable = min_year; |
|
max_year_representable = max_year; |
|
} |
} |
|
|
static int |
static int |
Line 734 const void * cp2; |
|
Line 742 const void * cp2; |
|
} |
} |
|
|
static void |
static void |
associate P((void)) |
associate(void) |
{ |
{ |
register struct zone * zp; |
register struct zone * zp; |
register struct rule * rp; |
register struct rule * rp; |
Line 796 associate P((void)) |
|
Line 804 associate P((void)) |
|
*/ |
*/ |
eat(zp->z_filename, zp->z_linenum); |
eat(zp->z_filename, zp->z_linenum); |
zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"), |
zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"), |
TRUE); |
TRUE); |
/* |
/* |
** Note, though, that if there's no rule, |
** Note, though, that if there's no rule, |
** a '%s' in the format is a bad thing. |
** a '%s' in the format is a bad thing. |
Line 806 associate P((void)) |
|
Line 814 associate P((void)) |
|
} |
} |
} |
} |
if (errors) |
if (errors) |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
|
|
static void |
static void |
Line 830 const char * name; |
|
Line 838 const char * name; |
|
|
|
(void) fprintf(stderr, _("%s: Can't open %s: %s\n"), |
(void) fprintf(stderr, _("%s: Can't open %s: %s\n"), |
progname, name, e); |
progname, name, e); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
wantcont = FALSE; |
wantcont = FALSE; |
for (num = 1; ; ++num) { |
for (num = 1; ; ++num) { |
Line 840 const char * name; |
|
Line 848 const char * name; |
|
cp = strchr(buf, '\n'); |
cp = strchr(buf, '\n'); |
if (cp == NULL) { |
if (cp == NULL) { |
error(_("line too long")); |
error(_("line too long")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
*cp = '\0'; |
*cp = '\0'; |
fields = getfields(buf); |
fields = getfields(buf); |
Line 884 _("%s: Leap line in non leap seconds fil |
|
Line 892 _("%s: Leap line in non leap seconds fil |
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: panic: Invalid l_value %d\n"), |
_("%s: panic: Invalid l_value %d\n"), |
progname, lp->l_value); |
progname, lp->l_value); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
} |
} |
ifree((char *) fields); |
ifree((char *) fields); |
Line 892 _("%s: panic: Invalid l_value %d\n"), |
|
Line 900 _("%s: panic: Invalid l_value %d\n"), |
|
if (ferror(fp)) { |
if (ferror(fp)) { |
(void) fprintf(stderr, _("%s: Error reading %s\n"), |
(void) fprintf(stderr, _("%s: Error reading %s\n"), |
progname, filename); |
progname, filename); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
if (fp != stdin && fclose(fp)) { |
if (fp != stdin && fclose(fp)) { |
const char *e = strerror(errno); |
const char *e = strerror(errno); |
|
|
(void) fprintf(stderr, _("%s: Error closing %s: %s\n"), |
(void) fprintf(stderr, _("%s: Error closing %s: %s\n"), |
progname, filename, e); |
progname, filename, e); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
if (wantcont) |
if (wantcont) |
error(_("expected continuation line not found")); |
error(_("expected continuation line not found")); |
Line 919 const char * string; |
|
Line 927 const char * string; |
|
const char * const errstring; |
const char * const errstring; |
const int signable; |
const int signable; |
{ |
{ |
int hh, mm, ss, sign; |
long hh; |
|
int mm, ss, sign; |
|
|
if (string == NULL || *string == '\0') |
if (string == NULL || *string == '\0') |
return 0; |
return 0; |
Line 929 const int signable; |
|
Line 938 const int signable; |
|
sign = -1; |
sign = -1; |
++string; |
++string; |
} else sign = 1; |
} else sign = 1; |
if (sscanf(string, scheck(string, "%d"), &hh) == 1) |
if (sscanf(string, scheck(string, "%ld"), &hh) == 1) |
mm = ss = 0; |
mm = ss = 0; |
else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2) |
else if (sscanf(string, scheck(string, "%ld:%d"), &hh, &mm) == 2) |
ss = 0; |
ss = 0; |
else if (sscanf(string, scheck(string, "%d:%d:%d"), |
else if (sscanf(string, scheck(string, "%ld:%d:%d"), |
&hh, &mm, &ss) != 3) { |
&hh, &mm, &ss) != 3) { |
error(errstring); |
error(errstring); |
return 0; |
return 0; |
} |
} |
if ((hh < 0 || hh >= HOURSPERDAY || |
if (hh < 0 || |
mm < 0 || mm >= MINSPERHOUR || |
mm < 0 || mm >= MINSPERHOUR || |
ss < 0 || ss > SECSPERMIN) && |
ss < 0 || ss > SECSPERMIN) { |
!(hh == HOURSPERDAY && mm == 0 && ss == 0)) { |
|
error(errstring); |
error(errstring); |
return 0; |
return 0; |
} |
} |
if (noise && hh == HOURSPERDAY) |
if (LONG_MAX / SECSPERHOUR < hh) { |
|
error(_("time overflow")); |
|
return 0; |
|
} |
|
if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0) |
warning(_("24:00 not handled by pre-1998 versions of zic")); |
warning(_("24:00 not handled by pre-1998 versions of zic")); |
return eitol(sign) * |
if (noise && (hh > HOURSPERDAY || |
(eitol(hh * MINSPERHOUR + mm) * |
(hh == HOURSPERDAY && (mm != 0 || ss != 0)))) |
eitol(SECSPERMIN) + eitol(ss)); |
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))); |
} |
} |
|
|
static void |
static void |
Line 974 const int nfields; |
|
Line 988 const int nfields; |
|
fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); |
fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); |
r.r_name = ecpyalloc(fields[RF_NAME]); |
r.r_name = ecpyalloc(fields[RF_NAME]); |
r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); |
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, |
rules = (struct rule *) (void *) erealloc((char *) rules, |
(int) ((nrules + 1) * sizeof *rules)); |
(int) ((nrules + 1) * sizeof *rules)); |
rules[nrules++] = r; |
rules[nrules++] = r; |
Line 1079 const int iscont; |
|
Line 1095 const int iscont; |
|
} |
} |
z.z_rule = ecpyalloc(fields[i_rule]); |
z.z_rule = ecpyalloc(fields[i_rule]); |
z.z_format = ecpyalloc(fields[i_format]); |
z.z_format = ecpyalloc(fields[i_format]); |
|
if (max_format_len < strlen(z.z_format)) |
|
max_format_len = strlen(z.z_format); |
hasuntil = nfields > i_untilyear; |
hasuntil = nfields > i_untilyear; |
if (hasuntil) { |
if (hasuntil) { |
z.z_untilrule.r_filename = filename; |
z.z_untilrule.r_filename = filename; |
Line 1099 const int iscont; |
|
Line 1117 const int iscont; |
|
zones[nzones - 1].z_untiltime > min_time && |
zones[nzones - 1].z_untiltime > min_time && |
zones[nzones - 1].z_untiltime < max_time && |
zones[nzones - 1].z_untiltime < max_time && |
zones[nzones - 1].z_untiltime >= z.z_untiltime) { |
zones[nzones - 1].z_untiltime >= z.z_untiltime) { |
error(_("Zone continuation line end time is not after end time of previous line")); |
error(_( |
|
"Zone continuation line end time is not after end time of previous line" |
|
)); |
return FALSE; |
return FALSE; |
} |
} |
} |
} |
Line 1123 const int nfields; |
|
Line 1143 const int nfields; |
|
register int i, j; |
register int i, j; |
int year, month, day; |
int year, month, day; |
long dayoff, tod; |
long dayoff, tod; |
time_t t; |
zic_t t; |
|
|
if (nfields != LEAP_FIELDS) { |
if (nfields != LEAP_FIELDS) { |
error(_("wrong number of fields on Leap line")); |
error(_("wrong number of fields on Leap line")); |
Line 1132 const int nfields; |
|
Line 1152 const int nfields; |
|
dayoff = 0; |
dayoff = 0; |
cp = fields[LP_YEAR]; |
cp = fields[LP_YEAR]; |
if (sscanf(cp, scheck(cp, "%d"), &year) != 1) { |
if (sscanf(cp, scheck(cp, "%d"), &year) != 1) { |
/* |
/* |
* Leapin' Lizards! |
** Leapin' Lizards! |
*/ |
*/ |
error(_("invalid leaping year")); |
error(_("invalid leaping year")); |
return; |
return; |
} |
} |
|
if (!leapseen || leapmaxyear < year) |
|
leapmaxyear = year; |
|
if (!leapseen || leapminyear > year) |
|
leapminyear = year; |
|
leapseen = TRUE; |
j = EPOCH_YEAR; |
j = EPOCH_YEAR; |
while (j != year) { |
while (j != year) { |
if (year > j) { |
if (year > j) { |
Line 1167 const int nfields; |
|
Line 1192 const int nfields; |
|
return; |
return; |
} |
} |
dayoff = oadd(dayoff, eitol(day - 1)); |
dayoff = oadd(dayoff, eitol(day - 1)); |
if (dayoff < 0 && !TYPE_SIGNED(time_t)) { |
if (dayoff < 0 && !TYPE_SIGNED(zic_t)) { |
error(_("time before zero")); |
error(_("time before zero")); |
return; |
return; |
} |
} |
Line 1179 const int nfields; |
|
Line 1204 const int nfields; |
|
error(_("time too large")); |
error(_("time too large")); |
return; |
return; |
} |
} |
t = (time_t) dayoff * SECSPERDAY; |
t = (zic_t) dayoff * SECSPERDAY; |
tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE); |
tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE); |
cp = fields[LP_CORR]; |
cp = fields[LP_CORR]; |
{ |
{ |
Line 1203 const int nfields; |
|
Line 1228 const int nfields; |
|
return; |
return; |
} |
} |
if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) { |
if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) { |
error(_("illegal Rolling/Stationary field on Leap line")); |
error(_( |
|
"illegal Rolling/Stationary field on Leap line" |
|
)); |
return; |
return; |
} |
} |
leapadd(tadd(t, tod), positive, lp->l_value, count); |
leapadd(tadd(t, tod), positive, lp->l_value, count); |
Line 1290 const char * const timep; |
|
Line 1317 const char * const timep; |
|
*/ |
*/ |
cp = loyearp; |
cp = loyearp; |
lp = byword(cp, begin_years); |
lp = byword(cp, begin_years); |
if (lp != NULL) switch ((int) lp->l_value) { |
rp->r_lowasnum = lp == NULL; |
|
if (!rp->r_lowasnum) switch ((int) lp->l_value) { |
case YR_MINIMUM: |
case YR_MINIMUM: |
rp->r_loyear = INT_MIN; |
rp->r_loyear = INT_MIN; |
break; |
break; |
Line 1301 const char * const timep; |
|
Line 1329 const char * const timep; |
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: panic: Invalid l_value %d\n"), |
_("%s: panic: Invalid l_value %d\n"), |
progname, lp->l_value); |
progname, lp->l_value); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) { |
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) { |
error(_("invalid starting year")); |
error(_("invalid starting year")); |
return; |
return; |
} else if (noise) { |
|
if (rp->r_loyear < min_year_representable) |
|
warning(_("starting year too low to be represented")); |
|
else if (rp->r_loyear > max_year_representable) |
|
warning(_("starting year too high to be represented")); |
|
} |
} |
cp = hiyearp; |
cp = hiyearp; |
if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) { |
lp = byword(cp, end_years); |
|
rp->r_hiwasnum = lp == NULL; |
|
if (!rp->r_hiwasnum) switch ((int) lp->l_value) { |
case YR_MINIMUM: |
case YR_MINIMUM: |
rp->r_hiyear = INT_MIN; |
rp->r_hiyear = INT_MIN; |
break; |
break; |
Line 1326 const char * const timep; |
|
Line 1351 const char * const timep; |
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: panic: Invalid l_value %d\n"), |
_("%s: panic: Invalid l_value %d\n"), |
progname, lp->l_value); |
progname, lp->l_value); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) { |
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) { |
error(_("invalid ending year")); |
error(_("invalid ending year")); |
return; |
return; |
} else if (noise) { |
|
if (rp->r_loyear < min_year_representable) |
|
warning(_("ending year too low to be represented")); |
|
else if (rp->r_loyear > max_year_representable) |
|
warning(_("ending year too high to be represented")); |
|
} |
} |
if (rp->r_loyear > rp->r_hiyear) { |
if (rp->r_loyear > rp->r_hiyear) { |
error(_("starting year greater than ending year")); |
error(_("starting year greater than ending year")); |
Line 1349 const char * const timep; |
|
Line 1369 const char * const timep; |
|
} |
} |
rp->r_yrtype = ecpyalloc(typep); |
rp->r_yrtype = ecpyalloc(typep); |
} |
} |
if (rp->r_loyear < min_year && rp->r_loyear > 0) |
|
min_year = rp->r_loyear; |
|
/* |
/* |
** Day work. |
** Day work. |
** Accept things such as: |
** Accept things such as: |
Line 1404 const long val; |
|
Line 1422 const long val; |
|
char * const buf; |
char * const buf; |
{ |
{ |
register int i; |
register int i; |
register long shift; |
register int shift; |
|
|
for (i = 0, shift = 24; i < 4; ++i, shift -= 8) |
for (i = 0, shift = 24; i < 4; ++i, shift -= 8) |
buf[i] = val >> shift; |
buf[i] = val >> shift; |
} |
} |
|
|
static void |
static void |
|
convert64(val, buf) |
|
const zic_t val; |
|
char * const buf; |
|
{ |
|
register int i; |
|
register int shift; |
|
|
|
for (i = 0, shift = 56; i < 8; ++i, shift -= 8) |
|
buf[i] = val >> shift; |
|
} |
|
|
|
static void |
puttzcode(val, fp) |
puttzcode(val, fp) |
const long val; |
const long val; |
FILE * const fp; |
FILE * const fp; |
Line 1421 FILE * const fp; |
|
Line 1451 FILE * const fp; |
|
(void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); |
(void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); |
} |
} |
|
|
|
static void |
|
puttzcode64(val, fp) |
|
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); |
|
} |
|
|
static int |
static int |
atcomp(avp, bvp) |
atcomp(avp, bvp) |
const void * avp; |
const void * avp; |
const void * bvp; |
const void * bvp; |
{ |
{ |
if (((const struct attype *) avp)->at < ((const struct attype *) bvp)->at) |
const zic_t a = ((const struct attype *) avp)->at; |
return -1; |
const zic_t b = ((const struct attype *) bvp)->at; |
else if (((const struct attype *) avp)->at > ((const struct attype *) bvp)->at) |
|
return 1; |
return (a < b) ? -1 : (a > b); |
else return 0; |
} |
|
|
|
static int |
|
is32(x) |
|
const zic_t x; |
|
{ |
|
return INT32_MIN <= x && x <= INT32_MAX; |
} |
} |
|
|
static void |
static void |
writezone(name) |
writezone(name, string) |
const char * const name; |
const char * const name; |
|
const char * const string; |
{ |
{ |
register FILE * fp; |
register FILE * fp; |
register int i, j; |
register int i, j; |
static char * fullname; |
register int leapcnt32, leapi32; |
static struct tzhead tzh; |
register int timecnt32, timei32; |
time_t ats[TZ_MAX_TIMES]; |
register int pass; |
unsigned char types[TZ_MAX_TIMES]; |
static char * fullname; |
|
static const struct tzhead tzh0; |
|
static struct tzhead tzh; |
|
zic_t ats[TZ_MAX_TIMES]; |
|
unsigned char types[TZ_MAX_TIMES]; |
|
|
/* |
/* |
** Sort. |
** Sort. |
Line 1465 const char * const name; |
|
Line 1517 const char * const name; |
|
while (fromi < timecnt && attypes[fromi].type == 0) |
while (fromi < timecnt && attypes[fromi].type == 0) |
++fromi; /* handled by default rule */ |
++fromi; /* handled by default rule */ |
for ( ; fromi < timecnt; ++fromi) { |
for ( ; fromi < timecnt; ++fromi) { |
if (toi != 0 |
if (toi != 0 && ((attypes[fromi].at + |
&& ((attypes[fromi].at |
gmtoffs[attypes[toi - 1].type]) <= |
+ gmtoffs[attypes[toi - 1].type]) |
(attypes[toi - 1].at + gmtoffs[toi == 1 ? 0 |
<= (attypes[toi - 1].at |
: attypes[toi - 2].type]))) { |
+ gmtoffs[toi == 1 ? 0 |
attypes[toi - 1].type = |
: attypes[toi - 2].type]))) { |
attypes[fromi].type; |
attypes[toi - 1].type = attypes[fromi].type; |
continue; |
continue; |
|
} |
} |
if (toi == 0 || |
if (toi == 0 || |
attypes[toi - 1].type != attypes[fromi].type) |
attypes[toi - 1].type != attypes[fromi].type) |
Line 1487 const char * const name; |
|
Line 1538 const char * const name; |
|
ats[i] = attypes[i].at; |
ats[i] = attypes[i].at; |
types[i] = attypes[i].type; |
types[i] = attypes[i].type; |
} |
} |
|
/* |
|
** Correct for leap seconds. |
|
*/ |
|
for (i = 0; i < timecnt; ++i) { |
|
j = leapcnt; |
|
while (--j >= 0) |
|
if (ats[i] > trans[j] - corr[j]) { |
|
ats[i] = tadd(ats[i], corr[j]); |
|
break; |
|
} |
|
} |
|
/* |
|
** Figure out 32-bit-limited starts and counts. |
|
*/ |
|
timecnt32 = timecnt; |
|
timei32 = 0; |
|
leapcnt32 = leapcnt; |
|
leapi32 = 0; |
|
while (timecnt32 > 0 && !is32(ats[timecnt32 - 1])) |
|
--timecnt32; |
|
while (timecnt32 > 0 && !is32(ats[timei32])) { |
|
--timecnt32; |
|
++timei32; |
|
} |
|
while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1])) |
|
--leapcnt32; |
|
while (leapcnt32 > 0 && !is32(trans[leapi32])) { |
|
--leapcnt32; |
|
++leapi32; |
|
} |
fullname = erealloc(fullname, |
fullname = erealloc(fullname, |
(int) (strlen(directory) + 1 + strlen(name) + 1)); |
(int) (strlen(directory) + 1 + strlen(name) + 1)); |
(void) sprintf(fullname, "%s/%s", directory, name); /* XXX: sprintf is safe */ |
(void) sprintf(fullname, "%s/%s", directory, name); /* XXX: sprintf is safe */ |
Line 1498 const char * const name; |
|
Line 1579 const char * const name; |
|
|
|
(void) fprintf(stderr, _("%s: Can't remove %s: %s\n"), |
(void) fprintf(stderr, _("%s: Can't remove %s: %s\n"), |
progname, fullname, e); |
progname, fullname, e); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
if ((fp = fopen(fullname, "wb")) == NULL) { |
if ((fp = fopen(fullname, "wb")) == NULL) { |
if (mkdirs(fullname) != 0) |
if (mkdirs(fullname) != 0) |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
if ((fp = fopen(fullname, "wb")) == NULL) { |
if ((fp = fopen(fullname, "wb")) == NULL) { |
const char *e = strerror(errno); |
const char *e = strerror(errno); |
|
|
(void) fprintf(stderr, _("%s: Can't create %s: %s\n"), |
(void) fprintf(stderr, _("%s: Can't create %s: %s\n"), |
progname, fullname, e); |
progname, fullname, e); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
} |
} |
convert(eitol(typecnt), tzh.tzh_ttisgmtcnt); |
for (pass = 1; pass <= 2; ++pass) { |
convert(eitol(typecnt), tzh.tzh_ttisstdcnt); |
register int thistimei, thistimecnt; |
convert(eitol(leapcnt), tzh.tzh_leapcnt); |
register int thisleapi, thisleapcnt; |
convert(eitol(timecnt), tzh.tzh_timecnt); |
register int thistimelim, thisleaplim; |
convert(eitol(typecnt), tzh.tzh_typecnt); |
int writetype[TZ_MAX_TIMES]; |
convert(eitol(charcnt), tzh.tzh_charcnt); |
int typemap[TZ_MAX_TYPES]; |
(void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); |
register int thistypecnt; |
#define DO(field) (void) fwrite((void *) tzh.field, (size_t) sizeof tzh.field, (size_t) 1, fp) |
char thischars[TZ_MAX_CHARS]; |
DO(tzh_magic); |
char thischarcnt; |
DO(tzh_reserved); |
int indmap[TZ_MAX_CHARS]; |
DO(tzh_ttisgmtcnt); |
|
DO(tzh_ttisstdcnt); |
if (pass == 1) { |
DO(tzh_leapcnt); |
thistimei = timei32; |
DO(tzh_timecnt); |
thistimecnt = timecnt32; |
DO(tzh_typecnt); |
thisleapi = leapi32; |
DO(tzh_charcnt); |
thisleapcnt = leapcnt32; |
|
} else { |
|
thistimei = 0; |
|
thistimecnt = timecnt; |
|
thisleapi = 0; |
|
thisleapcnt = leapcnt; |
|
} |
|
thistimelim = thistimei + thistimecnt; |
|
thisleaplim = thisleapi + thisleapcnt; |
|
for (i = 0; i < typecnt; ++i) |
|
writetype[i] = thistimecnt == timecnt; |
|
if (thistimecnt == 0) { |
|
/* |
|
** No transition times fall in the current |
|
** (32- or 64-bit) window. |
|
*/ |
|
if (typecnt != 0) |
|
writetype[typecnt - 1] = TRUE; |
|
} else { |
|
for (i = thistimei - 1; i < thistimelim; ++i) |
|
if (i >= 0) |
|
writetype[types[i]] = TRUE; |
|
/* |
|
** For America/Godthab and Antarctica/Palmer |
|
*/ |
|
if (thistimei == 0) |
|
writetype[0] = TRUE; |
|
} |
|
thistypecnt = 0; |
|
for (i = 0; i < typecnt; ++i) |
|
typemap[i] = writetype[i] ? thistypecnt++ : -1; |
|
for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i) |
|
indmap[i] = -1; |
|
thischarcnt = 0; |
|
for (i = 0; i < typecnt; ++i) { |
|
register char * thisabbr; |
|
|
|
if (!writetype[i]) |
|
continue; |
|
if (indmap[abbrinds[i]] >= 0) |
|
continue; |
|
thisabbr = &chars[abbrinds[i]]; |
|
for (j = 0; j < thischarcnt; ++j) |
|
if (strcmp(&thischars[j], thisabbr) == 0) |
|
break; |
|
if (j == thischarcnt) { |
|
(void) strcpy(&thischars[(int) thischarcnt], |
|
thisabbr); |
|
thischarcnt += strlen(thisabbr) + 1; |
|
} |
|
indmap[abbrinds[i]] = j; |
|
} |
|
#define DO(field) (void) fwrite((void *) tzh.field, \ |
|
(size_t) sizeof tzh.field, (size_t) 1, fp) |
|
tzh = tzh0; |
|
(void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); |
|
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); |
|
DO(tzh_magic); |
|
DO(tzh_version); |
|
DO(tzh_reserved); |
|
DO(tzh_ttisgmtcnt); |
|
DO(tzh_ttisstdcnt); |
|
DO(tzh_leapcnt); |
|
DO(tzh_timecnt); |
|
DO(tzh_typecnt); |
|
DO(tzh_charcnt); |
#undef DO |
#undef DO |
for (i = 0; i < timecnt; ++i) { |
for (i = thistimei; i < thistimelim; ++i) |
j = leapcnt; |
if (pass == 1) |
while (--j >= 0) |
puttzcode((long) ats[i], fp); |
if (ats[i] >= trans[j]) { |
else puttzcode64(ats[i], fp); |
ats[i] = tadd(ats[i], corr[j]); |
for (i = thistimei; i < thistimelim; ++i) { |
break; |
unsigned char uc; |
|
|
|
uc = typemap[types[i]]; |
|
(void) fwrite((void *) &uc, |
|
(size_t) sizeof uc, |
|
(size_t) 1, |
|
fp); |
|
} |
|
for (i = 0; i < typecnt; ++i) |
|
if (writetype[i]) { |
|
puttzcode(gmtoffs[i], fp); |
|
(void) putc(isdsts[i], fp); |
|
(void) putc((unsigned char) indmap[abbrinds[i]], fp); |
} |
} |
puttzcode((long) ats[i], fp); |
if (thischarcnt != 0) |
|
(void) fwrite((void *) thischars, |
|
(size_t) sizeof thischars[0], |
|
(size_t) thischarcnt, fp); |
|
for (i = thisleapi; i < thisleaplim; ++i) { |
|
register zic_t todo; |
|
|
|
if (roll[i]) { |
|
if (timecnt == 0 || trans[i] < ats[0]) { |
|
j = 0; |
|
while (isdsts[j]) |
|
if (++j >= typecnt) { |
|
j = 0; |
|
break; |
|
} |
|
} else { |
|
j = 1; |
|
while (j < timecnt && |
|
trans[i] >= ats[j]) |
|
++j; |
|
j = types[j - 1]; |
|
} |
|
todo = tadd(trans[i], -gmtoffs[j]); |
|
} else todo = trans[i]; |
|
if (pass == 1) |
|
puttzcode((long) todo, fp); |
|
else puttzcode64(todo, fp); |
|
puttzcode(corr[i], fp); |
|
} |
|
for (i = 0; i < typecnt; ++i) |
|
if (writetype[i]) |
|
(void) putc(ttisstds[i], fp); |
|
for (i = 0; i < typecnt; ++i) |
|
if (writetype[i]) |
|
(void) putc(ttisgmts[i], fp); |
} |
} |
if (timecnt > 0) |
(void) fprintf(fp, "\n%s\n", string); |
(void) fwrite((void *) types, (size_t) sizeof types[0], |
|
(size_t) timecnt, fp); |
|
for (i = 0; i < typecnt; ++i) { |
|
puttzcode((long) gmtoffs[i], fp); |
|
(void) putc(isdsts[i], fp); |
|
(void) putc(abbrinds[i], fp); |
|
} |
|
if (charcnt != 0) |
|
(void) fwrite((void *) chars, (size_t) sizeof chars[0], |
|
(size_t) charcnt, fp); |
|
for (i = 0; i < leapcnt; ++i) { |
|
if (roll[i]) { |
|
if (timecnt == 0 || trans[i] < ats[0]) { |
|
j = 0; |
|
while (isdsts[j]) |
|
if (++j >= typecnt) { |
|
j = 0; |
|
break; |
|
} |
|
} else { |
|
j = 1; |
|
while (j < timecnt && trans[i] >= ats[j]) |
|
++j; |
|
j = types[j - 1]; |
|
} |
|
puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp); |
|
} else puttzcode((long) trans[i], fp); |
|
puttzcode((long) corr[i], fp); |
|
} |
|
for (i = 0; i < typecnt; ++i) |
|
(void) putc(ttisstds[i], fp); |
|
for (i = 0; i < typecnt; ++i) |
|
(void) putc(ttisgmts[i], fp); |
|
if (ferror(fp) || fclose(fp)) { |
if (ferror(fp) || fclose(fp)) { |
(void) fprintf(stderr, _("%s: Error writing %s\n"), |
(void) fprintf(stderr, _("%s: Error writing %s\n"), |
progname, fullname); |
progname, fullname); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
} |
} |
|
|
static void |
static void |
doabbr(abbr, abbrlen, format, letters, isdst) |
doabbr(abbr, abbrlen, format, letters, isdst, doquotes) |
char * const abbr; |
char * const abbr; |
const int abbrlen; |
const int abbrlen; |
const char * const format; |
const char * const format; |
const char * const letters; |
const char * const letters; |
const int isdst; |
const int isdst; |
|
const int doquotes; |
{ |
{ |
if (strchr(format, '/') == NULL) { |
register char * cp; |
|
register char * slashp; |
|
register int len; |
|
|
|
slashp = strchr(format, '/'); |
|
if (slashp == NULL) { |
if (letters == NULL) |
if (letters == NULL) |
(void)strncpy(abbr, format, abbrlen - 1); |
(void) strlcpy(abbr, format, abbrlen); |
else |
else (void) snprintf(abbr, abbrlen, format, letters); |
(void)snprintf(abbr, abbrlen, format, letters); |
} else if (isdst) { |
} else if (isdst) |
(void) strlcpy(abbr, slashp + 1, abbrlen); |
(void)strncpy(abbr, strchr(format, '/') + 1, abbrlen - 1); |
} else { |
else { |
if (slashp > format) |
(void)strncpy(abbr, format, abbrlen - 1); |
(void) strncpy(abbr, format, |
*strchr(abbr, '/') = '\0'; |
(unsigned) (slashp - format)); |
|
abbr[slashp - format] = '\0'; |
|
} |
|
if (!doquotes) |
|
return; |
|
for (cp = abbr; *cp != '\0'; ++cp) |
|
if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", *cp) == NULL && |
|
strchr("abcdefghijklmnopqrstuvwxyz", *cp) == NULL) |
|
break; |
|
len = strlen(abbr); |
|
if (len > 0 && *cp == '\0') |
|
return; |
|
abbr[len + 2] = '\0'; |
|
abbr[len + 1] = '>'; |
|
for ( ; len > 0; --len) |
|
abbr[len] = abbr[len - 1]; |
|
abbr[0] = '<'; |
|
} |
|
|
|
static void |
|
updateminmax(x) |
|
const int x; |
|
{ |
|
if (min_year > x) |
|
min_year = x; |
|
if (max_year < x) |
|
max_year = x; |
|
} |
|
|
|
static int |
|
stringoffset(result, offset) |
|
char * result; |
|
long offset; |
|
{ |
|
register int hours; |
|
register int minutes; |
|
register int seconds; |
|
|
|
result[0] = '\0'; |
|
if (offset < 0) { |
|
(void) strcpy(result, "-"); |
|
offset = -offset; |
|
} |
|
seconds = offset % SECSPERMIN; |
|
offset /= SECSPERMIN; |
|
minutes = offset % MINSPERHOUR; |
|
offset /= MINSPERHOUR; |
|
hours = offset; |
|
if (hours >= HOURSPERDAY) { |
|
result[0] = '\0'; |
|
return -1; |
|
} |
|
(void) sprintf(end(result), "%d", hours); |
|
if (minutes != 0 || seconds != 0) { |
|
(void) sprintf(end(result), ":%02d", minutes); |
|
if (seconds != 0) |
|
(void) sprintf(end(result), ":%02d", seconds); |
|
} |
|
return 0; |
|
} |
|
|
|
static int |
|
stringrule(result, rp, dstoff, gmtoff) |
|
char * result; |
|
const struct rule * const rp; |
|
const long dstoff; |
|
const long gmtoff; |
|
{ |
|
register long tod; |
|
|
|
result = end(result); |
|
if (rp->r_dycode == DC_DOM) { |
|
register int month, total; |
|
|
|
if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY) |
|
return -1; |
|
total = 0; |
|
for (month = 0; month < rp->r_month; ++month) |
|
total += len_months[0][month]; |
|
(void) sprintf(result, "J%d", total + rp->r_dayofmonth); |
|
} else { |
|
register int week; |
|
|
|
if (rp->r_dycode == DC_DOWGEQ) { |
|
week = 1 + rp->r_dayofmonth / DAYSPERWEEK; |
|
if ((week - 1) * DAYSPERWEEK + 1 != rp->r_dayofmonth) |
|
return -1; |
|
} 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; |
|
} |
|
} else return -1; /* "cannot happen" */ |
|
(void) sprintf(result, "M%d.%d.%d", |
|
rp->r_month + 1, week, rp->r_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; |
|
} |
|
return 0; |
|
} |
|
|
|
static void |
|
stringzone(result, resultlen, zpfirst, zonecount) |
|
char * result; |
|
const int resultlen; |
|
const struct zone * const zpfirst; |
|
const int zonecount; |
|
{ |
|
register const struct zone * zp; |
|
register struct rule * rp; |
|
register struct rule * stdrp; |
|
register struct rule * dstrp; |
|
register int i; |
|
register const char * abbrvar; |
|
|
|
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) |
|
continue; |
|
if (rp->r_yrtype != NULL) |
|
continue; |
|
if (rp->r_stdoff == 0) { |
|
if (stdrp == NULL) |
|
stdrp = rp; |
|
else return; |
|
} else { |
|
if (dstrp == NULL) |
|
dstrp = rp; |
|
else return; |
|
} |
|
} |
|
if (stdrp == NULL && dstrp == NULL) { |
|
/* |
|
** There are no rules running through "max". |
|
** Let's find the latest rule. |
|
*/ |
|
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 (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; |
|
} |
|
if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0)) |
|
return; |
|
abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; |
|
doabbr(result, resultlen, zp->z_format, abbrvar, FALSE, TRUE); |
|
if (stringoffset(end(result), -zp->z_gmtoff) != 0) { |
|
result[0] = '\0'; |
|
return; |
|
} |
|
if (dstrp == NULL) |
|
return; |
|
doabbr(end(result), resultlen - strlen(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; |
|
} |
|
(void) strcat(result, ","); |
|
if (stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { |
|
result[0] = '\0'; |
|
return; |
|
} |
|
(void) strcat(result, ","); |
|
if (stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { |
|
result[0] = '\0'; |
|
return; |
} |
} |
} |
} |
|
|
Line 1608 const int zonecount; |
|
Line 1976 const int zonecount; |
|
register struct rule * rp; |
register struct rule * rp; |
register int i, j; |
register int i, j; |
register int usestart, useuntil; |
register int usestart, useuntil; |
register time_t starttime, untiltime; |
register zic_t starttime, untiltime; |
register long gmtoff; |
register long gmtoff; |
register long stdoff; |
register long stdoff; |
register int year; |
register int year; |
Line 1616 const int zonecount; |
|
Line 1984 const int zonecount; |
|
register int startttisstd; |
register int startttisstd; |
register int startttisgmt; |
register int startttisgmt; |
register int type; |
register int type; |
char startbuf[BUFSIZ]; |
register char * startbuf; |
|
register char * ab; |
|
register char * envvar; |
|
register int max_abbr_len; |
|
register int max_envvar_len; |
|
|
|
max_abbr_len = 2 + max_format_len + max_abbrvar_len; |
|
max_envvar_len = 2 * max_abbr_len + 5 * 9; |
|
startbuf = emalloc(max_abbr_len + 1); |
|
ab = emalloc(max_abbr_len + 1); |
|
envvar = emalloc(max_envvar_len + 1); |
INITIALIZE(untiltime); |
INITIALIZE(untiltime); |
INITIALIZE(starttime); |
INITIALIZE(starttime); |
/* |
/* |
Line 1627 const int zonecount; |
|
Line 2004 const int zonecount; |
|
typecnt = 0; |
typecnt = 0; |
charcnt = 0; |
charcnt = 0; |
/* |
/* |
** Thanks to Earl Chew (earl@dnd.icp.nec.com.au) |
** Thanks to Earl Chew |
** for noting the need to unconditionally initialize startttisstd. |
** for noting the need to unconditionally initialize startttisstd. |
*/ |
*/ |
startttisstd = FALSE; |
startttisstd = FALSE; |
startttisgmt = FALSE; |
startttisgmt = FALSE; |
|
min_year = max_year = EPOCH_YEAR; |
|
if (leapseen) { |
|
updateminmax(leapminyear); |
|
updateminmax(leapmaxyear + (leapmaxyear < INT_MAX)); |
|
} |
|
for (i = 0; i < zonecount; ++i) { |
|
zp = &zpfirst[i]; |
|
if (i < zonecount - 1) |
|
updateminmax(zp->z_untilrule.r_loyear); |
|
for (j = 0; j < zp->z_nrules; ++j) { |
|
rp = &zp->z_rules[j]; |
|
if (rp->r_lowasnum) |
|
updateminmax(rp->r_loyear); |
|
if (rp->r_hiwasnum) |
|
updateminmax(rp->r_hiyear); |
|
} |
|
} |
|
/* |
|
** Generate lots of data if a rule can't cover all future times. |
|
*/ |
|
stringzone(envvar, max_envvar_len+1, 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; |
|
} |
|
/* |
|
** For the benefit of older systems, |
|
** generate data from 1900 through 2037. |
|
*/ |
|
if (min_year > 1900) |
|
min_year = 1900; |
|
if (max_year < 2037) |
|
max_year = 2037; |
for (i = 0; i < zonecount; ++i) { |
for (i = 0; i < zonecount; ++i) { |
/* |
/* |
** A guess that may well be corrected later. |
** A guess that may well be corrected later. |
Line 1648 const int zonecount; |
|
Line 2071 const int zonecount; |
|
startoff = zp->z_gmtoff; |
startoff = zp->z_gmtoff; |
if (zp->z_nrules == 0) { |
if (zp->z_nrules == 0) { |
stdoff = zp->z_stdoff; |
stdoff = zp->z_stdoff; |
doabbr(startbuf, sizeof startbuf, zp->z_format, |
doabbr(startbuf, max_abbr_len + 1, zp->z_format, |
(char *) NULL, stdoff != 0); |
(char *) NULL, stdoff != 0, FALSE); |
type = addtype(oadd(zp->z_gmtoff, stdoff), |
type = addtype(oadd(zp->z_gmtoff, stdoff), |
startbuf, stdoff != 0, startttisstd, |
startbuf, stdoff != 0, startttisstd, |
startttisgmt); |
startttisgmt); |
Line 1677 const int zonecount; |
|
Line 2100 const int zonecount; |
|
} |
} |
for ( ; ; ) { |
for ( ; ; ) { |
register int k; |
register int k; |
register time_t jtime, ktime; |
register zic_t jtime, ktime; |
register long offset; |
register long offset; |
char buf[BUFSIZ]; |
|
|
|
INITIALIZE(ktime); |
INITIALIZE(ktime); |
if (useuntil) { |
if (useuntil) { |
Line 1733 const int zonecount; |
|
Line 2155 const int zonecount; |
|
if (ktime < starttime) { |
if (ktime < starttime) { |
startoff = oadd(zp->z_gmtoff, |
startoff = oadd(zp->z_gmtoff, |
stdoff); |
stdoff); |
doabbr(startbuf,sizeof startbuf, |
doabbr(startbuf, |
|
max_abbr_len + 1, |
zp->z_format, |
zp->z_format, |
rp->r_abbrvar, |
rp->r_abbrvar, |
rp->r_stdoff != 0); |
rp->r_stdoff != 0, |
|
FALSE); |
continue; |
continue; |
} |
} |
if (*startbuf == '\0' && |
if (*startbuf == '\0' && |
startoff == oadd(zp->z_gmtoff, |
startoff == oadd(zp->z_gmtoff, |
stdoff)) { |
stdoff)) { |
doabbr(startbuf,sizeof startbuf, |
doabbr(startbuf, |
zp->z_format, |
max_abbr_len + 1, |
rp->r_abbrvar, |
zp->z_format, |
rp->r_stdoff != 0); |
rp->r_abbrvar, |
|
rp->r_stdoff != |
|
0, |
|
FALSE); |
} |
} |
} |
} |
eats(zp->z_filename, zp->z_linenum, |
eats(zp->z_filename, zp->z_linenum, |
rp->r_filename, rp->r_linenum); |
rp->r_filename, rp->r_linenum); |
doabbr(buf, sizeof buf, zp->z_format, |
doabbr(ab, max_abbr_len+1, zp->z_format, rp->r_abbrvar, |
rp->r_abbrvar, rp->r_stdoff != 0); |
rp->r_stdoff != 0, FALSE); |
offset = oadd(zp->z_gmtoff, rp->r_stdoff); |
offset = oadd(zp->z_gmtoff, rp->r_stdoff); |
type = addtype(offset, buf, rp->r_stdoff != 0, |
type = addtype(offset, ab, rp->r_stdoff != 0, |
rp->r_todisstd, rp->r_todisgmt); |
rp->r_todisstd, rp->r_todisgmt); |
addtt(ktime, type); |
addtt(ktime, type); |
} |
} |
Line 1764 const int zonecount; |
|
Line 2191 const int zonecount; |
|
strchr(zp->z_format, '%') == NULL && |
strchr(zp->z_format, '%') == NULL && |
strchr(zp->z_format, '/') == NULL) |
strchr(zp->z_format, '/') == NULL) |
(void)strncpy(startbuf, zp->z_format, |
(void)strncpy(startbuf, zp->z_format, |
sizeof(startbuf) - 1); |
max_abbr_len + 1 - 1); |
eat(zp->z_filename, zp->z_linenum); |
eat(zp->z_filename, zp->z_linenum); |
if (*startbuf == '\0') |
if (*startbuf == '\0') |
error(_("can't determine time zone abbreviation to use just after until time")); |
error(_("can't determine time zone abbreviation to use just after until time")); |
Line 1787 error(_("can't determine time zone abbre |
|
Line 2214 error(_("can't determine time zone abbre |
|
starttime = tadd(starttime, -gmtoff); |
starttime = tadd(starttime, -gmtoff); |
} |
} |
} |
} |
writezone(zpfirst->z_name); |
writezone(zpfirst->z_name, envvar); |
|
ifree(startbuf); |
|
ifree(ab); |
|
ifree(envvar); |
} |
} |
|
|
static void |
static void |
addtt(starttime, type) |
addtt(starttime, type) |
const time_t starttime; |
const zic_t starttime; |
int type; |
int type; |
{ |
{ |
if (starttime <= min_time || |
if (starttime <= min_time || |
|
|
} |
} |
if (timecnt >= TZ_MAX_TIMES) { |
if (timecnt >= TZ_MAX_TIMES) { |
error(_("too many transitions?!")); |
error(_("too many transitions?!")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
attypes[timecnt].at = starttime; |
attypes[timecnt].at = starttime; |
attypes[timecnt].type = type; |
attypes[timecnt].type = type; |
Line 1830 const int ttisgmt; |
|
Line 2260 const int ttisgmt; |
|
|
|
if (isdst != TRUE && isdst != FALSE) { |
if (isdst != TRUE && isdst != FALSE) { |
error(_("internal error - addtype called with bad isdst")); |
error(_("internal error - addtype called with bad isdst")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
if (ttisstd != TRUE && ttisstd != FALSE) { |
if (ttisstd != TRUE && ttisstd != FALSE) { |
error(_("internal error - addtype called with bad ttisstd")); |
error(_("internal error - addtype called with bad ttisstd")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
if (ttisgmt != TRUE && ttisgmt != FALSE) { |
if (ttisgmt != TRUE && ttisgmt != FALSE) { |
error(_("internal error - addtype called with bad ttisgmt")); |
error(_("internal error - addtype called with bad ttisgmt")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
/* |
/* |
** See if there's already an entry for this zone type. |
** See if there's already an entry for this zone type. |
Line 1857 const int ttisgmt; |
|
Line 2287 const int ttisgmt; |
|
*/ |
*/ |
if (typecnt >= TZ_MAX_TYPES) { |
if (typecnt >= TZ_MAX_TYPES) { |
error(_("too many local time types")); |
error(_("too many local time types")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
|
} |
|
if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) { |
|
error(_("UTC offset out of range")); |
|
exit(EXIT_FAILURE); |
} |
} |
gmtoffs[i] = gmtoff; |
gmtoffs[i] = gmtoff; |
isdsts[i] = isdst; |
isdsts[i] = isdst; |
Line 1876 const int ttisgmt; |
|
Line 2310 const int ttisgmt; |
|
|
|
static void |
static void |
leapadd(t, positive, rolling, count) |
leapadd(t, positive, rolling, count) |
const time_t t; |
const zic_t t; |
const int positive; |
const int positive; |
const int rolling; |
const int rolling; |
int count; |
int count; |
|
|
|
|
if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { |
if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { |
error(_("too many leap seconds")); |
error(_("too many leap seconds")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
for (i = 0; i < leapcnt; ++i) |
for (i = 0; i < leapcnt; ++i) |
if (t <= trans[i]) { |
if (t <= trans[i]) { |
if (t == trans[i]) { |
if (t == trans[i]) { |
error(_("repeated leap second moment")); |
error(_("repeated leap second moment")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
break; |
break; |
} |
} |
|
|
} |
} |
|
|
static void |
static void |
adjleap P((void)) |
adjleap(void) |
{ |
{ |
register int i; |
register int i; |
register long last = 0; |
register long last = 0; |
Line 1946 const char * const type; |
|
Line 2380 const char * const type; |
|
(void) fprintf(stderr, _("%s: command was '%s', result was %d\n"), |
(void) fprintf(stderr, _("%s: command was '%s', result was %d\n"), |
progname, buf, result); |
progname, buf, result); |
for ( ; ; ) |
for ( ; ; ) |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
|
|
static int |
static int |
Line 2027 register char * cp; |
|
Line 2461 register char * cp; |
|
emalloc((int) ((strlen(cp) + 1) * sizeof *array)); |
emalloc((int) ((strlen(cp) + 1) * sizeof *array)); |
nsubs = 0; |
nsubs = 0; |
for ( ; ; ) { |
for ( ; ; ) { |
while (isascii(*cp) && isspace((unsigned char) *cp)) |
while (isascii((unsigned char) *cp) && |
++cp; |
isspace((unsigned char) *cp)) |
|
++cp; |
if (*cp == '\0' || *cp == '#') |
if (*cp == '\0' || *cp == '#') |
break; |
break; |
array[nsubs++] = dp = cp; |
array[nsubs++] = dp = cp; |
Line 2038 register char * cp; |
|
Line 2473 register char * cp; |
|
else while ((*dp = *cp++) != '"') |
else while ((*dp = *cp++) != '"') |
if (*dp != '\0') |
if (*dp != '\0') |
++dp; |
++dp; |
else error(_("Odd number of quotation marks")); |
else { |
|
error(_( |
|
"Odd number of quotation marks" |
|
)); |
|
exit(1); |
|
} |
} while (*cp != '\0' && *cp != '#' && |
} while (*cp != '\0' && *cp != '#' && |
(!isascii(*cp) || !isspace((unsigned char) *cp))); |
(!isascii(*cp) || !isspace((unsigned char) *cp))); |
if (isascii(*cp) && isspace((unsigned char) *cp)) |
if (isascii(*cp) && isspace((unsigned char) *cp)) |
|
|
t = t1 + t2; |
t = t1 + t2; |
if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { |
if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { |
error(_("time overflow")); |
error(_("time overflow")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
return t; |
return t; |
} |
} |
|
|
static time_t |
static zic_t |
tadd(t1, t2) |
tadd(t1, t2) |
const time_t t1; |
const zic_t t1; |
const long t2; |
const long t2; |
{ |
{ |
register time_t t; |
register zic_t t; |
|
|
if (t1 == max_time && t2 > 0) |
if (t1 == max_time && t2 > 0) |
return max_time; |
return max_time; |
|
|
t = t1 + t2; |
t = t1 + t2; |
if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { |
if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { |
error(_("time overflow")); |
error(_("time overflow")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
return t; |
return t; |
} |
} |
|
|
** 1970, 00:00 LOCAL time - in that year that the rule refers to. |
** 1970, 00:00 LOCAL time - in that year that the rule refers to. |
*/ |
*/ |
|
|
static time_t |
static zic_t |
rpytime(rp, wantedy) |
rpytime(rp, wantedy) |
register const struct rule * const rp; |
register const struct rule * const rp; |
register const int wantedy; |
register const int wantedy; |
{ |
{ |
register int y, m, i; |
register int y, m, i; |
register long dayoff; /* with a nod to Margaret O. */ |
register long dayoff; /* with a nod to Margaret O. */ |
register time_t t; |
register zic_t t; |
|
|
if (wantedy == INT_MIN) |
if (wantedy == INT_MIN) |
return min_time; |
return min_time; |
Line 2125 register const int wantedy; |
|
Line 2565 register const int wantedy; |
|
--i; |
--i; |
else { |
else { |
error(_("use of 2/29 in non leap-year")); |
error(_("use of 2/29 in non leap-year")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
} |
} |
--i; |
--i; |
Line 2159 register const int wantedy; |
|
Line 2599 register const int wantedy; |
|
} |
} |
if (i < 0 || i >= len_months[isleap(y)][m]) { |
if (i < 0 || i >= len_months[isleap(y)][m]) { |
if (noise) |
if (noise) |
warning(_("rule goes past start/end of month--will not work with pre-2004 versions of zic")); |
warning(_("rule goes past start/end of month--\ |
|
will not work with pre-2004 versions of zic")); |
} |
} |
} |
} |
if (dayoff < 0 && !TYPE_SIGNED(time_t)) |
|
return min_time; |
|
if (dayoff < min_time / SECSPERDAY) |
if (dayoff < min_time / SECSPERDAY) |
return min_time; |
return min_time; |
if (dayoff > max_time / SECSPERDAY) |
if (dayoff > max_time / SECSPERDAY) |
return max_time; |
return max_time; |
t = (time_t) dayoff * SECSPERDAY; |
t = (zic_t) dayoff * SECSPERDAY; |
return tadd(t, rp->r_tod); |
return tadd(t, rp->r_tod); |
} |
} |
|
|
Line 2178 const char * const string; |
|
Line 2617 const char * const string; |
|
{ |
{ |
register int i; |
register int i; |
|
|
|
if (strcmp(string, GRANDPARENTED) != 0) { |
|
register const char * cp; |
|
register char * wp; |
|
|
|
/* |
|
** 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; |
|
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"); |
|
if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN) |
|
wp = _("time zone abbreviation has too many alphabetics"); |
|
if (wp == NULL && (*cp == '+' || *cp == '-')) { |
|
++cp; |
|
if (isascii((unsigned char) *cp) && |
|
isdigit((unsigned char) *cp)) |
|
if (*cp++ == '1' && |
|
*cp >= '0' && *cp <= '4') |
|
++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); |
|
} |
|
} |
i = strlen(string) + 1; |
i = strlen(string) + 1; |
if (charcnt + i > TZ_MAX_CHARS) { |
if (charcnt + i > TZ_MAX_CHARS) { |
error(_("too many, or too long, time zone abbreviations")); |
error(_("too many, or too long, time zone abbreviations")); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
(void)strncpy(&chars[charcnt], string, sizeof(chars) - charcnt - 1); |
(void)strncpy(&chars[charcnt], string, sizeof(chars) - charcnt - 1); |
charcnt += eitol(i); |
charcnt += eitol(i); |
Line 2189 const char * const string; |
|
Line 2666 const char * const string; |
|
|
|
static int |
static int |
mkdirs(argname) |
mkdirs(argname) |
char * const argname; |
char * argname; |
{ |
{ |
register char * name; |
register char * name; |
register char * cp; |
register char * cp; |
|
|
(void) fprintf(stderr, |
(void) fprintf(stderr, |
_("%s: %d did not sign extend correctly\n"), |
_("%s: %d did not sign extend correctly\n"), |
progname, i); |
progname, i); |
(void) exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
return l; |
return l; |
} |
} |