aboutsummaryrefslogtreecommitdiff
path: root/timezone/zdump.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2018-12-10 13:11:58 +0000
committerJoseph Myers <joseph@codesourcery.com>2018-12-10 13:11:58 +0000
commit0afcb29d50312409f0b698001d1ee2b535d06a3c (patch)
tree810bf1bbcabd4ad6cc535fb15de39c22b7aeac2e /timezone/zdump.c
parentb93f4052fc171f456c8f594d4ae4aeb02ec5b3b6 (diff)
downloadglibc-0afcb29d50312409f0b698001d1ee2b535d06a3c.tar
glibc-0afcb29d50312409f0b698001d1ee2b535d06a3c.tar.gz
glibc-0afcb29d50312409f0b698001d1ee2b535d06a3c.tar.bz2
glibc-0afcb29d50312409f0b698001d1ee2b535d06a3c.zip
Update timezone code from tzcode 2018g.
This patch updates files coming from tzcode to the versions in tzcode 2018g. No changes elsewhere in glibc were needed. Tested for x86_64. * timezone/private.h: Update from tzcode 2018g. * timezone/tzfile.h: Likewise. * timezone/tzselect.ksh: Likewise. * timezone/zdump.c: Likewise. * timezone/zic.c: Likewise.
Diffstat (limited to 'timezone/zdump.c')
-rw-r--r--timezone/zdump.c131
1 files changed, 84 insertions, 47 deletions
diff --git a/timezone/zdump.c b/timezone/zdump.c
index bf75800101..608f288691 100644
--- a/timezone/zdump.c
+++ b/timezone/zdump.c
@@ -1,3 +1,5 @@
+/* Dump time zone data in a textual format. */
+
/*
** This file is in the public domain, so clarified as of
** 2009-05-17 by Arthur David Olson.
@@ -5,21 +7,16 @@
#include "version.h"
-/*
-** This code has been made independent of the rest of the time
-** conversion package to increase confidence in the verification it provides.
-** You can use this code to help in verifying other implementations.
-** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
-*/
-
#ifndef NETBSD_INSPIRED
# define NETBSD_INSPIRED 1
#endif
-#ifndef USE_LTZ
-# define USE_LTZ 1
-#endif
#include "private.h"
+#include <stdio.h>
+
+#ifndef HAVE_SNPRINTF
+# define HAVE_SNPRINTF (199901 <= __STDC_VERSION__)
+#endif
#ifndef HAVE_LOCALTIME_R
# define HAVE_LOCALTIME_R 1
@@ -72,14 +69,11 @@ enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 };
# define timezone_t char **
#endif
-extern char ** environ;
-
#if !HAVE_POSIX_DECLS
extern int getopt(int argc, char * const argv[],
const char * options);
extern char * optarg;
extern int optind;
-extern char * tzname[];
#endif
/* The minimum and maximum finite time values. */
@@ -144,7 +138,7 @@ sumsize(size_t a, size_t b)
/* Return a pointer to a newly allocated buffer of size SIZE, exiting
on failure. SIZE should be nonzero. */
-static void *
+static void * ATTRIBUTE_MALLOC
xmalloc(size_t size)
{
void *p = malloc(size);
@@ -263,7 +257,7 @@ tzfree(timezone_t env)
}
#endif /* ! USE_LOCALTIME_RZ */
-/* A UTC time zone, and its initializer. */
+/* A UT time zone, and its initializer. */
static timezone_t gmtz;
static void
gmtzinit(void)
@@ -278,7 +272,7 @@ gmtzinit(void)
}
}
-/* Convert *TP to UTC, storing the broken-down time into *TMP.
+/* Convert *TP to UT, storing the broken-down time into *TMP.
Return TMP if successful, NULL otherwise. This is like gmtime_r(TP, TMP),
except typically faster if USE_LOCALTIME_RZ. */
static struct tm *
@@ -390,7 +384,7 @@ static void
usage(FILE * const stream, const int status)
{
fprintf(stream,
-_("%s: usage: %s OPTIONS ZONENAME ...\n"
+_("%s: usage: %s OPTIONS TIMEZONE ...\n"
"Options include:\n"
" -c [L,]U Start at year L (default -500), end before year U (default 2500)\n"
" -t [L,]U Start at time L, end before time U (in seconds since 1970)\n"
@@ -550,6 +544,7 @@ main(int argc, char *argv[])
}
if (t < cutlotime)
t = cutlotime;
+ INITIALIZE (ab);
tm_ok = my_localtime_rz(tz, &t, &tm) != NULL;
if (tm_ok) {
ab = saveabbr(&abbrev, &abbrevsize, &tm);
@@ -565,11 +560,10 @@ main(int argc, char *argv[])
: cuthitime);
struct tm *newtmp = localtime_rz(tz, &newt, &newtm);
bool newtm_ok = newtmp != NULL;
- if (! (tm_ok & newtm_ok
- ? (delta(&newtm, &tm) == newt - t
- && newtm.tm_isdst == tm.tm_isdst
- && strcmp(abbr(&newtm), ab) == 0)
- : tm_ok == newtm_ok)) {
+ if (tm_ok != newtm_ok
+ || (tm_ok && (delta(&newtm, &tm) != newt - t
+ || newtm.tm_isdst != tm.tm_isdst
+ || strcmp(abbr(&newtm), ab) != 0))) {
newt = hunt(tz, argv[i], t, newt);
newtmp = localtime_rz(tz, &newt, &newtm);
newtm_ok = newtmp != NULL;
@@ -685,17 +679,15 @@ hunt(timezone_t tz, char *name, time_t lot, time_t hit)
}
/*
-** Thanks to Paul Eggert for logic used in delta.
+** Thanks to Paul Eggert for logic used in delta_nonneg.
*/
static intmax_t
-delta(struct tm * newp, struct tm *oldp)
+delta_nonneg(struct tm *newp, struct tm *oldp)
{
register intmax_t result;
register int tmy;
- if (newp->tm_year < oldp->tm_year)
- return -delta(oldp, newp);
result = 0;
for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE);
@@ -709,6 +701,14 @@ delta(struct tm * newp, struct tm *oldp)
return result;
}
+static intmax_t
+delta(struct tm *newp, struct tm *oldp)
+{
+ return (newp->tm_year < oldp->tm_year
+ ? -delta_nonneg(oldp, newp)
+ : delta_nonneg(newp, oldp));
+}
+
#ifndef TM_GMTOFF
/* Return A->tm_yday, adjusted to compare it fairly to B->tm_yday.
Assume A and B differ by at most one year. */
@@ -722,8 +722,8 @@ adjusted_yday(struct tm const *a, struct tm const *b)
}
#endif
-/* If A is the broken-down local time and B the broken-down UTC for
- the same instant, return A's UTC offset in seconds, where positive
+/* If A is the broken-down local time and B the broken-down UT for
+ the same instant, return A's UT offset in seconds, where positive
offsets are east of Greenwich. On failure, return LONG_MIN.
If T is nonnull, *T is the timestamp that corresponds to A; call
@@ -787,6 +787,40 @@ show(timezone_t tz, char *zone, time_t t, bool v)
abbrok(abbr(tmp), zone);
}
+#if HAVE_SNPRINTF
+# define my_snprintf snprintf
+#else
+# include <stdarg.h>
+
+/* A substitute for snprintf that is good enough for zdump. */
+static int ATTRIBUTE_FORMAT((printf, 3, 4))
+my_snprintf(char *s, size_t size, char const *format, ...)
+{
+ int n;
+ va_list args;
+ char const *arg;
+ size_t arglen, slen;
+ char buf[1024];
+ va_start(args, format);
+ if (strcmp(format, "%s") == 0) {
+ arg = va_arg(args, char const *);
+ arglen = strlen(arg);
+ } else {
+ n = vsprintf(buf, format, args);
+ if (n < 0)
+ return n;
+ arg = buf;
+ arglen = n;
+ }
+ slen = arglen < size ? arglen : size - 1;
+ memcpy(s, arg, slen);
+ s[slen] = '\0';
+ n = arglen <= INT_MAX ? arglen : -1;
+ va_end(args);
+ return n;
+}
+#endif
+
/* Store into BUF, of size SIZE, a formatted local time taken from *TM.
Use ISO 8601 format +HH:MM:SS. Omit :SS if SS is zero, and omit
:MM too if MM is also zero.
@@ -799,16 +833,16 @@ format_local_time(char *buf, size_t size, struct tm const *tm)
{
int ss = tm->tm_sec, mm = tm->tm_min, hh = tm->tm_hour;
return (ss
- ? snprintf(buf, size, "%02d:%02d:%02d", hh, mm, ss)
+ ? my_snprintf(buf, size, "%02d:%02d:%02d", hh, mm, ss)
: mm
- ? snprintf(buf, size, "%02d:%02d", hh, mm)
- : snprintf(buf, size, "%02d", hh));
+ ? my_snprintf(buf, size, "%02d:%02d", hh, mm)
+ : my_snprintf(buf, size, "%02d", hh));
}
-/* Store into BUF, of size SIZE, a formatted UTC offset for the
+/* Store into BUF, of size SIZE, a formatted UT offset for the
localtime *TM corresponding to time T. Use ISO 8601 format
+HHMMSS, or -HHMMSS for timestamps west of Greenwich; use the
- format -00 for unknown UTC offsets. If the hour needs more than
+ format -00 for unknown UT offsets. If the hour needs more than
two digits to represent, extend the length of HH as needed.
Otherwise, omit SS if SS is zero, and omit MM too if MM is also
zero.
@@ -837,10 +871,10 @@ format_utc_offset(char *buf, size_t size, struct tm const *tm, time_t t)
mm = off / 60 % 60;
hh = off / 60 / 60;
return (ss || 100 <= hh
- ? snprintf(buf, size, "%c%02ld%02d%02d", sign, hh, mm, ss)
+ ? my_snprintf(buf, size, "%c%02ld%02d%02d", sign, hh, mm, ss)
: mm
- ? snprintf(buf, size, "%c%02ld%02d", sign, hh, mm)
- : snprintf(buf, size, "%c%02ld", sign, hh));
+ ? my_snprintf(buf, size, "%c%02ld%02d", sign, hh, mm)
+ : my_snprintf(buf, size, "%c%02ld", sign, hh));
}
/* Store into BUF (of size SIZE) a quoted string representation of P.
@@ -883,7 +917,7 @@ format_quoted_string(char *buf, size_t size, char const *p)
%f zone name
%L local time as per format_local_time
- %Q like "U\t%Z\tD" where U is the UTC offset as for format_utc_offset
+ %Q like "U\t%Z\tD" where U is the UT offset as for format_utc_offset
and D is the isdst flag; except omit D if it is zero, omit %Z if
it equals U, quote and escape %Z if it contains nonalphabetics,
and omit any trailing tabs. */
@@ -943,15 +977,16 @@ istrftime(char *buf, size_t size, char const *time_fmt,
for (abp = ab; is_alpha(*abp); abp++)
continue;
len = (!*abp && *ab
- ? snprintf(b, s, "%s", ab)
+ ? my_snprintf(b, s, "%s", ab)
: format_quoted_string(b, s, ab));
if (s <= len)
return false;
b += len, s -= len;
}
- formatted_len = (tm->tm_isdst
- ? snprintf(b, s, &"\t\t%d"[show_abbr], tm->tm_isdst)
- : 0);
+ formatted_len
+ = (tm->tm_isdst
+ ? my_snprintf(b, s, &"\t\t%d"[show_abbr], tm->tm_isdst)
+ : 0);
}
break;
}
@@ -993,9 +1028,11 @@ abbr(struct tm const *tmp)
#ifdef TM_ZONE
return tmp->TM_ZONE;
#else
- return (0 <= tmp->tm_isdst && tzname[0 < tmp->tm_isdst]
- ? tzname[0 < tmp->tm_isdst]
- : "");
+# if HAVE_TZNAME
+ if (0 <= tmp->tm_isdst && tzname[0 < tmp->tm_isdst])
+ return tzname[0 < tmp->tm_isdst];
+# endif
+ return "";
#endif
}
@@ -1030,10 +1067,10 @@ tformat(void)
static void
dumptime(register const struct tm *timeptr)
{
- static const char wday_name[][3] = {
+ static const char wday_name[][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
- static const char mon_name[][3] = {
+ static const char mon_name[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
@@ -1059,7 +1096,7 @@ dumptime(register const struct tm *timeptr)
(int) (sizeof mon_name / sizeof mon_name[0]))
mn = "???";
else mn = mon_name[timeptr->tm_mon];
- printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
+ printf("%s %s%3d %.2d:%.2d:%.2d ",
wn, mn,
timeptr->tm_mday, timeptr->tm_hour,
timeptr->tm_min, timeptr->tm_sec);