From aff84ecc8f819a5f1134a83c067f8d7abf813138 Mon Sep 17 00:00:00 2001 From: wollman Date: Thu, 18 Jul 1996 19:40:52 +0000 Subject: Second part of the timezone code import for version 96h. This includes a number of bug fixes to the compiler (which bugs would previously have caused undesirable behavior during transition times). --- usr.sbin/zic/Music | 81 ++++++ usr.sbin/zic/README | 16 +- usr.sbin/zic/Theory | 20 +- usr.sbin/zic/WWW | 71 +++++ usr.sbin/zic/ialloc.c | 41 +-- usr.sbin/zic/scheck.c | 12 +- usr.sbin/zic/zdump.8 | 5 +- usr.sbin/zic/zdump.c | 149 +++++++--- usr.sbin/zic/zic.8 | 34 +-- usr.sbin/zic/zic.c | 758 ++++++++++++++++++++++++++++++++------------------ 10 files changed, 791 insertions(+), 396 deletions(-) create mode 100644 usr.sbin/zic/Music create mode 100644 usr.sbin/zic/WWW (limited to 'usr.sbin/zic') diff --git a/usr.sbin/zic/Music b/usr.sbin/zic/Music new file mode 100644 index 0000000..9fb0cec --- /dev/null +++ b/usr.sbin/zic/Music @@ -0,0 +1,81 @@ +@(#)Music 7.4 + +Data on recordings of "Save That Time," Russ Long, Serrob Publishing, BMI: +-------------------------------------------------------------------------- +Artist: Karrin Allyson +CD: I Didn't Know About You +Copyright Date: 1993 +Label: Concord Jazz, Inc. +ID: CCD-4543 +Track Time: 3:44 +Personnel: Karrin Allyson, vocal + Russ Long, piano + Gerald Spaits, bass + Todd Strait, drums +Notes: CD notes "additional lyric by Karrin Allyson; + arranged by Russ Long and Karrin Allyson" +Rating: 1 star +-------------------------------------------------------------------------- +Artist: Kevin Mahogany +CD: Double Rainbow +Copyright Date: 1993 +Label: Enja Records +ID: ENJ-7097 2 +Track Time: 6:27 +Personnel: Kevin Mahogany, vocal + Kenny Barron, piano + Ray Drummond, bss + Ralph Moore, tenor saxophone + Lewis Nash, drums +Rating: 1.5 stars +-------------------------------------------------------------------------- +Artist: Joe Williams +CD: Here's to Life +Copyright Date: 1994 +Label: Telarc International Corporation +ID: CD-83357 +Track Time: 3:58 +Personnel: Joe Williams, vocal + The Robert Farnon [39 piece] Orchestra +Rating: black dot +-------------------------------------------------------------------------- +Artist: Charles Fambrough +CD: Keeper of the Spirit +Copyright Date: 1995 +Label: AudioQuest Music +ID: AQ-CD1033 +Track Time: 7:07 +Personnel: Charles Fambrough, bass + Joel Levine, tenor recorder + Edward Simon, piano + Lenny White, drums + Marion Simon, percussion +Rating: 2 stars +========================================================================== +Also of note: +Artist: Milt Hinton +CD: Old Man Time +Date: 1993 +Label: Chiaroscuro +ID: CR(D) 310 +Total Time: 149:38 (two CDs) +Personnel: Milt Hinton, bass + Doc Cheatham, Dizzy Gillespie, Clark Terry, trumpet + Al Grey, trombone + Eddier Barefield, Joe Camel (Flip Phillips), Buddy Tate, + clarinet and saxophone + John Bunch, Red Richards, Norman Simmons, Derek Smith, + Ralph Sutton, piano + Danny Barker, Al Casey, guitar + Gus Johnson, Gerryck King, Bob Rosengarden, Jackie Williams, + drums + Lionel Hampton, vibraphone + Cab Calloway, Joe Williams, vocal + Buck Clayton, arrangements +Notes: tunes include Old Man Time, Time After Time, + Sometimes I'm Happy, + A Hot Time in the Old Town Tonight, + Four or Five Times, Now's the Time, + Time on My Hands, This Time It's Us, + and Good Time Charlie +Rating: 3 stars diff --git a/usr.sbin/zic/README b/usr.sbin/zic/README index 5eea1a2..3ca53ca 100644 --- a/usr.sbin/zic/README +++ b/usr.sbin/zic/README @@ -1,4 +1,4 @@ -@(#)README 7.5 +@(#)README 7.8 "What time is it?" -- Richard Deacon as The King "Any time you want it to be." -- Frank Baxter as The Scientist @@ -22,13 +22,6 @@ and as "part of the application" in others, there's no good way to name functions, such as timegm, that are not part of the proposed ANSI C standard; such functions have kept their old, underscore-free names in this update.) -Support for the tz_abbr variable has been eliminated from this version -(to forestall "kitchen sink" complaints from certain quarters :-). - -Support for Turbo C compilation has also been eliminated; it was present to -allow checking in an ANSI-style environment, and such checking is now done with -gcc. - And the "dysize" function has disappeared; it was present to allow compilation of the "date" command on old BSD systems, and a version of "date" is now provided in the package. The "date" command is not created when you "make all" @@ -64,9 +57,10 @@ Thanks to these Timezone Caballeros who've made major contributions to the time conversion package: Keith Bostic; Bob Devine; Paul Eggert; Robert Elz; Guy Harris; Mark Horton; John Mackin; and Bradley White. Thanks also to Michael Bloom, Art Neilson, Stephen Prince, John Sovereign, and Frank Wales -for testing work. None of them are responsible for remaining errors. +for testing work, and to Gwillim Law for checking local mean time data. +None of them are responsible for remaining errors. -Look in the ~ftp/pub directory of elsie.nci.nih.gov (128.231.16.1) +Look in the ~ftp/pub directory of elsie.nci.nih.gov for updated versions of these files. -Please send comments or information to ado@elsie.nci.nih.gov. +Please send comments or information to tz@elsie.nci.nih.gov. diff --git a/usr.sbin/zic/Theory b/usr.sbin/zic/Theory index 93a07c0..2e34663 100644 --- a/usr.sbin/zic/Theory +++ b/usr.sbin/zic/Theory @@ -1,4 +1,4 @@ -@(#)Theory 7.2 +@(#)Theory 7.4 These time and date functions are much like the System V Release 2.0 (SVR2) time and date functions; there are a few additions and changes to extend @@ -47,7 +47,7 @@ These are the changes that have been made to the SVR2 functions: abbreviations are used. It was recognized that allowing the "TZ" environment variable to - take on values such as "US/Eastern" might cause "old" programs + take on values such as "America/New_York" might cause "old" programs (that expect "TZ" to have a certain form) to operate incorrectly; consideration was given to using some other environment variable (for example, "TIMEZONE") to hold the string used to generate the @@ -79,8 +79,8 @@ These are the changes that have been made to the SVR2 functions: best approximation to local wall clock time to be delivered by subsequent calls to "localtime." Source code for portable applications that "must" run on local wall clock time should call - "tzsetwall();" if such code is moved to "old" systems that don't provide - tzsetwall, you won't be able to generate an executable program. + "tzsetwall();" if such code is moved to "old" systems that don't + provide tzsetwall, you won't be able to generate an executable program. (These time zone functions also arrange for local wall clock time to be used if tzset is called--directly or indirectly--and there's no "TZ" environment variable; portable applications should not, however, rely @@ -94,8 +94,8 @@ Points of interest to folks with Version 7 or BSD systems: time zone abbreviation, and we refuse to guess. Programs that in the past used the timezone function may now examine tzname[localtime(&clock)->tm_isdst] to learn the correct time - zone abbreviation to use. Alternatively, use localtime(&clock)->tm_zone - if this has been enabled. + zone abbreviation to use. Alternatively, use + localtime(&clock)->tm_zone if this has been enabled. * The BSD gettimeofday function is not used in this package; this lets users control the time zone used in doing time conversions. @@ -104,10 +104,10 @@ Points of interest to folks with Version 7 or BSD systems: file "/etc/zoneinfo/localtime"; see the time zone compiler writeup for information on how to initialize this file. -The functions that are conditionally compiled if STD_INSPIRED is defined should, -at this point, be looked on primarily as food for thought. They are not in -any sense "standard compatible"--some are not, in fact, specified in *any* -standard. They do, however, represent responses of various authors to +The functions that are conditionally compiled if STD_INSPIRED is defined +should, at this point, be looked on primarily as food for thought. They are +not in any sense "standard compatible"--some are not, in fact, specified in +*any* standard. They do, however, represent responses of various authors to standardization proposals. Other time conversion proposals, in particular the one developed by folks at diff --git a/usr.sbin/zic/WWW b/usr.sbin/zic/WWW new file mode 100644 index 0000000..d2fd684 --- /dev/null +++ b/usr.sbin/zic/WWW @@ -0,0 +1,71 @@ +# '@(#)WWW 7.3' + +# From Paul Eggert (1995-11-03) +# +# The Web has several other sources for time zone and daylight savings data. +# Here are some recent links that may be of interest. +# +# Date and Time Gateway +# http://www.bsdi.com/date +# A text-based source for tables of current time throughout the world. +# Its point-and-click interface accesses a recent version of the tz data. +# +# Local Times Around the World +# http://www.hilink.com.au/times/ +# This text-based system contains links to local time servers +# throughout the world, and though the coverage is limited, +# the live data provide a nice way to check one's tables. +# +# World Time Zones +# http://tycho.usno.navy.mil/tzones.html +# US Naval Observatory data, used as the source for `usno1995'. +# +# Standard Time Zones of the World +# http://www.odci.gov/cia/publications/95fact/802389.gif [54 kB] +# http://www.odci.gov/cia/publications/95fact/802389h.gif [1317 kB] +# A static time zone map, available in both low-resolution and +# high-resolution versions. The quality is good, but the map does not +# indicate summer time, and parts of the data are a few years out of date. +# +# VIBE's World Map +# http://pathfinder.com/vibe/vibeworld +# An active time zone map. You can point to the map and find out what +# time it is at that location. The map and data are not as good as +# other sources. + +############################################################################### + +# From Manavendra Thakur (1995-11-06) +# +# To Paul's list of time zone information on the web, I would add the +# following URL: +# http://www.dhl.com/dhl/dhlinfo/1bb.html +# or more simply: +# http://www.dhl.com/ +# +# This is run by DHL (the courier company), and it presents a list of the +# countries served by that company. If you then click on a particular +# country, here's an example of what you'll see (graphics stripped out): +# +# United Kingdom +# +# HOLIDAYS: Jan 1, 2, Apr 14, 17, May 1, 29, Aug 28, Dec 25, 26 +# +# INTERNATIONAL DIALING CODE: +44 +# +# CURRENT LOCAL TIME: 09:41 Monday 6 November 1995 +# +# I find this rather handy, and given that DHL covers 217 countries and +# territories, it's pretty comprehensive coverage. +# +# (I have no idea what system DHL is using to calculate the local time, but +# it's been accurate so far.) + +############################################################################### + + +# From Arthur David Olson (1996-01-04) +# +# A good source of information about ISO 8601 seems to be +# http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html +# maintained by Markus Kuhn. diff --git a/usr.sbin/zic/ialloc.c b/usr.sbin/zic/ialloc.c index 7dc2f2b..5631947 100644 --- a/usr.sbin/zic/ialloc.c +++ b/usr.sbin/zic/ialloc.c @@ -1,6 +1,6 @@ #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)ialloc.c 8.21"; +static char elsieid[] = "@(#)ialloc.c 8.28"; #endif /* !defined NOID */ #endif /* !defined lint */ @@ -8,35 +8,20 @@ static char elsieid[] = "@(#)ialloc.c 8.21"; #include "private.h" -#ifdef MAL -#define NULLMAL(x) ((x) == NULL || (x) == MAL) -#endif /* defined MAL */ -#ifndef MAL -#define NULLMAL(x) ((x) == NULL) -#endif /* !defined MAL */ - #define nonzero(n) (((n) == 0) ? 1 : (n)) char * icalloc P((int nelem, int elsize)); char * icatalloc P((char * old, const char * new)); char * icpyalloc P((const char * string)); char * imalloc P((int n)); -char * irealloc P((char * pointer, int size)); +void * irealloc P((void * pointer, int size)); void ifree P((char * pointer)); char * imalloc(n) const int n; { -#ifdef MAL - register char * result; - - result = malloc((alloc_size_t) nonzero(n)); - return NULLMAL(result) ? NULL : result; -#endif /* defined MAL */ -#ifndef MAL - return malloc((alloc_size_t) nonzero(n)); -#endif /* !defined MAL */ + return malloc((size_t) nonzero(n)); } char * @@ -46,17 +31,17 @@ int elsize; { if (nelem == 0 || elsize == 0) nelem = elsize = 1; - return calloc((alloc_size_t) nelem, (alloc_size_t) elsize); + return calloc((size_t) nelem, (size_t) elsize); } -char * +void * irealloc(pointer, size) -char * const pointer; +void * const pointer; const int size; { - if (NULLMAL(pointer)) + if (pointer == NULL) return imalloc(size); - return realloc((genericptr_t) pointer, (alloc_size_t) nonzero(size)); + return realloc((void *) pointer, (size_t) nonzero(size)); } char * @@ -67,14 +52,14 @@ const char * const new; register char * result; register int oldsize, newsize; - newsize = NULLMAL(new) ? 0 : strlen(new); - if (NULLMAL(old)) + newsize = (new == NULL) ? 0 : strlen(new); + if (old == NULL) oldsize = 0; else if (newsize == 0) return old; else oldsize = strlen(old); if ((result = irealloc(old, oldsize + newsize + 1)) != NULL) - if (!NULLMAL(new)) + if (new != NULL) (void) strcpy(result + oldsize, new); return result; } @@ -90,7 +75,7 @@ void ifree(p) char * const p; { - if (!NULLMAL(p)) + if (p != NULL) (void) free(p); } @@ -98,6 +83,6 @@ void icfree(p) char * const p; { - if (!NULLMAL(p)) + if (p != NULL) (void) free(p); } diff --git a/usr.sbin/zic/scheck.c b/usr.sbin/zic/scheck.c index 4d9616d..64f2507 100644 --- a/usr.sbin/zic/scheck.c +++ b/usr.sbin/zic/scheck.c @@ -1,6 +1,6 @@ #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)scheck.c 8.11"; +static char elsieid[] = "@(#)scheck.c 8.13"; #endif /* !defined lint */ #endif /* !defined NOID */ @@ -14,7 +14,7 @@ extern void ifree P((char * p)); char * scheck(string, format) const char * const string; -const char * const format; +char * const format; { register char * fbuf; register const char * fp; @@ -22,12 +22,12 @@ const char * const format; register int c; register char * result; char dummy; - static char nada[1]; + static char nada; - result = nada; + result = &nada; if (string == NULL || format == NULL) return result; - fbuf = imalloc(2 * strlen(format) + 4); + fbuf = imalloc((int) (2 * strlen(format) + 4)); if (fbuf == NULL) return result; fp = format; @@ -42,7 +42,7 @@ const char * const format; *tp++ = '*'; if (*fp == '*') ++fp; - while (isascii(*fp) && isdigit(*fp)) + while (is_digit(*fp)) *tp++ = *fp++; if (*fp == 'l' || *fp == 'h') *tp++ = *fp++; diff --git a/usr.sbin/zic/zdump.8 b/usr.sbin/zic/zdump.8 index 23f4946..3323129 100644 --- a/usr.sbin/zic/zdump.8 +++ b/usr.sbin/zic/zdump.8 @@ -20,8 +20,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, @@ -37,4 +36,4 @@ otherwise. Cut off the verbose output near the start of the given year. .SH "SEE ALSO" newctime(3), tzfile(5), zic(8) -.\" @(#)zdump.8 7.2 +.\" @(#)zdump.8 7.3 diff --git a/usr.sbin/zic/zdump.c b/usr.sbin/zic/zdump.c index 1e44d4a..1058a84 100644 --- a/usr.sbin/zic/zdump.c +++ b/usr.sbin/zic/zdump.c @@ -1,6 +1,6 @@ #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)zdump.c 7.10"; +static char elsieid[] = "@(#)zdump.c 7.24"; #endif /* !defined NOID */ #endif /* !defined lint */ @@ -10,10 +10,11 @@ static char elsieid[] = "@(#)zdump.c 7.10"; ** You can use this code to help in verifying other implementations. */ -#include "stdio.h" /* for stdout, stderr */ +#include "stdio.h" /* for stdout, stderr, perror */ #include "string.h" /* for strcpy */ #include "sys/types.h" /* for time_t */ #include "time.h" /* for struct tm */ +#include "stdlib.h" /* for exit, malloc, atoi */ #ifndef MAX_STRING_LENGTH #define MAX_STRING_LENGTH 1024 @@ -67,18 +68,55 @@ static char elsieid[] = "@(#)zdump.c 7.10"; #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 +#endif /* defined lint */ +#ifndef lint +#ifdef __GNUC__ +#define GNUC_or_lint +#endif /* defined __GNUC__ */ +#endif /* !defined lint */ +#endif /* !defined GNUC_or_lint */ + +#ifndef INITIALIZE +#ifdef GNUC_or_lint +#define INITIALIZE(x) ((x) = 0) +#endif /* defined GNUC_or_lint */ +#ifndef GNUC_or_lint +#define INITIALIZE(x) +#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; extern int optind; extern time_t time(); extern char * tzname[2]; -extern void tzset(); - -#ifdef USG -extern void exit(); -extern void perror(); -#endif /* defined USG */ static char * abbr(); static long delta(); @@ -92,16 +130,28 @@ main(argc, argv) int argc; char * argv[]; { - register int i, c; - register int vflag; - register char * cutoff; - register int cutyear; - register long cuttime; - time_t now; - time_t t, newt; - time_t hibit; - struct tm tm, newtm; - + register int i; + register int c; + register int vflag; + register char * cutoff; + register int cutyear; + register long cuttime; + char ** fakeenv; + time_t now; + time_t t; + time_t newt; + time_t hibit; + struct tm tm; + 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; @@ -112,7 +162,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); } @@ -132,28 +182,36 @@ char * argv[]; longest = strlen(argv[i]); for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) continue; - for (i = optind; i < argc; ++i) { - register char ** saveenv; - static char buf[MAX_STRING_LENGTH]; - char * fakeenv[2]; - - if (strlen(argv[i]) + 4 > sizeof buf) { - (void) fflush(stdout); - (void) fprintf(stderr, "%s: argument too long -- %s\n", - progname, argv[i]); - (void) exit(EXIT_FAILURE); + { + register int from; + register int to; + + for (i = 0; environ[i] != NULL; ++i) + continue; + fakeenv = (char **) malloc((size_t) ((i + 2) * + sizeof *fakeenv)); + if (fakeenv == NULL || + (fakeenv[0] = (char *) malloc((size_t) (longest + + 4))) == NULL) { + (void) perror(progname); + (void) exit(EXIT_FAILURE); } - (void) strcpy(buf, "TZ="); - (void) strcat(buf, argv[i]); - fakeenv[0] = buf; - fakeenv[1] = NULL; - saveenv = environ; + to = 0; + (void) strcpy(fakeenv[to++], "TZ="); + for (from = 0; environ[from] != NULL; ++from) + if (strncmp(environ[from], "TZ=", 3) != 0) + fakeenv[to++] = environ[from]; + fakeenv[to] = NULL; environ = fakeenv; - (void) tzset(); - environ = saveenv; - show(argv[i], now, FALSE); - if (!vflag) + } + for (i = optind; i < argc; ++i) { + static char buf[MAX_STRING_LENGTH]; + + (void) strcpy(&fakeenv[0][3], argv[i]); + if (!vflag) { + show(argv[i], now, FALSE); continue; + } /* ** Get lowest value of t. */ @@ -197,9 +255,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); @@ -268,14 +326,15 @@ struct tm * oldp; return result; } +extern struct tm * localtime(); + static void show(zone, t, v) char * zone; time_t t; int v; { - struct tm * tmp; - extern struct tm * localtime(); + struct tm * tmp; (void) printf("%-*s ", longest, zone); if (v) @@ -298,10 +357,10 @@ abbr(tmp) struct tm * tmp; { register char * result; - static char nada[1]; + static char nada; if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1) - return nada; + return &nada; result = tzname[tmp->tm_isdst]; - return (result == NULL) ? nada : result; + return (result == NULL) ? &nada : result; } diff --git a/usr.sbin/zic/zic.8 b/usr.sbin/zic/zic.8 index 6972d0e..979f4fa 100644 --- a/usr.sbin/zic/zic.8 +++ b/usr.sbin/zic/zic.8 @@ -154,17 +154,7 @@ then the rule applies in all years between .B FROM and .B TO -inclusive; -if -.B TYPE -is -.BR uspres , -the rule applies in U.S. Presidential election years; -if -.B TYPE -is -.BR nonpres , -the rule applies in years other than U.S. Presidential election years. +inclusive. If .B TYPE is something else, then @@ -219,14 +209,18 @@ Any of these forms may be followed by the letter .B w if the given time is local .q "wall clock" -time or +time, .B s if the given time is local .q standard -time; in the absence of -.B w +time, or +.B u +(or +.B g or -.BR s , +.BR z ) +if the given time is universal time; +in the absence of an indicator, wall clock time is assumed. .TP .B SAVE @@ -300,6 +294,9 @@ The pair of characters is used to show where the .q "variable part" of the time zone abbreviation goes. +Alternately, +a slash (/) +separates standard and daylight abbreviations. .TP .B UNTIL The time at which the GMT offset or the rule(s) change for a location. @@ -326,14 +323,13 @@ A link line has the form .sp .nf .ti +.5i -.if t .ta \w'Link\0\0'u +\w'LINK-FROM\0\0'u -.if n .ta \w'Link\0\0'u +\w'US/Eastern\0\0'u +.ta \w'Link\0\0'u +\w'Europe/Istanbul\0\0'u Link LINK-FROM LINK-TO .sp For example: .sp .ti +.5i -Link US/Eastern EST5EDT +Link Europe/Istanbul Asia/Istanbul .sp .fi The @@ -409,4 +405,4 @@ the earliest transition time recorded in the compiled file is correct. /usr/local/etc/zoneinfo standard directory used for created files .SH "SEE ALSO" newctime(3), tzfile(5), zdump(8) -.\" @(#)zic.8 7.7 +.\" @(#)zic.8 7.12 diff --git a/usr.sbin/zic/zic.c b/usr.sbin/zic/zic.c index a0dc5f6..0cec893 100644 --- a/usr.sbin/zic/zic.c +++ b/usr.sbin/zic/zic.c @@ -1,11 +1,28 @@ #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)zic.c 7.22"; +static char elsieid[] = "@(#)zic.c 7.77"; #endif /* !defined NOID */ #endif /* !defined lint */ #include "private.h" +#include "locale.h" #include "tzfile.h" +#ifdef unix +#include "sys/stat.h" /* for umask manifest constants */ +#endif /* defined unix */ + +/* +** On some ancient hosts, predicates like `isspace(C)' are defined +** 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. +** Neither the C Standard nor Posix require that `isascii' exist. +** For portability, we check both ancient and modern requirements. +** If isascii is not defined, the isascii check succeeds trivially. +*/ +#include "ctype.h" +#ifndef isascii +#define isascii(x) 1 +#endif struct rule { const char * r_filename; @@ -25,6 +42,8 @@ struct rule { long r_tod; /* time from midnight */ int r_todisstd; /* above is standard time if TRUE */ /* or wall clock time if FALSE */ + int r_todisgmt; /* above is GMT if TRUE */ + /* or local time if FALSE */ long r_stdoff; /* offset from standard time */ const char * r_abbrvar; /* variable part of abbreviation */ @@ -58,13 +77,13 @@ struct zone { time_t z_untiltime; }; -extern int emkdir P((const char * name, int mode)); -extern int getopt P((int argc, char * argv[], const char * options)); +extern int getopt P((int argc, char * const argv[], + const char * options)); extern char * icatalloc P((char * old, const char * new)); extern char * icpyalloc P((const char * string)); extern void ifree P((char * p)); extern char * imalloc P((int n)); -extern char * irealloc P((char * old, int n)); +extern void * irealloc P((void * old, int n)); extern int link P((const char * fromname, const char * toname)); extern char * optarg; extern int optind; @@ -72,13 +91,15 @@ extern char * scheck P((const char * string, const char * format)); static void addtt P((time_t starttime, int type)); static int addtype P((long gmtoff, const char * abbr, int isdst, - int ttisstd)); + int ttisstd, int ttisgmt)); static void leapadd P((time_t t, int positive, int rolling, int count)); static void adjleap P((void)); static void associate P((void)); static int ciequal P((const char * ap, const char * bp)); static void convert P((long val, char * buf)); static void dolink P((const char * fromfile, const char * tofile)); +static void doabbr P((char * abbr, const char * format, + const char * letters, int isdst)); static void eat P((const char * name, int num)); static void eats P((const char * name, int num, const char * rname, int rnum)); @@ -103,27 +124,29 @@ static void newabbr P((const char * abbr)); static long oadd P((long t1, long t2)); static void outzone P((const struct zone * zp, int ntzones)); static void puttzcode P((long code, FILE * fp)); -static int rcomp P((const genericptr_t leftp, const genericptr_t rightp)); +static int rcomp P((const void * leftp, const void * rightp)); static time_t rpytime P((const struct rule * rp, int wantedy)); static void rulesub P((struct rule * rp, - char * loyearp, char * hiyearp, - char * typep, char * monthp, - char * dayp, char * timep)); + const char * loyearp, const char * hiyearp, + const char * typep, const char * monthp, + const char * dayp, const char * timep)); static void setboundaries P((void)); static time_t tadd P((time_t t1, long t2)); static void usage P((void)); static void writezone P((const char * name)); static int yearistype P((int year, const char * type)); +#if !HAVE_STRERROR +static char * strerror P((int)); +#endif /* !HAVE_STRERROR */ + static int charcnt; static int errors; static const char * filename; static int leapcnt; static int linenum; -static int max_int; static time_t max_time; static int max_year; -static int min_int; static time_t min_time; static int min_year; static int noise; @@ -132,7 +155,6 @@ static int rlinenum; static const char * progname; static int timecnt; static int typecnt; -static int tt_signed; /* ** Line codes. @@ -313,12 +335,15 @@ 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]; static char ttisstds[TZ_MAX_TYPES]; +static char ttisgmts[TZ_MAX_TYPES]; static char chars[TZ_MAX_CHARS]; static time_t trans[TZ_MAX_LEAPS]; static long corr[TZ_MAX_LEAPS]; @@ -333,21 +358,37 @@ 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; } #define emalloc(size) memcheck(imalloc(size)) -#define erealloc(ptr, size) memcheck(irealloc(ptr, size)) +#define erealloc(ptr, size) memcheck(irealloc((ptr), (size))) #define ecpyalloc(ptr) memcheck(icpyalloc(ptr)) -#define ecatalloc(oldp, newp) memcheck(icatalloc(oldp, newp)) +#define ecatalloc(oldp, newp) memcheck(icatalloc((oldp), (newp))) /* ** Error handling. */ +#if ! HAVE_STRERROR +static char * +strerror(errnum) +int errnum; +{ + extern char *sys_errlist[]; + extern int sys_nerr; + + if (errnum > 0 && errnum <= sys_nerr) + return sys_errlist[errnum]; + return "Unknown system error"; +} +#endif /* ! HAVE_STRERROR */ + static void eats(name, num, rname, rnum) const char * const name; @@ -375,24 +416,35 @@ const char * const string; { /* ** Match the format of "cc" to allow sh users to - ** zic ... 2>&1 | error -t "*" -v + ** 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 -usage() +warning(string) +const char * const string; { - (void) fprintf(stderr, -"%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ] \n\ -\t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n", + 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"), progname, progname); (void) exit(EXIT_FAILURE); } @@ -409,12 +461,20 @@ main(argc, argv) int argc; char * argv[]; { - register int i, j; + register int i; + register int j; register int c; #ifdef unix - (void) umask(umask(022) | 022); + (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) { @@ -425,7 +485,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); } @@ -435,7 +495,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); } @@ -445,7 +505,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); } @@ -455,7 +515,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); } @@ -465,7 +525,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); } @@ -491,9 +551,6 @@ char * argv[]; adjleap(); } - zones = (struct zone *) emalloc(0); - rules = (struct rule *) emalloc(0); - links = (struct link *) emalloc(0); for (i = optind; i < argc; ++i) infile(argv[i]); if (errors) @@ -528,14 +585,14 @@ const char * const tofile; register char * toname; if (fromfile[0] == '/') - fromname = fromfile; + fromname = ecpyalloc(fromfile); else { fromname = ecpyalloc(directory); fromname = ecatalloc(fromname, "/"); fromname = ecatalloc(fromname, fromfile); } if (tofile[0] == '/') - toname = tofile; + toname = ecpyalloc(tofile); else { toname = ecpyalloc(directory); toname = ecatalloc(toname, "/"); @@ -551,48 +608,52 @@ 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); } } - if (fromname != fromfile) - ifree(fromname); - if (toname != tofile) - ifree(toname); + ifree(fromname); + ifree(toname); } +#ifndef INT_MAX +#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 -setboundaries() +setboundaries P((void)) { - register time_t bit; - register int bii; - - for (bit = 1; bit > 0; bit <<= 1) - continue; - if (bit == 0) { /* time_t is an unsigned type */ - tt_signed = FALSE; - min_time = 0; - max_time = ~(time_t) 0; - if (sflag) - max_time >>= 1; - } else { - tt_signed = TRUE; - min_time = bit; - max_time = bit; - ++max_time; - max_time = -max_time; + if (TYPE_SIGNED(time_t)) { + min_time = ~ (time_t) 0; + min_time <<= TIME_T_BITS_IN_FILE - 1; + max_time = ~ (time_t) 0 - min_time; if (sflag) min_time = 0; + } 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; - - for (bii = 1; bii > 0; bii <<= 1) - continue; - min_int = bii; - max_int = -1 - bii; } static int @@ -604,7 +665,7 @@ const char * const name; myname = ecpyalloc(name); myname = ecatalloc(myname, "/."); - accres = access(myname, 0); + accres = access(myname, F_OK); ifree(myname); return accres == 0; } @@ -619,25 +680,50 @@ const char * const name; static int rcomp(cp1, cp2) -const genericptr_t cp1; -const genericptr_t cp2; +const void * cp1; +const void * cp2; { - return strcmp(((struct rule *) cp1)->r_name, - ((struct rule *) cp2)->r_name); + return strcmp(((const struct rule *) cp1)->r_name, + ((const struct rule *) cp2)->r_name); } static void -associate() +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) - (void) qsort((genericptr_t) rules, - (qsort_size_t) nrules, - (qsort_size_t) sizeof *rules, rcomp); + 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; @@ -663,13 +749,14 @@ associate() ** 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) @@ -690,11 +777,12 @@ 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; @@ -704,17 +792,17 @@ 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'; fields = getfields(buf); nfields = 0; while (fields[nfields] != NULL) { - static char nada[1]; + static char nada; - if (ciequal(fields[nfields], "-")) - fields[nfields] = nada; + if (strcmp(fields[nfields], "-") == 0) + fields[nfields] = &nada; ++nfields; } if (nfields == 0) { @@ -724,7 +812,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); @@ -740,14 +828,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); } @@ -755,22 +843,23 @@ 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")); } /* ** Convert a string of one of the forms -** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss +** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss ** into a number of seconds. ** A null string maps to zero. ** Call error with errstring and return zero on errors. @@ -820,21 +909,21 @@ 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]); r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); - rules = (struct rule *) erealloc((char *) rules, + rules = (struct rule *) (void *) erealloc((char *) rules, (int) ((nrules + 1) * sizeof *rules)); rules[nrules++] = r; } @@ -848,21 +937,21 @@ 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, 132 + strlen(TZDEFAULT)); + 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; } if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) { - buf = erealloc(buf, 132 + strlen(TZDEFRULES)); + 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; @@ -870,11 +959,11 @@ const int nfields; for (i = 0; i < nzones; ++i) if (zones[i].z_name != NULL && strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) { - buf = erealloc(buf, 132 + + buf = erealloc(buf, (int) (132 + strlen(fields[ZF_NAME]) + - strlen(zones[i].z_filename)); + 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); @@ -890,7 +979,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); @@ -930,10 +1019,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; } } @@ -959,11 +1048,11 @@ 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; } } - zones = (struct zone *) erealloc((char *) zones, + zones = (struct zone *) (void *) erealloc((char *) zones, (int) ((nzones + 1) * sizeof *zones)); zones[nzones++] = z; /* @@ -986,7 +1075,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; @@ -995,7 +1084,7 @@ const int nfields; /* * Leapin' Lizards! */ - error("invalid leaping year"); + error(_("invalid leaping year")); return; } j = EPOCH_YEAR; @@ -1010,7 +1099,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; @@ -1023,12 +1112,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 && !tt_signed) { - error("time before zero"); + if (dayoff < 0 && !TYPE_SIGNED(time_t)) { + error(_("time before zero")); return; } t = (time_t) dayoff * SECSPERDAY; @@ -1036,10 +1125,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; @@ -1058,11 +1147,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); @@ -1077,22 +1166,22 @@ 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; l.l_linenum = linenum; l.l_from = ecpyalloc(fields[LF_FROM]); l.l_to = ecpyalloc(fields[LF_TO]); - links = (struct link *) erealloc((char *) links, + links = (struct link *) (void *) erealloc((char *) links, (int) ((nlinks + 1) * sizeof *links)); links[nlinks++] = l; } @@ -1100,86 +1189,99 @@ const int nfields; static void rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep) register struct rule * const rp; -char * const loyearp; -char * const hiyearp; -char * const typep; -char * const monthp; -char * const dayp; -char * const timep; +const char * const loyearp; +const char * const hiyearp; +const char * const typep; +const char * const monthp; +const char * const dayp; +const char * const timep; { - register struct lookup const * lp; - register char * cp; + register const struct lookup * lp; + register const char * cp; + register char * dp; + 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; rp->r_todisstd = FALSE; - cp = timep; - if (*cp != '\0') { - cp += strlen(cp) - 1; - switch (lowerit(*cp)) { - case 's': + rp->r_todisgmt = FALSE; + dp = ecpyalloc(timep); + if (*dp != '\0') { + ep = dp + strlen(dp) - 1; + switch (lowerit(*ep)) { + case 's': /* Standard */ rp->r_todisstd = TRUE; - *cp = '\0'; + rp->r_todisgmt = FALSE; + *ep = '\0'; break; - case 'w': + case 'w': /* Wall */ rp->r_todisstd = FALSE; - *cp = '\0'; + rp->r_todisgmt = FALSE; + *ep = '\0'; + case 'g': /* Greenwich */ + case 'u': /* Universal */ + case 'z': /* Zulu */ + rp->r_todisstd = TRUE; + rp->r_todisgmt = TRUE; + *ep = '\0'; break; } } - rp->r_tod = gethms(timep, "invalid time of day", FALSE); + rp->r_tod = gethms(dp, _("invalid time of day"), FALSE); + ifree(dp); /* ** Year work. */ cp = loyearp; - if ((lp = byword(cp, begin_years)) != NULL) switch ((int) lp->l_value) { + lp = byword(cp, begin_years); + if (lp != NULL) switch ((int) lp->l_value) { case YR_MINIMUM: - rp->r_loyear = min_int; + rp->r_loyear = INT_MIN; break; case YR_MAXIMUM: - rp->r_loyear = max_int; + rp->r_loyear = INT_MAX; 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; if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) { case YR_MINIMUM: - rp->r_hiyear = min_int; + rp->r_hiyear = INT_MIN; break; case YR_MAXIMUM: - rp->r_hiyear = max_int; + rp->r_hiyear = INT_MAX; break; case YR_ONLY: rp->r_hiyear = rp->r_loyear; 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); @@ -1192,38 +1294,43 @@ char * const timep; ** Sun<=20 ** Sun>=7 */ - if ((lp = byword(dayp, lasts)) != NULL) { + dp = ecpyalloc(dayp); + if ((lp = byword(dp, lasts)) != NULL) { rp->r_dycode = DC_DOWLEQ; rp->r_wday = lp->l_value; rp->r_dayofmonth = len_months[1][rp->r_month]; } else { - if ((cp = strchr(dayp, '<')) != 0) + if ((ep = strchr(dp, '<')) != 0) rp->r_dycode = DC_DOWLEQ; - else if ((cp = strchr(dayp, '>')) != 0) + else if ((ep = strchr(dp, '>')) != 0) rp->r_dycode = DC_DOWGEQ; else { - cp = dayp; + ep = dp; rp->r_dycode = DC_DOM; } if (rp->r_dycode != DC_DOM) { - *cp++ = 0; - if (*cp++ != '=') { - error("invalid day of month"); + *ep++ = 0; + if (*ep++ != '=') { + error(_("invalid day of month")); + ifree(dp); return; } - if ((lp = byword(dayp, wday_names)) == NULL) { - error("invalid weekday name"); + if ((lp = byword(dp, wday_names)) == NULL) { + error(_("invalid weekday name")); + ifree(dp); return; } rp->r_wday = lp->l_value; } - if (sscanf(cp, scheck(cp, "%d"), &rp->r_dayofmonth) != 1 || + 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; } } + ifree(dp); } static void @@ -1246,9 +1353,19 @@ FILE * const fp; char buf[4]; convert(val, buf); - (void) fwrite((genericptr_t) buf, - (fwrite_size_t) sizeof buf, - (fwrite_size_t) 1, 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 @@ -1259,27 +1376,78 @@ 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, - strlen(directory) + 1 + strlen(name) + 1); + (int) (strlen(directory) + 1 + strlen(name) + 1)); (void) sprintf(fullname, "%s/%s", directory, name); 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); } } + convert(eitol(typecnt), tzh.tzh_ttisgmtcnt); convert(eitol(typecnt), tzh.tzh_ttisstdcnt); convert(eitol(leapcnt), tzh.tzh_leapcnt); convert(eitol(timecnt), tzh.tzh_timecnt); convert(eitol(typecnt), tzh.tzh_typecnt); convert(eitol(charcnt), tzh.tzh_charcnt); - (void) fwrite((genericptr_t) &tzh, - (fwrite_size_t) sizeof tzh, - (fwrite_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); + DO(tzh_leapcnt); + DO(tzh_timecnt); + DO(tzh_typecnt); + DO(tzh_charcnt); +#undef DO for (i = 0; i < timecnt; ++i) { j = leapcnt; while (--j >= 0) @@ -1290,18 +1458,16 @@ const char * const name; puttzcode((long) ats[i], fp); } if (timecnt > 0) - (void) fwrite((genericptr_t) types, - (fwrite_size_t) sizeof types[0], - (fwrite_size_t) timecnt, fp); + (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((genericptr_t) chars, - (fwrite_size_t) sizeof chars[0], - (fwrite_size_t) charcnt, fp); + (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]) { @@ -1323,14 +1489,35 @@ const char * const name; } 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)) { - (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); } } static void +doabbr(abbr, format, letters, isdst) +char * const abbr; +const char * const format; +const char * const letters; +const int isdst; +{ + if (strchr(format, '/') == NULL) { + if (letters == NULL) + (void) strcpy(abbr, format); + else (void) sprintf(abbr, format, letters); + } else if (isdst) + (void) strcpy(abbr, strchr(format, '/') + 1); + else { + (void) strcpy(abbr, format); + *strchr(abbr, '/') = '\0'; + } +} + +static void outzone(zpfirst, zonecount) const struct zone * const zpfirst; const int zonecount; @@ -1344,11 +1531,13 @@ const int zonecount; register long stdoff; register int year; register long startoff; - register int startisdst; register int startttisstd; + register int startttisgmt; register int type; char startbuf[BUFSIZ]; + INITIALIZE(untiltime); + INITIALIZE(starttime); /* ** Now. . .finally. . .generate some useful data! */ @@ -1364,9 +1553,7 @@ const int zonecount; ** for noting the need to unconditionally initialize startttisstd. */ startttisstd = FALSE; -#ifdef lint - starttime = 0; -#endif /* defined lint */ + startttisgmt = FALSE; for (i = 0; i < zonecount; ++i) { zp = &zpfirst[i]; usestart = i > 0 && (zp - 1)->z_untiltime > min_time; @@ -1375,14 +1562,19 @@ 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; - (void) strcpy(startbuf, zp->z_format); + doabbr(startbuf, zp->z_format, + (char *) NULL, stdoff != 0); type = addtype(oadd(zp->z_gmtoff, stdoff), - startbuf, stdoff != 0, startttisstd); - if (usestart) + startbuf, stdoff != 0, startttisstd, + startttisgmt); + if (usestart) { addtt(starttime, type); + usestart = FALSE; + } else if (stdoff != 0) addtt(min_time, type); } else for (year = min_year; year <= max_year; ++year) { @@ -1408,14 +1600,17 @@ const int zonecount; register long offset; char buf[BUFSIZ]; + INITIALIZE(ktime); if (useuntil) { /* ** Turn untiltime into GMT ** assuming the current gmtoff and ** stdoff values. */ - untiltime = tadd(zp->z_untiltime, - -gmtoff); + untiltime = zp->z_untiltime; + if (!zp->z_untilrule.r_todisgmt) + untiltime = tadd(untiltime, + -gmtoff); if (!zp->z_untilrule.r_todisstd) untiltime = tadd(untiltime, -stdoff); @@ -1425,16 +1620,13 @@ const int zonecount; ** that takes effect earliest in the year. */ k = -1; -#ifdef lint - ktime = 0; -#endif /* defined lint */ for (j = 0; j < zp->z_nrules; ++j) { rp = &zp->z_rules[j]; if (!rp->r_todo) continue; eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); - offset = gmtoff; + offset = rp->r_todisgmt ? 0 : gmtoff; if (!rp->r_todisstd) offset = oadd(offset, stdoff); jtime = rp->r_temp; @@ -1453,54 +1645,62 @@ 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); - (void) sprintf(startbuf, zp->z_format, - rp->r_abbrvar); - 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)); - } } eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); - (void) sprintf(buf, zp->z_format, - rp->r_abbrvar); + doabbr(buf, zp->z_format, rp->r_abbrvar, + rp->r_stdoff != 0); offset = oadd(zp->z_gmtoff, rp->r_stdoff); type = addtype(offset, buf, rp->r_stdoff != 0, - rp->r_todisstd); + 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 abbrevation 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); @@ -1511,28 +1711,37 @@ 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; } static int -addtype(gmtoff, abbr, isdst, ttisstd) +addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt) const long gmtoff; const char * const abbr; const int isdst; const int ttisstd; +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. @@ -1540,7 +1749,8 @@ const int ttisstd; for (i = 0; i < typecnt; ++i) { if (gmtoff == gmtoffs[i] && isdst == isdsts[i] && strcmp(abbr, &chars[abbrinds[i]]) == 0 && - ttisstd == ttisstds[i]) + ttisstd == ttisstds[i] && + ttisgmt == ttisgmts[i]) return i; } /* @@ -1548,12 +1758,13 @@ const int ttisstd; ** 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; isdsts[i] = isdst; ttisstds[i] = ttisstd; + ttisgmts[i] = ttisgmt; for (j = 0; j < charcnt; ++j) if (strcmp(&chars[j], abbr) == 0) @@ -1575,13 +1786,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; @@ -1600,7 +1811,7 @@ int count; } static void -adjleap() +adjleap P((void)) { register int i; register long last = 0; @@ -1624,19 +1835,15 @@ const char * const type; if (type == NULL || *type == '\0') return TRUE; - if (strcmp(type, "uspres") == 0) - return (year % 4) == 0; - if (strcmp(type, "nonpres") == 0) - return (year % 4) != 0; - buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type)); + buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type))); (void) sprintf(buf, "%s %d %s", yitcommand, year, type); result = system(buf); if (result == 0) 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); @@ -1644,8 +1851,9 @@ const char * const type; static int lowerit(a) -const int a; +int a; { + a = (unsigned char) a; return (isascii(a) && isupper(a)) ? tolower(a) : a; } @@ -1669,9 +1877,10 @@ register const char * word; return FALSE; ++word; while (*++abbr != '\0') - do if (*word == '\0') - return FALSE; - while (lowerit(*word++) != lowerit(*abbr)); + do { + if (*word == '\0') + return FALSE; + } while (lowerit(*word++) != lowerit(*abbr)); return TRUE; } @@ -1713,10 +1922,11 @@ register char * cp; if (cp == NULL) return NULL; - array = (char **) emalloc((int) ((strlen(cp) + 1) * sizeof *array)); + array = (char **) (void *) + emalloc((int) ((strlen(cp) + 1) * sizeof *array)); nsubs = 0; for ( ; ; ) { - while (isascii(*cp) && isspace(*cp)) + while (isascii(*cp) && isspace((unsigned char) *cp)) ++cp; if (*cp == '\0' || *cp == '#') break; @@ -1727,10 +1937,10 @@ 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(*cp))); - if (isascii(*cp) && isspace(*cp)) + (!isascii(*cp) || !isspace((unsigned char) *cp))); + if (isascii(*cp) && isspace((unsigned char) *cp)) ++cp; *dp = '\0'; } @@ -1747,7 +1957,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; @@ -1766,7 +1976,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; @@ -1786,9 +1996,9 @@ register const int wantedy; register long dayoff; /* with a nod to Margaret O. */ register time_t t; - if (wantedy == min_int) + if (wantedy == INT_MIN) return min_time; - if (wantedy == max_int) + if (wantedy == INT_MAX) return max_time; dayoff = 0; m = TM_JANUARY; @@ -1813,7 +2023,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); } } @@ -1847,11 +2057,11 @@ 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); } } - if (dayoff < 0 && !tt_signed) + if (dayoff < 0 && !TYPE_SIGNED(time_t)) return min_time; t = (time_t) dayoff * SECSPERDAY; /* @@ -1870,7 +2080,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); @@ -1891,10 +2101,10 @@ char * const argname; *cp = '\0'; #ifndef unix /* - ** MS-DOS drive specifier? + ** DOS drive specifier? */ - if (strlen(name) == 2 && isascii(name[0]) && - isalpha(name[0]) && name[1] == ':') { + if (isalpha((unsigned char) name[0]) && + name[1] == ':' && name[2] == '\0') { *cp = '/'; continue; } @@ -1903,11 +2113,11 @@ char * const argname; /* ** It doesn't seem to exist, so we try to create it. */ - if (emkdir(name, 0755) != 0) { + 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; } @@ -1927,7 +2137,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); } @@ -1935,5 +2145,5 @@ const int i; } /* -** UNIX is a registered trademark of AT&T. +** UNIX was a registered trademark of UNIX System Laboratories in 1993. */ -- cgit v1.1