From 0bce2915eb430cfbae0bf2a6c0903b15fee7f9dd Mon Sep 17 00:00:00 2001 From: millert Date: Tue, 14 Jan 1997 03:16:42 +0000 Subject: [PATCH] Update to tzcode1996o + our fixes. Fixes problem pointed out by cross@va.pubnix.com. --- lib/libc/time/asctime.c | 11 +- lib/libc/time/ctime.3 | 7 +- lib/libc/time/difftime.c | 11 +- lib/libc/time/ialloc.c | 6 +- lib/libc/time/localtime.c | 23 +- lib/libc/time/private.h | 72 ++++++- lib/libc/time/scheck.c | 6 +- lib/libc/time/time2posix.3 | 7 +- lib/libc/time/tzfile.5 | 8 +- lib/libc/time/tzfile.h | 24 ++- lib/libc/time/tzset.3 | 3 +- lib/libc/time/zdump.8 | 7 +- lib/libc/time/zdump.c | 54 ++++- lib/libc/time/zic.8 | 9 +- lib/libc/time/zic.c | 421 +++++++++++++++++++++++++------------ 15 files changed, 493 insertions(+), 176 deletions(-) diff --git a/lib/libc/time/asctime.c b/lib/libc/time/asctime.c index 0db9e34ab56..e31c6148584 100644 --- a/lib/libc/time/asctime.c +++ b/lib/libc/time/asctime.c @@ -1,5 +1,14 @@ +/* +** This file is in the public domain, so clarified as of +** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +*/ + #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: asctime.c,v 1.2 1996/08/19 08:34:47 tholo Exp $"; +#if 0 +static char elsieid[] = "@(#)asctime.c 7.8"; +#else +static char rcsid[] = "$OpenBSD: asctime.c,v 1.3 1997/01/14 03:16:42 millert Exp $"; +#endif #endif /* LIBC_SCCS and not lint */ /*LINTLIBRARY*/ diff --git a/lib/libc/time/ctime.3 b/lib/libc/time/ctime.3 index 88eb9e84da2..81c6c595cd4 100644 --- a/lib/libc/time/ctime.3 +++ b/lib/libc/time/ctime.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ctime.3,v 1.5 1996/08/19 08:34:48 tholo Exp $ +.\" $OpenBSD: ctime.3,v 1.6 1997/01/14 03:16:43 millert Exp $ .TH CTIME 3 .SH NAME asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time to ASCII @@ -31,13 +31,14 @@ asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time to .B time_t mktime(tm) .B struct tm *tm; .PP +.B cc ... -lz .fi .SH DESCRIPTION .I Ctime\^ converts a long integer, pointed to by .IR clock , representing the time in seconds since -00:00:00 UTC, January 1, 1970, +00:00:00 UTC, 1970-01-01, and returns a pointer to a 26-character string of the form @@ -211,4 +212,4 @@ will also be overwritten at the next call Avoid using out-of-range values with .I mktime when setting up lunch with promptness sticklers in Riyadh. -.\" @(#)newctime.3 7.12 +.\" @(#)newctime.3 7.13 diff --git a/lib/libc/time/difftime.c b/lib/libc/time/difftime.c index f61af9ada65..6cfddc68ef1 100644 --- a/lib/libc/time/difftime.c +++ b/lib/libc/time/difftime.c @@ -1,5 +1,14 @@ +/* +** This file is in the public domain, so clarified as of +** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov). +*/ + #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: difftime.c,v 1.3 1996/08/19 08:34:48 tholo Exp $"; +#if 0 +static char elsieid[] = "@(#)difftime.c 7.7"; +#else +static char rcsid[] = "$OpenBSD: difftime.c,v 1.4 1997/01/14 03:16:44 millert Exp $"; +#endif #endif /* LIBC_SCCS and not lint */ /*LINTLIBRARY*/ diff --git a/lib/libc/time/ialloc.c b/lib/libc/time/ialloc.c index e912eadc37f..5590dd13b54 100644 --- a/lib/libc/time/ialloc.c +++ b/lib/libc/time/ialloc.c @@ -1,5 +1,9 @@ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: ialloc.c,v 1.2 1996/08/19 08:34:49 tholo Exp $"; +#if 0 +static char elsieid[] = "@(#)ialloc.c 8.28"; +#else +static char rcsid[] = "$OpenBSD: ialloc.c,v 1.3 1997/01/14 03:16:45 millert Exp $"; +#endif #endif /* LIBC_SCCS and not lint */ /*LINTLIBRARY*/ diff --git a/lib/libc/time/localtime.c b/lib/libc/time/localtime.c index c25b4356049..a7cdae4a063 100644 --- a/lib/libc/time/localtime.c +++ b/lib/libc/time/localtime.c @@ -1,5 +1,14 @@ +/* +** This file is in the public domain, so clarified as of +** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +*/ + #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: localtime.c,v 1.7 1996/10/30 00:20:14 tholo Exp $"; +#if 0 +static char elsieid[] = "@(#)localtime.c 7.59"; +#else +static char rcsid[] = "$OpenBSD: localtime.c,v 1.8 1997/01/14 03:16:47 millert Exp $"; +#endif #endif /* LIBC_SCCS and not lint */ /* @@ -285,7 +294,7 @@ register struct state * const sp; if (!doaccess && issetugid() == 0) { if ((p = TZDIR) == NULL) return -1; - if (strlen(p) + 1 + strlen(name) + 1 >= sizeof fullname) + if ((strlen(p) + strlen(name) + 2) >= sizeof fullname) return -1; (void) strcpy(fullname, p); (void) strcat(fullname, "/"); @@ -878,6 +887,7 @@ const int lastditch; sp->ttis[1].tt_gmtoff = -dstoffset; sp->ttis[1].tt_isdst = TRUE; sp->ttis[1].tt_abbrind = stdlen + 1; + sp->typecnt = 2; } } else { dstlen = 0; @@ -1223,7 +1233,8 @@ const time_t * const timep; /* ** Adapted from code provided by Robert Elz, who writes: ** The "best" way to do mktime I think is based on an idea of Bob -** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). +** Kridle's (so its said...) from a long time ago. +** [kridle@xinet.com as of 1996-01-16.] ** It does a binary search of the time_t space. Since time_t's are ** just 32 bits, its a max of 32 iterations (even at 64 bits it ** would still be very reasonable). @@ -1313,10 +1324,12 @@ int * const okayp; while (yourtm.tm_mday <= 0) { if (increment_overflow(&yourtm.tm_year, -1)) return WRONG; - yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year)]; + i = yourtm.tm_year + (1 < yourtm.tm_mon); + yourtm.tm_mday += year_lengths[isleap(i)]; } while (yourtm.tm_mday > DAYSPERLYEAR) { - yourtm.tm_mday -= year_lengths[isleap(yourtm.tm_year)]; + i = yourtm.tm_year + (1 < yourtm.tm_mon); + yourtm.tm_mday -= year_lengths[isleap(i)]; if (increment_overflow(&yourtm.tm_year, 1)) return WRONG; } diff --git a/lib/libc/time/private.h b/lib/libc/time/private.h index a90fc20638b..98d09dfbdf6 100644 --- a/lib/libc/time/private.h +++ b/lib/libc/time/private.h @@ -1,14 +1,21 @@ -/* $OpenBSD: private.h,v 1.5 1996/10/30 00:20:12 tholo Exp $ */ +/* $OpenBSD: private.h,v 1.6 1997/01/14 03:16:48 millert Exp $ */ #ifndef PRIVATE_H + #define PRIVATE_H +/* +** This file is in the public domain, so clarified as of +** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +*/ + /* OpenBSD defaults */ -#define TM_GMTOFF tm_gmtoff -#define TM_ZONE tm_zone -#define PCTS 1 -#define STD_INSPIRED 1 -#define HAVE_LONG_DOUBLE 1 +#define TM_GMTOFF tm_gmtoff +#define TM_ZONE tm_zone +#define PCTS 1 +#define STD_INSPIRED 1 +#define HAVE_LONG_DOUBLE 1 +#define HAVE_STRERROR 1 /* ** This header is for use ONLY with the time conversion code. @@ -18,6 +25,18 @@ ** Thank you! */ +/* +** ID +*/ + +#if 0 +#ifndef lint +#ifndef NOID +static char privatehid[] = "@(#)private.h 7.44"; +#endif /* !defined NOID */ +#endif /* !defined lint */ +#endif + /* ** Defaults for preprocessor symbols. ** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'. @@ -27,10 +46,18 @@ #define HAVE_ADJTIME 1 #endif /* !defined HAVE_ADJTIME */ +#ifndef HAVE_GETTEXT +#define HAVE_GETTEXT 0 +#endif /* !defined HAVE_GETTEXT */ + #ifndef HAVE_SETTIMEOFDAY #define HAVE_SETTIMEOFDAY 3 #endif /* !defined HAVE_SETTIMEOFDAY */ +#ifndef HAVE_STRERROR +#define HAVE_STRERROR 0 +#endif /* !defined HAVE_STRERROR */ + #ifndef HAVE_UNISTD_H #define HAVE_UNISTD_H 1 #endif /* !defined HAVE_UNISTD_H */ @@ -55,6 +82,10 @@ #include "time.h" #include "stdlib.h" +#if HAVE_GETTEXT - 0 +#include "libintl.h" +#endif /* HAVE_GETTEXT - 0 */ + #if HAVE_UNISTD_H - 0 #include "unistd.h" /* for F_OK and R_OK */ #endif /* HAVE_UNISTD_H - 0 */ @@ -144,6 +175,17 @@ extern int unlink P((const char * filename)); #define remove unlink #endif /* !defined remove */ +#if 0 +/* +** Some ancient errno.h implementations don't declare errno. +** But some newer errno.h implementations define it as a macro. +** Fix the former without affecting the latter. +*/ +#ifndef errno +extern int errno; +#endif /* !defined errno */ +#endif + /* ** Finally, some convenience items. */ @@ -199,6 +241,24 @@ extern int unlink P((const char * filename)); #endif /* !defined GNUC_or_lint */ #endif /* !defined INITIALIZE */ +/* +** For the benefit of GNU folk... +** `_(MSGID)' uses the current locale's message library string for MSGID. +** The default is to use gettext if available, and use MSGID otherwise. +*/ + +#ifndef _ +#if HAVE_GETTEXT - 0 +#define _(msgid) gettext(msgid) +#else /* !(HAVE_GETTEXT - 0) */ +#define _(msgid) msgid +#endif /* !(HAVE_GETTEXT - 0) */ +#endif /* !defined _ */ + +#ifndef TZ_DOMAIN +#define TZ_DOMAIN "tz" +#endif /* !defined TZ_DOMAIN */ + /* ** UNIX was a registered trademark of UNIX System Laboratories in 1993. */ diff --git a/lib/libc/time/scheck.c b/lib/libc/time/scheck.c index 5fd5b09eea5..e7455daf67b 100644 --- a/lib/libc/time/scheck.c +++ b/lib/libc/time/scheck.c @@ -1,5 +1,9 @@ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: scheck.c,v 1.3 1996/08/19 08:34:51 tholo Exp $"; +#if 0 +static char elsieid[] = "@(#)scheck.c 8.13"; +#else +static char rcsid[] = "$OpenBSD: scheck.c,v 1.4 1997/01/14 03:16:49 millert Exp $"; +#endif #endif /* LIBC_SCCS and not lint */ /*LINTLIBRARY*/ diff --git a/lib/libc/time/time2posix.3 b/lib/libc/time/time2posix.3 index 9ad2b879938..2f2f9aafe79 100644 --- a/lib/libc/time/time2posix.3 +++ b/lib/libc/time/time2posix.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: time2posix.3,v 1.3 1996/08/19 08:34:52 tholo Exp $ +.\" $OpenBSD: time2posix.3,v 1.4 1997/01/14 03:16:50 millert Exp $ .TH TIME2POSIX 3 .SH NAME time2posix, posix2time \- convert seconds since the Epoch @@ -13,6 +13,7 @@ time2posix, posix2time \- convert seconds since the Epoch .B time_t posix2time(t) .B time_t t .PP +.B cc ... -lz .fi .SH DESCRIPTION IEEE Standard 1003.1 @@ -116,4 +117,6 @@ difftime(3), localtime(3), mktime(3), time(3) -.\" @(#)time2posix.3 7.3 +.\" @(#)time2posix.3 7.5 +.\" This file is in the public domain, so clarified as of +.\" 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). diff --git a/lib/libc/time/tzfile.5 b/lib/libc/time/tzfile.5 index 58705b231a3..bafaf75f370 100644 --- a/lib/libc/time/tzfile.5 +++ b/lib/libc/time/tzfile.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tzfile.5,v 1.3 1996/08/19 08:34:52 tholo Exp $ +.\" $OpenBSD: tzfile.5,v 1.4 1997/01/14 03:16:51 millert Exp $ .TH TZFILE 5 .SH NAME tzfile \- time zone information @@ -44,7 +44,7 @@ four-byte values of type sorted in ascending order. These values are written in ``standard'' byte order. Each is used as a transition time (as returned by -.IR time (2)) +.IR time (3)) at which the rules for computing local time change. Next come .I tzh_timecnt @@ -132,4 +132,6 @@ is zero or the time argument is less than the first transition time recorded in the file. .SH SEE ALSO ctime(3) -.\" @(#)tzfile.5 7.3 +.\" @(#)tzfile.5 7.5 +.\" This file is in the public domain, so clarified as of +.\" 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). diff --git a/lib/libc/time/tzfile.h b/lib/libc/time/tzfile.h index ce1c7cfb88a..82e6852936e 100644 --- a/lib/libc/time/tzfile.h +++ b/lib/libc/time/tzfile.h @@ -1,8 +1,14 @@ -/* $OpenBSD: tzfile.h,v 1.3 1996/08/19 08:34:53 tholo Exp $ */ +/* $OpenBSD: tzfile.h,v 1.4 1997/01/14 03:16:52 millert Exp $ */ #ifndef TZFILE_H + #define TZFILE_H +/* +** This file is in the public domain, so clarified as of +** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +*/ + /* ** This header is for use ONLY with the time conversion code. ** There is no guarantee that it will remain unchanged, @@ -11,12 +17,24 @@ ** Thank you! */ +/* +** ID +*/ + +#if 0 +#ifndef lint +#ifndef NOID +static char tzfilehid[] = "@(#)tzfile.h 7.9"; +#endif /* !defined NOID */ +#endif /* !defined lint */ +#endif + /* ** Information about time zone files. */ -#ifndef TZDIR /* Time zone object file directory */ -#define TZDIR "/usr/share/zoneinfo" +#ifndef TZDIR +#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */ #endif /* !defined TZDIR */ #ifndef TZDEFAULT diff --git a/lib/libc/time/tzset.3 b/lib/libc/time/tzset.3 index aa27f05bda9..9ff0575ecf4 100644 --- a/lib/libc/time/tzset.3 +++ b/lib/libc/time/tzset.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tzset.3,v 1.4 1996/08/19 08:34:53 tholo Exp $ +.\" $OpenBSD: tzset.3,v 1.5 1997/01/14 03:16:54 millert Exp $ .TH TZSET 3 .SH NAME tzset \- initialize time conversion information @@ -6,6 +6,7 @@ tzset \- initialize time conversion information .nf .B void tzset() .PP +.B cc ... -lz .fi .SH DESCRIPTION .I Tzset diff --git a/lib/libc/time/zdump.8 b/lib/libc/time/zdump.8 index 59e03041e81..7126d4e0875 100644 --- a/lib/libc/time/zdump.8 +++ b/lib/libc/time/zdump.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: zdump.8,v 1.2 1996/08/19 08:34:54 tholo Exp $ +.\" $OpenBSD: zdump.8,v 1.3 1997/01/14 03:16:54 millert Exp $ .TH ZDUMP 8 .SH NAME zdump \- time zone dumper @@ -21,8 +21,7 @@ These options are available: For each .I zonename on the command line, -print the current time, -the time at the lowest possible time value, +print the time at the lowest possible time value, the time one day after the lowest possible time value, the times both one second before and exactly at each detected time discontinuity, @@ -38,4 +37,4 @@ otherwise. Cut off the verbose output near the start of the given year. .SH "SEE ALSO" ctime(3), tzfile(5), zic(8) -.\" @(#)zdump.8 7.2 +.\" @(#)zdump.8 7.3 diff --git a/lib/libc/time/zdump.c b/lib/libc/time/zdump.c index e0f76d13fac..2df4b3e0930 100644 --- a/lib/libc/time/zdump.c +++ b/lib/libc/time/zdump.c @@ -1,5 +1,9 @@ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: zdump.c,v 1.3 1996/08/27 03:36:57 deraadt Exp $"; +#if 0 +static char elsieid[] = "@(#)zdump.c 7.24"; +#else +static char rcsid[] = "$OpenBSD: zdump.c,v 1.4 1997/01/14 03:16:56 millert Exp $"; +#endif #endif /* LIBC_SCCS and not lint */ /* @@ -66,6 +70,11 @@ static char rcsid[] = "$OpenBSD: zdump.c,v 1.3 1996/08/27 03:36:57 deraadt Exp $ #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) #endif /* !defined isleap */ +#if HAVE_GETTEXT - 0 +#include "locale.h" /* for setlocale */ +#include "libintl.h" +#endif /* HAVE_GETTEXT - 0 */ + #ifndef GNUC_or_lint #ifdef lint #define GNUC_or_lint @@ -86,6 +95,24 @@ static char rcsid[] = "$OpenBSD: zdump.c,v 1.3 1996/08/27 03:36:57 deraadt Exp $ #endif /* !defined GNUC_or_lint */ #endif /* !defined INITIALIZE */ +/* +** For the benefit of GNU folk... +** `_(MSGID)' uses the current locale's message library string for MSGID. +** The default is to use gettext if available, and use MSGID otherwise. +*/ + +#ifndef _ +#if HAVE_GETTEXT - 0 +#define _(msgid) gettext(msgid) +#else /* !(HAVE_GETTEXT - 0) */ +#define _(msgid) msgid +#endif /* !(HAVE_GETTEXT - 0) */ +#endif /* !defined _ */ + +#ifndef TZ_DOMAIN +#define TZ_DOMAIN "tz" +#endif /* !defined TZ_DOMAIN */ + extern char ** environ; extern int getopt(); extern char * optarg; @@ -120,6 +147,13 @@ char * argv[]; struct tm newtm; INITIALIZE(cuttime); +#if HAVE_GETTEXT - 0 + (void) setlocale(LC_MESSAGES, ""); +#ifdef TZ_DOMAINDIR + (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); +#endif /* defined(TEXTDOMAINDIR) */ + (void) textdomain(TZ_DOMAIN); +#endif /* HAVE_GETTEXT - 0 */ progname = argv[0]; vflag = 0; cutoff = NULL; @@ -130,7 +164,7 @@ char * argv[]; if (c != EOF || (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { (void) fprintf(stderr, -"%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n", +_("%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n"), argv[0], argv[0]); (void) exit(EXIT_FAILURE); } @@ -189,8 +223,8 @@ char * argv[]; t += SECSPERHOUR * HOURSPERDAY; show(argv[i], t, TRUE); tm = *localtime(&t); - (void) strncpy(buf, abbr(&tm), sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\0'; + (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); + buf[(sizeof buf) - 1] = '\0'; for ( ; ; ) { if (cutoff != NULL && t >= cuttime) break; @@ -206,8 +240,8 @@ char * argv[]; newt = hunt(argv[i], t, newt); newtm = *localtime(&newt); (void) strncpy(buf, abbr(&newtm), - sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\0'; + (sizeof buf) - 1); + buf[(sizeof buf) - 1] = '\0'; } t = newt; tm = newtm; @@ -224,9 +258,9 @@ char * argv[]; show(argv[i], t, TRUE); } if (fflush(stdout) || ferror(stdout)) { - (void) fprintf(stderr, "%s: Error writing standard output ", + (void) fprintf(stderr, _("%s: Error writing standard output "), argv[0]); - (void) perror("standard output"); + (void) perror(_("standard output")); (void) exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); @@ -248,8 +282,8 @@ time_t hit; static char loab[MAX_STRING_LENGTH]; lotm = *localtime(&lot); - (void) strncpy(loab, abbr(&lotm), sizeof(loab) - 1); - loab[sizeof(loab) - 1] = '\0'; + (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); + loab[(sizeof loab) - 1] = '\0'; while ((hit - lot) >= 2) { t = lot / 2 + hit / 2; if (t <= lot) diff --git a/lib/libc/time/zic.8 b/lib/libc/time/zic.8 index 256dfbe1600..004ff093e68 100644 --- a/lib/libc/time/zic.8 +++ b/lib/libc/time/zic.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: zic.8,v 1.3 1996/08/19 08:34:55 tholo Exp $ +.\" $OpenBSD: zic.8,v 1.4 1997/01/14 03:16:57 millert Exp $ .TH ZIC 8 .SH NAME zic \- time zone compiler @@ -74,7 +74,7 @@ no leap second information appears in output files. .B \-v Complain if a year that appears in a data file is outside the range of years representable by -.IR time (2) +.IR time (3) values. .TP .B \-s @@ -305,6 +305,9 @@ It is specified as a year, a month, a day, and a time of day. If this is specified, the time zone information is generated from the given GMT offset and rule change until the time specified. +The month, day, and time of day have the same format as the IN, ON, and AT +columns of a rule; trailing columns can be omitted, and default to the +earliest possible value for the missing columns. .IP The next line must be a .q continuation @@ -406,4 +409,4 @@ the earliest transition time recorded in the compiled file is correct. /usr/share/zoneinfo standard directory used for created files .SH "SEE ALSO" ctime(3), tzfile(5), zdump(8) -.\" @(#)zic.8 7.12 +.\" @(#)zic.8 7.14 diff --git a/lib/libc/time/zic.c b/lib/libc/time/zic.c index 6205e8fd922..98e063e479f 100644 --- a/lib/libc/time/zic.c +++ b/lib/libc/time/zic.c @@ -1,8 +1,13 @@ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: zic.c,v 1.4 1996/08/19 08:34:56 tholo Exp $"; +#if 0 +static char elsieid[] = "@(#)zic.c 7.80"; +#else +static char rcsid[] = "$OpenBSD: zic.c,v 1.5 1997/01/14 03:16:58 millert Exp $"; +#endif #endif /* LIBC_SCCS and not lint */ #include "private.h" +#include "locale.h" #include "tzfile.h" #ifdef unix #include "sys/stat.h" /* for umask manifest constants */ @@ -133,6 +138,10 @@ static void usage P((void)); static void writezone P((const char * name)); static int yearistype P((int year, const char * type)); +#if !(HAVE_STRERROR - 0) +static char * strerror P((int)); +#endif /* !(HAVE_STRERROR - 0) */ + static int charcnt; static int errors; static const char * filename; @@ -328,8 +337,10 @@ static const int len_years[2] = { DAYSPERNYEAR, DAYSPERLYEAR }; -static time_t ats[TZ_MAX_TIMES]; -static unsigned char types[TZ_MAX_TIMES]; +static struct attype { + time_t at; + unsigned char type; +} attypes[TZ_MAX_TIMES]; static long gmtoffs[TZ_MAX_TYPES]; static char isdsts[TZ_MAX_TYPES]; static unsigned char abbrinds[TZ_MAX_TYPES]; @@ -349,7 +360,10 @@ memcheck(ptr) char * const ptr; { if (ptr == NULL) { - (void) perror(progname); + const char *e = strerror(errno); + + (void) fprintf(stderr, _("%s: Memory exhausted: %s\n"), + progname, e); (void) exit(EXIT_FAILURE); } return ptr; @@ -364,6 +378,19 @@ char * const ptr; ** 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 eats(name, num, rname, rnum) const char * const name; @@ -394,21 +421,32 @@ const char * const string; ** zic ... 2>&1 | error -t "*" -v ** on BSD systems. */ - (void) fprintf(stderr, "\"%s\", line %d: %s", + (void) fprintf(stderr, _("\"%s\", line %d: %s"), filename, linenum, string); if (rfilename != NULL) - (void) fprintf(stderr, " (rule from \"%s\", line %d)", + (void) fprintf(stderr, _(" (rule from \"%s\", line %d)"), rfilename, rlinenum); (void) fprintf(stderr, "\n"); ++errors; } +static void +warning(string) +const char * const string; +{ + char * cp; + + cp = ecpyalloc("warning: "); + cp = ecatalloc(cp, string); + error(string); + ifree(cp); + --errors; +} + static void usage P((void)) { - (void) fprintf(stderr, "%s: usage is %s \ -[ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ]\n\ -\t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n", + (void) fprintf(stderr, _("%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ]\n\t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"), progname, progname); (void) exit(EXIT_FAILURE); } @@ -432,6 +470,13 @@ char * argv[]; #ifdef unix (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH)); #endif /* defined unix */ +#if HAVE_GETTEXT - 0 + (void) setlocale(LC_MESSAGES, ""); +#ifdef TZ_DOMAINDIR + (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); +#endif /* defined TEXTDOMAINDIR */ + (void) textdomain(TZ_DOMAIN); +#endif /* HAVE_GETTEXT - 0 */ progname = argv[0]; while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF) switch (c) { @@ -442,7 +487,7 @@ char * argv[]; directory = optarg; else { (void) fprintf(stderr, -"%s: More than one -d option specified\n", +_("%s: More than one -d option specified\n"), progname); (void) exit(EXIT_FAILURE); } @@ -452,7 +497,7 @@ char * argv[]; lcltime = optarg; else { (void) fprintf(stderr, -"%s: More than one -l option specified\n", +_("%s: More than one -l option specified\n"), progname); (void) exit(EXIT_FAILURE); } @@ -462,7 +507,7 @@ char * argv[]; psxrules = optarg; else { (void) fprintf(stderr, -"%s: More than one -p option specified\n", +_("%s: More than one -p option specified\n"), progname); (void) exit(EXIT_FAILURE); } @@ -472,7 +517,7 @@ char * argv[]; yitcommand = optarg; else { (void) fprintf(stderr, -"%s: More than one -y option specified\n", +_("%s: More than one -y option specified\n"), progname); (void) exit(EXIT_FAILURE); } @@ -482,7 +527,7 @@ char * argv[]; leapsec = optarg; else { (void) fprintf(stderr, -"%s: More than one -L option specified\n", +_("%s: More than one -L option specified\n"), progname); (void) exit(EXIT_FAILURE); } @@ -565,9 +610,11 @@ const char * const tofile; if (mkdirs(toname) != 0) (void) exit(EXIT_FAILURE); if (link(fromname, toname) != 0) { - (void) fprintf(stderr, "%s: Can't link from %s to ", - progname, fromname); - (void) perror(toname); + const char *e = strerror(errno); + + (void) fprintf(stderr, + _("%s: Can't link from %s to %s: %s\n"), + progname, fromname, toname, e); (void) exit(EXIT_FAILURE); } } @@ -591,8 +638,7 @@ const char * const tofile; */ #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) +#define TIME_T_BITS_IN_FILE ((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE) static void setboundaries P((void)) @@ -650,11 +696,37 @@ associate P((void)) register struct zone * zp; register struct rule * rp; register int base, out; - register int i; + register int i, j; - if (nrules != 0) + if (nrules != 0) { (void) qsort((void *) rules, (size_t) nrules, (size_t) sizeof *rules, rcomp); + for (i = 0; i < nrules - 1; ++i) { + if (strcmp(rules[i].r_name, + rules[i + 1].r_name) != 0) + continue; + if (strcmp(rules[i].r_filename, + rules[i + 1].r_filename) == 0) + continue; + eat(rules[i].r_filename, rules[i].r_linenum); + warning(_("same rule name in multiple files")); + eat(rules[i + 1].r_filename, rules[i + 1].r_linenum); + warning(_("same rule name in multiple files")); + for (j = i + 2; j < nrules; ++j) { + if (strcmp(rules[i].r_name, + rules[j].r_name) != 0) + break; + if (strcmp(rules[i].r_filename, + rules[j].r_filename) == 0) + continue; + if (strcmp(rules[i + 1].r_filename, + rules[j].r_filename) == 0) + continue; + break; + } + i = j - 1; + } + } for (i = 0; i < nzones; ++i) { zp = &zones[i]; zp->z_rules = NULL; @@ -680,13 +752,14 @@ associate P((void)) ** Maybe we have a local standard time offset. */ eat(zp->z_filename, zp->z_linenum); - zp->z_stdoff = gethms(zp->z_rule, "unruly zone", TRUE); + zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"), + TRUE); /* ** Note, though, that if there's no rule, ** a '%s' in the format is a bad thing. */ if (strchr(zp->z_format, '%') != 0) - error("%s in ruleless zone"); + error(_("%s in ruleless zone")); } } if (errors) @@ -707,11 +780,13 @@ const char * name; char buf[BUFSIZ]; if (strcmp(name, "-") == 0) { - name = "standard input"; + name = _("standard input"); fp = stdin; } else if ((fp = fopen(name, "r")) == NULL) { - (void) fprintf(stderr, "%s: Can't open ", progname); - (void) perror(name); + const char *e = strerror(errno); + + (void) fprintf(stderr, _("%s: Can't open %s: %s\n"), + progname, name, e); (void) exit(EXIT_FAILURE); } wantcont = FALSE; @@ -721,7 +796,7 @@ const char * name; break; cp = strchr(buf, '\n'); if (cp == NULL) { - error("line too long"); + error(_("line too long")); (void) exit(EXIT_FAILURE); } *cp = '\0'; @@ -741,7 +816,7 @@ const char * name; } else { lp = byword(fields[0], line_codes); if (lp == NULL) - error("input line of unknown type"); + error(_("input line of unknown type")); else switch ((int) (lp->l_value)) { case LC_RULE: inrule(fields, nfields); @@ -757,14 +832,14 @@ const char * name; case LC_LEAP: if (name != leapsec) (void) fprintf(stderr, -"%s: Leap line in non leap seconds file %s\n", +_("%s: Leap line in non leap seconds file %s\n"), progname, name); else inleap(fields, nfields); wantcont = FALSE; break; default: /* "cannot happen" */ (void) fprintf(stderr, -"%s: panic: Invalid l_value %d\n", +_("%s: panic: Invalid l_value %d\n"), progname, lp->l_value); (void) exit(EXIT_FAILURE); } @@ -772,17 +847,19 @@ const char * name; ifree((char *) fields); } if (ferror(fp)) { - (void) fprintf(stderr, "%s: Error reading ", progname); - (void) perror(filename); + (void) fprintf(stderr, _("%s: Error reading %s\n"), + progname, filename); (void) exit(EXIT_FAILURE); } if (fp != stdin && fclose(fp)) { - (void) fprintf(stderr, "%s: Error closing ", progname); - (void) perror(filename); + const char *e = strerror(errno); + + (void) fprintf(stderr, _("%s: Error closing %s: %s\n"), + progname, filename, e); (void) exit(EXIT_FAILURE); } if (wantcont) - error("expected continuation line not found"); + error(_("expected continuation line not found")); } /* @@ -837,16 +914,16 @@ const int nfields; static struct rule r; if (nfields != RULE_FIELDS) { - error("wrong number of fields on Rule line"); + error(_("wrong number of fields on Rule line")); return; } if (*fields[RF_NAME] == '\0') { - error("nameless rule"); + error(_("nameless rule")); return; } r.r_filename = filename; r.r_linenum = linenum; - r.r_stdoff = gethms(fields[RF_STDOFF], "invalid saved time", TRUE); + r.r_stdoff = gethms(fields[RF_STDOFF], _("invalid saved time"), TRUE); rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND], fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); r.r_name = ecpyalloc(fields[RF_NAME]); @@ -865,13 +942,13 @@ const int nfields; static char * buf; if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) { - error("wrong number of fields on Zone line"); + 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, -"\"Zone %s\" line and -l option are mutually exclusive", +_("\"Zone %s\" line and -l option are mutually exclusive"), TZDEFAULT); error(buf); return FALSE; @@ -879,7 +956,7 @@ const int nfields; if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) { buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES))); (void) sprintf(buf, -"\"Zone %s\" line and -p option are mutually exclusive", +_("\"Zone %s\" line and -p option are mutually exclusive"), TZDEFRULES); error(buf); return FALSE; @@ -891,7 +968,7 @@ const int nfields; strlen(fields[ZF_NAME]) + strlen(zones[i].z_filename))); (void) sprintf(buf, -"duplicate zone name %s (file \"%s\", line %d)", +_("duplicate zone name %s (file \"%s\", line %d)"), fields[ZF_NAME], zones[i].z_filename, zones[i].z_linenum); @@ -907,7 +984,7 @@ register char ** const fields; const int nfields; { if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) { - error("wrong number of fields on Zone continuation line"); + error(_("wrong number of fields on Zone continuation line")); return FALSE; } return inzsub(fields, nfields, TRUE); @@ -947,10 +1024,10 @@ const int iscont; } z.z_filename = filename; z.z_linenum = linenum; - z.z_gmtoff = gethms(fields[i_gmtoff], "invalid GMT offset", TRUE); + z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid GMT offset"), TRUE); if ((cp = strchr(fields[i_format], '%')) != 0) { if (*++cp != 's' || strchr(cp, '%') != 0) { - error("invalid abbreviation format"); + error(_("invalid abbreviation format")); return FALSE; } } @@ -976,8 +1053,7 @@ const int iscont; zones[nzones - 1].z_untiltime > min_time && zones[nzones - 1].z_untiltime < max_time && 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; } } @@ -1004,7 +1080,7 @@ const int nfields; time_t t; if (nfields != LEAP_FIELDS) { - error("wrong number of fields on Leap line"); + error(_("wrong number of fields on Leap line")); return; } dayoff = 0; @@ -1013,7 +1089,7 @@ const int nfields; /* * Leapin' Lizards! */ - error("invalid leaping year"); + error(_("invalid leaping year")); return; } j = EPOCH_YEAR; @@ -1028,7 +1104,7 @@ const int nfields; dayoff = oadd(dayoff, eitol(i)); } if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) { - error("invalid month name"); + error(_("invalid month name")); return; } month = lp->l_value; @@ -1041,12 +1117,12 @@ const int nfields; cp = fields[LP_DAY]; if (sscanf(cp, scheck(cp, "%d"), &day) != 1 || day <= 0 || day > len_months[isleap(year)][month]) { - error("invalid day of month"); + error(_("invalid day of month")); return; } dayoff = oadd(dayoff, eitol(day - 1)); if (dayoff < 0 && !TYPE_SIGNED(time_t)) { - error("time before zero"); + error(_("time before zero")); return; } t = (time_t) dayoff * SECSPERDAY; @@ -1054,10 +1130,10 @@ const int nfields; ** Cheap overflow check. */ if (t / SECSPERDAY != dayoff) { - error("time overflow"); + error(_("time overflow")); return; } - tod = gethms(fields[LP_TIME], "invalid time of day", FALSE); + tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE); cp = fields[LP_CORR]; { register int positive; @@ -1076,11 +1152,11 @@ const int nfields; positive = TRUE; count = 2; } else { - error("illegal CORRECTION field on Leap line"); + error(_("illegal CORRECTION field on Leap line")); return; } 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; } leapadd(tadd(t, tod), positive, lp->l_value, count); @@ -1095,15 +1171,15 @@ const int nfields; struct link l; if (nfields != LINK_FIELDS) { - error("wrong number of fields on Link line"); + error(_("wrong number of fields on Link line")); return; } if (*fields[LF_FROM] == '\0') { - error("blank FROM field on Link line"); + error(_("blank FROM field on Link line")); return; } if (*fields[LF_TO] == '\0') { - error("blank TO field on Link line"); + error(_("blank TO field on Link line")); return; } l.l_filename = filename; @@ -1131,7 +1207,7 @@ const char * const timep; register char * ep; if ((lp = byword(monthp, mon_names)) == NULL) { - error("invalid month name"); + error(_("invalid month name")); return; } rp->r_month = lp->l_value; @@ -1159,7 +1235,7 @@ const char * const timep; break; } } - rp->r_tod = gethms(dp, "invalid time of day", FALSE); + rp->r_tod = gethms(dp, _("invalid time of day"), FALSE); ifree(dp); /* ** Year work. @@ -1175,11 +1251,11 @@ const char * const timep; break; default: /* "cannot happen" */ (void) fprintf(stderr, - "%s: panic: Invalid l_value %d\n", + _("%s: panic: Invalid l_value %d\n"), progname, lp->l_value); (void) exit(EXIT_FAILURE); } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) { - error("invalid starting year"); + error(_("invalid starting year")); return; } cp = hiyearp; @@ -1195,22 +1271,22 @@ const char * const timep; break; default: /* "cannot happen" */ (void) fprintf(stderr, - "%s: panic: Invalid l_value %d\n", + _("%s: panic: Invalid l_value %d\n"), progname, lp->l_value); (void) exit(EXIT_FAILURE); } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) { - error("invalid ending year"); + error(_("invalid ending year")); return; } if (rp->r_loyear > rp->r_hiyear) { - error("starting year greater than ending year"); + error(_("starting year greater than ending year")); return; } if (*typep == '\0') rp->r_yrtype = NULL; else { if (rp->r_loyear == rp->r_hiyear) { - error("typed single year"); + error(_("typed single year")); return; } rp->r_yrtype = ecpyalloc(typep); @@ -1240,12 +1316,12 @@ const char * const timep; if (rp->r_dycode != DC_DOM) { *ep++ = 0; if (*ep++ != '=') { - error("invalid day of month"); + error(_("invalid day of month")); ifree(dp); return; } if ((lp = byword(dp, wday_names)) == NULL) { - error("invalid weekday name"); + error(_("invalid weekday name")); ifree(dp); return; } @@ -1254,7 +1330,7 @@ const char * const timep; if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 || rp->r_dayofmonth <= 0 || (rp->r_dayofmonth > len_months[1][rp->r_month])) { - error("invalid day of month"); + error(_("invalid day of month")); ifree(dp); return; } @@ -1285,6 +1361,18 @@ FILE * const fp; (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); } +static int +atcomp(avp, bvp) +void * avp; +void * bvp; +{ + if (((struct attype *) avp)->at < ((struct attype *) bvp)->at) + return -1; + else if (((struct attype *) avp)->at > ((struct attype *) bvp)->at) + return 1; + else return 0; +} + static void writezone(name) const char * const name; @@ -1293,16 +1381,71 @@ const char * const name; register int i, j; static char * fullname; static struct tzhead tzh; + time_t ats[TZ_MAX_TIMES]; + unsigned char types[TZ_MAX_TIMES]; + /* + ** Sort. + */ + if (timecnt > 1) + (void) qsort((void *) attypes, (size_t) timecnt, + (size_t) sizeof *attypes, atcomp); + /* + ** Optimize. + */ + { + int fromi; + int toi; + + toi = 0; + fromi = 0; + if (isdsts[0] == 0) + while (attypes[fromi].type == 0) + ++fromi; /* handled by default rule */ + for ( ; fromi < timecnt; ++fromi) { + if (toi != 0 + && ((attypes[fromi].at + + gmtoffs[attypes[toi - 1].type]) + <= (attypes[toi - 1].at + + gmtoffs[toi == 1 ? 0 + : attypes[toi - 2].type]))) { + attypes[toi - 1].type = attypes[fromi].type; + continue; + } + if (toi == 0 || + attypes[toi - 1].type != attypes[fromi].type) + attypes[toi++] = attypes[fromi]; + } + timecnt = toi; + } + /* + ** Transfer. + */ + for (i = 0; i < timecnt; ++i) { + ats[i] = attypes[i].at; + types[i] = attypes[i].type; + } fullname = erealloc(fullname, (int) (strlen(directory) + 1 + strlen(name) + 1)); (void) sprintf(fullname, "%s/%s", directory, name); + /* + ** Remove old file, if any, to snap links. + */ + if (!itsdir(fullname) && remove(fullname) != 0 && errno != ENOENT) { + const char *e = strerror(errno); + + (void) fprintf(stderr, _("%s: Can't remove %s: %s\n"), + progname, fullname, e); + (void) exit(EXIT_FAILURE); + } if ((fp = fopen(fullname, "wb")) == NULL) { if (mkdirs(fullname) != 0) (void) exit(EXIT_FAILURE); if ((fp = fopen(fullname, "wb")) == NULL) { - (void) fprintf(stderr, "%s: Can't create ", progname); - (void) perror(fullname); + const char *e = strerror(errno); + + (void) fprintf(stderr, _("%s: Can't create %s: %s\n"), + progname, fullname, e); (void) exit(EXIT_FAILURE); } } @@ -1312,8 +1455,7 @@ const char * const name; convert(eitol(timecnt), tzh.tzh_timecnt); convert(eitol(typecnt), tzh.tzh_typecnt); convert(eitol(charcnt), tzh.tzh_charcnt); -#define DO(field) (void) fwrite((void *) tzh.field, \ - (size_t) sizeof tzh.field, (size_t) 1, fp) +#define DO(field) (void) fwrite((void *) tzh.field, (size_t) sizeof tzh.field, (size_t) 1, fp) DO(tzh_reserved); DO(tzh_ttisgmtcnt); DO(tzh_ttisstdcnt); @@ -1366,8 +1508,8 @@ const char * const name; for (i = 0; i < typecnt; ++i) (void) putc(ttisgmts[i], fp); if (ferror(fp) || fclose(fp)) { - (void) fprintf(stderr, "%s: Write error on ", progname); - (void) perror(fullname); + (void) fprintf(stderr, _("%s: Error writing %s\n"), + progname, fullname); (void) exit(EXIT_FAILURE); } } @@ -1405,7 +1547,6 @@ const int zonecount; register long stdoff; register int year; register long startoff; - register int startisdst; register int startttisstd; register int startttisgmt; register int type; @@ -1413,7 +1554,6 @@ const int zonecount; INITIALIZE(untiltime); INITIALIZE(starttime); - INITIALIZE(startoff); /* ** Now. . .finally. . .generate some useful data! */ @@ -1438,7 +1578,8 @@ const int zonecount; continue; gmtoff = zp->z_gmtoff; eat(zp->z_filename, zp->z_linenum); - startisdst = -1; + *startbuf = '\0'; + startoff = zp->z_gmtoff; if (zp->z_nrules == 0) { stdoff = zp->z_stdoff; doabbr(startbuf, zp->z_format, @@ -1446,8 +1587,10 @@ const int zonecount; type = addtype(oadd(zp->z_gmtoff, stdoff), startbuf, stdoff != 0, startttisstd, startttisgmt); - if (usestart) + if (usestart) { addtt(starttime, type); + usestart = FALSE; + } else if (stdoff != 0) addtt(min_time, type); } else for (year = min_year; year <= max_year; ++year) { @@ -1518,36 +1661,25 @@ const int zonecount; rp->r_todo = FALSE; if (useuntil && ktime >= untiltime) break; + stdoff = rp->r_stdoff; + if (usestart && ktime == starttime) + usestart = FALSE; if (usestart) { - if (ktime < starttime) { - stdoff = rp->r_stdoff; - startoff = oadd(zp->z_gmtoff, - rp->r_stdoff); - doabbr(startbuf, zp->z_format, - rp->r_abbrvar, - rp->r_stdoff != 0); - startisdst = rp->r_stdoff != 0; - continue; - } - usestart = FALSE; - if (ktime != starttime) { - if (startisdst < 0 && - zp->z_gmtoff != - (zp - 1)->z_gmtoff) { - type = (timecnt == 0) ? 0 : - types[timecnt - 1]; - startoff = oadd(gmtoffs[type], - -(zp - 1)->z_gmtoff); - startisdst = startoff != 0; - startoff = oadd(startoff, - zp->z_gmtoff); - (void) strcpy(startbuf, - &chars[abbrinds[type]]); + if (ktime < starttime) { + startoff = oadd(zp->z_gmtoff, + stdoff); + doabbr(startbuf, zp->z_format, + rp->r_abbrvar, + rp->r_stdoff != 0); + continue; + } + if (*startbuf == '\0' && + startoff == oadd(zp->z_gmtoff, + stdoff)) { + doabbr(startbuf, zp->z_format, + rp->r_abbrvar, + rp->r_stdoff != 0); } - if (startisdst >= 0) -addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd, - startttisgmt)); - } } eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); @@ -1557,18 +1689,34 @@ addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd, type = addtype(offset, buf, rp->r_stdoff != 0, rp->r_todisstd, rp->r_todisgmt); addtt(ktime, type); - stdoff = rp->r_stdoff; } } + if (usestart) { + if (*startbuf == '\0' && + zp->z_format != NULL && + strchr(zp->z_format, '%') == NULL && + strchr(zp->z_format, '/') == NULL) + (void) strcpy(startbuf, zp->z_format); + eat(zp->z_filename, zp->z_linenum); + if (*startbuf == '\0') +error(_("can't determine time zone abbreviation to use just after until time")); + else addtt(starttime, + addtype(startoff, startbuf, + startoff != zp->z_gmtoff, + startttisstd, + startttisgmt)); + } /* ** Now we may get to set starttime for the next zone line. */ if (useuntil) { - starttime = tadd(zp->z_untiltime, -gmtoff); startttisstd = zp->z_untilrule.r_todisstd; startttisgmt = zp->z_untilrule.r_todisgmt; + starttime = zp->z_untiltime; if (!startttisstd) starttime = tadd(starttime, -stdoff); + if (!startttisgmt) + starttime = tadd(starttime, -gmtoff); } } writezone(zpfirst->z_name); @@ -1579,16 +1727,12 @@ addtt(starttime, type) const time_t starttime; const int type; { - if (timecnt != 0 && type == types[timecnt - 1]) - return; /* easy enough! */ - if (timecnt == 0 && type == 0 && isdsts[0] == 0) - return; /* handled by default rule */ if (timecnt >= TZ_MAX_TIMES) { - error("too many transitions?!"); + error(_("too many transitions?!")); (void) exit(EXIT_FAILURE); } - ats[timecnt] = starttime; - types[timecnt] = type; + attypes[timecnt].at = starttime; + attypes[timecnt].type = type; ++timecnt; } @@ -1602,6 +1746,18 @@ const int ttisgmt; { register int i, j; + if (isdst != TRUE && isdst != FALSE) { + error(_("internal error - addtype called with bad isdst")); + (void) exit(EXIT_FAILURE); + } + if (ttisstd != TRUE && ttisstd != FALSE) { + error(_("internal error - addtype called with bad ttisstd")); + (void) exit(EXIT_FAILURE); + } + if (ttisgmt != TRUE && ttisgmt != FALSE) { + error(_("internal error - addtype called with bad ttisgmt")); + (void) exit(EXIT_FAILURE); + } /* ** See if there's already an entry for this zone type. ** If so, just return its index. @@ -1618,7 +1774,7 @@ const int ttisgmt; ** many. */ if (typecnt >= TZ_MAX_TYPES) { - error("too many local time types"); + error(_("too many local time types")); (void) exit(EXIT_FAILURE); } gmtoffs[i] = gmtoff; @@ -1646,13 +1802,13 @@ int count; register int i, j; if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { - error("too many leap seconds"); + error(_("too many leap seconds")); (void) exit(EXIT_FAILURE); } for (i = 0; i < leapcnt; ++i) if (t <= trans[i]) { if (t == trans[i]) { - error("repeated leap second moment"); + error(_("repeated leap second moment")); (void) exit(EXIT_FAILURE); } break; @@ -1702,8 +1858,8 @@ const char * const type; return TRUE; if (result == (1 << 8)) return FALSE; - error("Wild result from command execution"); - (void) fprintf(stderr, "%s: command was '%s', result was %d\n", + error(_("Wild result from command execution")); + (void) fprintf(stderr, _("%s: command was '%s', result was %d\n"), progname, buf, result); for ( ; ; ) (void) exit(EXIT_FAILURE); @@ -1797,7 +1953,7 @@ register char * cp; else while ((*dp = *cp++) != '"') if (*dp != '\0') ++dp; - else error("Odd number of quotation marks"); + else error(_("Odd number of quotation marks")); } while (*cp != '\0' && *cp != '#' && (!isascii(*cp) || !isspace((unsigned char) *cp))); if (isascii(*cp) && isspace((unsigned char) *cp)) @@ -1817,7 +1973,7 @@ const long t2; t = t1 + t2; if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { - error("time overflow"); + error(_("time overflow")); (void) exit(EXIT_FAILURE); } return t; @@ -1836,7 +1992,7 @@ const long t2; return min_time; t = t1 + t2; if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { - error("time overflow"); + error(_("time overflow")); (void) exit(EXIT_FAILURE); } return t; @@ -1883,7 +2039,7 @@ register const int wantedy; if (rp->r_dycode == DC_DOWLEQ) --i; else { - error("use of 2/29 in non leap-year"); + error(_("use of 2/29 in non leap-year")); (void) exit(EXIT_FAILURE); } } @@ -1917,7 +2073,7 @@ register const int wantedy; --i; } if (i < 0 || i >= len_months[isleap(y)][m]) { - error("no day in month matches rule"); + error(_("no day in month matches rule")); (void) exit(EXIT_FAILURE); } } @@ -1940,7 +2096,7 @@ const char * const string; i = strlen(string) + 1; 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); } (void) strcpy(&chars[charcnt], string); @@ -1974,10 +2130,11 @@ char * const argname; ** It doesn't seem to exist, so we try to create it. */ if (mkdir(name, 0755) != 0) { + const char *e = strerror(errno); + (void) fprintf(stderr, - "%s: Can't create directory ", - progname); - (void) perror(name); + _("%s: Can't create directory %s: %s\n"), + progname, name, e); ifree(name); return -1; } @@ -1997,7 +2154,7 @@ const int i; 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", + _("%s: %d did not sign extend correctly\n"), progname, i); (void) exit(EXIT_FAILURE); } -- 2.20.1