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.
This commit is contained in:
Joseph Myers 2018-12-10 13:11:58 +00:00
parent b93f4052fc
commit 0afcb29d50
6 changed files with 609 additions and 339 deletions

View File

@ -1,3 +1,11 @@
2018-12-10 Joseph Myers <joseph@codesourcery.com>
* timezone/private.h: Update from tzcode 2018g.
* timezone/tzfile.h: Likewise.
* timezone/tzselect.ksh: Likewise.
* timezone/zdump.c: Likewise.
* timezone/zic.c: Likewise.
2018-12-08 Paul Pluzhnikov <ppluzhnikov@google.com>
[BZ #23490]

View File

@ -1,3 +1,5 @@
/* Private header for tzdb code. */
#ifndef PRIVATE_H
#define PRIVATE_H
@ -15,6 +17,16 @@
** Thank you!
*/
/*
** zdump has been made independent of the rest of the time
** conversion package to increase confidence in the verification it provides.
** You can use zdump to help in verifying other implementations.
** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
*/
#ifndef USE_LTZ
# define USE_LTZ 1
#endif
/* This string was in the Factory zone through version 2016f. */
#define GRANDPARENTED "Local time zone must be set--see zic manual page"
@ -27,13 +39,28 @@
#define HAVE_DECL_ASCTIME_R 1
#endif
#if !defined HAVE_GENERIC && defined __has_extension
# if __has_extension(c_generic_selections)
# define HAVE_GENERIC 1
# else
# define HAVE_GENERIC 0
# endif
#endif
/* _Generic is buggy in pre-4.9 GCC. */
#if !defined HAVE_GENERIC && defined __GNUC__
# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
#endif
#ifndef HAVE_GENERIC
# define HAVE_GENERIC (201112 <= __STDC_VERSION__)
#endif
#ifndef HAVE_GETTEXT
#define HAVE_GETTEXT 0
#endif /* !defined HAVE_GETTEXT */
#ifndef HAVE_INCOMPATIBLE_CTIME_R
#define HAVE_INCOMPATIBLE_CTIME_R 0
#endif /* !defined INCOMPATIBLE_CTIME_R */
#endif
#ifndef HAVE_LINK
#define HAVE_LINK 1
@ -43,10 +70,18 @@
#define HAVE_POSIX_DECLS 1
#endif
#ifndef HAVE_STDBOOL_H
#define HAVE_STDBOOL_H (199901 <= __STDC_VERSION__)
#endif
#ifndef HAVE_STRDUP
#define HAVE_STRDUP 1
#endif
#ifndef HAVE_STRTOLL
#define HAVE_STRTOLL 1
#endif
#ifndef HAVE_SYMLINK
#define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
@ -76,13 +111,23 @@
#define ctime_r _incompatible_ctime_r
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
/* Enable tm_gmtoff and tm_zone on GNUish systems. */
/* Enable tm_gmtoff, tm_zone, and environ on GNUish systems. */
#define _GNU_SOURCE 1
/* Fix asctime_r on Solaris 11. */
#define _POSIX_PTHREAD_SEMANTICS 1
/* Enable strtoimax on pre-C99 Solaris 11. */
#define __EXTENSIONS__ 1
/* To avoid having 'stat' fail unnecessarily with errno == EOVERFLOW,
enable large files on GNUish systems ... */
#ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
#endif
/* ... and on AIX ... */
#define _LARGE_FILES 1
/* ... and enable large inode numbers on Mac OS X 10.5 and later. */
#define _DARWIN_USE_64_BIT_INODE 1
/*
** Nested includes
*/
@ -105,7 +150,6 @@
#undef tzfree
#include <sys/types.h> /* for time_t */
#include <stdio.h>
#include <string.h>
#include <limits.h> /* for CHAR_BIT et al. */
#include <stdlib.h>
@ -126,19 +170,8 @@
#include <libintl.h>
#endif /* HAVE_GETTEXT */
#if HAVE_SYS_WAIT_H
#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
#endif /* HAVE_SYS_WAIT_H */
#ifndef WIFEXITED
#define WIFEXITED(status) (((status) & 0xff) == 0)
#endif /* !defined WIFEXITED */
#ifndef WEXITSTATUS
#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
#endif /* !defined WEXITSTATUS */
#if HAVE_UNISTD_H
#include <unistd.h> /* for F_OK, R_OK, and other POSIX goodness */
#include <unistd.h> /* for R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */
#ifndef HAVE_STRFTIME_L
@ -149,9 +182,22 @@
# endif
#endif
#ifndef F_OK
#define F_OK 0
#endif /* !defined F_OK */
#ifndef USG_COMPAT
# ifndef _XOPEN_VERSION
# define USG_COMPAT 0
# else
# define USG_COMPAT 1
# endif
#endif
#ifndef HAVE_TZNAME
# if _POSIX_VERSION < 198808 && !USG_COMPAT
# define HAVE_TZNAME 0
# else
# define HAVE_TZNAME 1
# endif
#endif
#ifndef R_OK
#define R_OK 4
#endif /* !defined R_OK */
@ -236,15 +282,19 @@ typedef int int_fast32_t;
#ifndef INTMAX_MAX
# ifdef LLONG_MAX
typedef long long intmax_t;
# define strtoimax strtoll
# if HAVE_STRTOLL
# define strtoimax strtoll
# endif
# define INTMAX_MAX LLONG_MAX
# define INTMAX_MIN LLONG_MIN
# else
typedef long intmax_t;
# define strtoimax strtol
# define INTMAX_MAX LONG_MAX
# define INTMAX_MIN LONG_MIN
# endif
# ifndef strtoimax
# define strtoimax strtol
# endif
#endif
#ifndef PRIdMAX
@ -294,12 +344,14 @@ typedef unsigned long uintmax_t;
#define SIZE_MAX ((size_t) -1)
#endif
#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
#if 3 <= __GNUC__
# define ATTRIBUTE_CONST __attribute__ ((const))
# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
#else
# define ATTRIBUTE_CONST /* empty */
# define ATTRIBUTE_MALLOC /* empty */
# define ATTRIBUTE_PURE /* empty */
# define ATTRIBUTE_FORMAT(spec) /* empty */
#endif
@ -326,6 +378,16 @@ typedef unsigned long uintmax_t;
#ifndef EPOCH_OFFSET
# define EPOCH_OFFSET 0
#endif
#ifndef RESERVE_STD_EXT_IDS
# define RESERVE_STD_EXT_IDS 0
#endif
/* If standard C identifiers with external linkage (e.g., localtime)
are reserved and are not already being renamed anyway, rename them
as if compiling with '-Dtime_tz=time_t'. */
#if !defined time_tz && RESERVE_STD_EXT_IDS && USE_LTZ
# define time_tz time_t
#endif
/*
** Compile with -Dtime_tz=T to build the tz package with a private
@ -335,6 +397,12 @@ typedef unsigned long uintmax_t;
** typical platforms.
*/
#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
# define TZ_TIME_T 1
#else
# define TZ_TIME_T 0
#endif
#if TZ_TIME_T
# ifdef LOCALTIME_IMPLEMENTATION
static time_t sys_time(time_t *x) { return time(x); }
# endif
@ -367,6 +435,8 @@ typedef time_tz tz_time_t;
# define posix2time tz_posix2time
# undef posix2time_z
# define posix2time_z tz_posix2time_z
# undef strftime
# define strftime tz_strftime
# undef time
# define time tz_time
# undef time2posix
@ -389,10 +459,34 @@ typedef time_tz tz_time_t;
# define tzset tz_tzset
# undef tzsetwall
# define tzsetwall tz_tzsetwall
# if HAVE_STRFTIME_L
# undef strftime_l
# define strftime_l tz_strftime_l
# endif
# if HAVE_TZNAME
# undef tzname
# define tzname tz_tzname
# endif
# if USG_COMPAT
# undef daylight
# define daylight tz_daylight
# undef timezone
# define timezone tz_timezone
# endif
# ifdef ALTZONE
# undef altzone
# define altzone tz_altzone
# endif
char *ctime(time_t const *);
char *ctime_r(time_t const *, char *);
double difftime(time_t, time_t);
double difftime(time_t, time_t) ATTRIBUTE_CONST;
size_t strftime(char *restrict, size_t, char const *restrict,
struct tm const *restrict);
# if HAVE_STRFTIME_L
size_t strftime_l(char *restrict, size_t, char const *restrict,
struct tm const *restrict, locale_t);
# endif
struct tm *gmtime(time_t const *);
struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
struct tm *localtime(time_t const *);
@ -406,18 +500,29 @@ void tzset(void);
extern char *asctime_r(struct tm const *restrict, char *restrict);
#endif
#if !HAVE_POSIX_DECLS
# ifdef USG_COMPAT
# ifndef timezone
extern long timezone;
# endif
# ifndef daylight
extern int daylight;
# endif
#ifndef HAVE_DECL_ENVIRON
# if defined environ || defined __USE_GNU
# define HAVE_DECL_ENVIRON 1
# else
# define HAVE_DECL_ENVIRON 0
# endif
#endif
#if defined ALTZONE && !defined altzone
#if !HAVE_DECL_ENVIRON
extern char **environ;
#endif
#if TZ_TIME_T || !HAVE_POSIX_DECLS
# if HAVE_TZNAME
extern char *tzname[];
# endif
# if USG_COMPAT
extern long timezone;
extern int daylight;
# endif
#endif
#ifdef ALTZONE
extern long altzone;
#endif
@ -427,25 +532,25 @@ extern long altzone;
*/
#ifdef STD_INSPIRED
# if !defined tzsetwall || defined time_tz
# if TZ_TIME_T || !defined tzsetwall
void tzsetwall(void);
# endif
# if !defined offtime || defined time_tz
# if TZ_TIME_T || !defined offtime
struct tm *offtime(time_t const *, long);
# endif
# if !defined timegm || defined time_tz
# if TZ_TIME_T || !defined timegm
time_t timegm(struct tm *);
# endif
# if !defined timelocal || defined time_tz
# if TZ_TIME_T || !defined timelocal
time_t timelocal(struct tm *);
# endif
# if !defined timeoff || defined time_tz
# if TZ_TIME_T || !defined timeoff
time_t timeoff(struct tm *, long);
# endif
# if !defined time2posix || defined time_tz
# if TZ_TIME_T || !defined time2posix
time_t time2posix(time_t);
# endif
# if !defined posix2time || defined time_tz
# if TZ_TIME_T || !defined posix2time
time_t posix2time(time_t);
# endif
#endif
@ -479,10 +584,10 @@ time_t mktime_z(timezone_t restrict, struct tm *restrict);
timezone_t tzalloc(char const *);
void tzfree(timezone_t);
# ifdef STD_INSPIRED
# if !defined posix2time_z || defined time_tz
# if TZ_TIME_T || !defined posix2time_z
time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE;
# endif
# if !defined time2posix_z || defined time_tz
# if TZ_TIME_T || !defined time2posix_z
time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
# endif
# endif
@ -492,12 +597,12 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
** Finally, some convenience items.
*/
#if __STDC_VERSION__ < 199901
#if HAVE_STDBOOL_H
# include <stdbool.h>
#else
# define true 1
# define false 0
# define bool int
#else
# include <stdbool.h>
#endif
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
@ -513,27 +618,32 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
#define MINVAL(t, b) \
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
/* The minimum and maximum finite time values. This implementation
assumes no padding if time_t is signed and either the compiler is
pre-C11 or time_t is not one of the standard signed integer types. */
#if 201112 <= __STDC_VERSION__
static time_t const time_t_min
= (TYPE_SIGNED(time_t)
? _Generic((time_t) 0,
signed char: SCHAR_MIN, short: SHRT_MIN,
int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN,
default: MINVAL(time_t, TYPE_BIT(time_t)))
: 0);
static time_t const time_t_max
= (TYPE_SIGNED(time_t)
? _Generic((time_t) 0,
signed char: SCHAR_MAX, short: SHRT_MAX,
int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX,
default: MAXVAL(time_t, TYPE_BIT(time_t)))
: -1);
/* The extreme time values, assuming no padding. */
#define TIME_T_MIN_NO_PADDING MINVAL(time_t, TYPE_BIT(time_t))
#define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t))
/* The extreme time values. These are macros, not constants, so that
any portability problem occur only when compiling .c files that use
the macros, which is safer for applications that need only zdump and zic.
This implementation assumes no padding if time_t is signed and
either the compiler lacks support for _Generic or time_t is not one
of the standard signed integer types. */
#if HAVE_GENERIC
# define TIME_T_MIN \
_Generic((time_t) 0, \
signed char: SCHAR_MIN, short: SHRT_MIN, \
int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, \
default: TIME_T_MIN_NO_PADDING)
# define TIME_T_MAX \
(TYPE_SIGNED(time_t) \
? _Generic((time_t) 0, \
signed char: SCHAR_MAX, short: SHRT_MAX, \
int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, \
default: TIME_T_MAX_NO_PADDING) \
: (time_t) -1)
#else
static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t));
static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
# define TIME_T_MIN TIME_T_MIN_NO_PADDING
# define TIME_T_MAX TIME_T_MAX_NO_PADDING
#endif
/*
@ -550,7 +660,7 @@ static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
** INITIALIZE(x)
*/
#ifdef lint
#ifdef GCC_LINT
# define INITIALIZE(x) ((x) = 0)
#else
# define INITIALIZE(x)
@ -633,7 +743,7 @@ char *ctime_r(time_t const *, char *);
** or
** isleap(a + b) == isleap(a % 400 + b % 400)
** This is true even if % means modulo rather than Fortran remainder
** (which is allowed by C89 but not C99).
** (which is allowed by C89 but not by C99 or later).
** We use this to avoid addition overflow problems.
*/

View File

@ -1,3 +1,5 @@
/* Layout and location of TZif files. */
#ifndef TZFILE_H
#define TZFILE_H
@ -20,11 +22,11 @@
*/
#ifndef TZDIR
#define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */
#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
#endif /* !defined TZDIR */
#ifndef TZDEFAULT
#define TZDEFAULT "localtime"
#define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES

View File

@ -1,12 +1,11 @@
#!/bin/bash
# Ask the user about the time zone, and output the resulting TZ value to stdout.
# Interact with the user via stderr and stdin.
PKGVERSION='(tzcode) '
TZVERSION=see_Makefile
REPORT_BUGS_TO=tz@iana.org
# Ask the user about the time zone, and output the resulting TZ value to stdout.
# Interact with the user via stderr and stdin.
# Contributed by Paul Eggert. This file is in the public domain.
# Porting notes:
@ -17,9 +16,9 @@ REPORT_BUGS_TO=tz@iana.org
# If your host lacks both Bash and the Korn shell, you can get their
# source from one of these locations:
#
# Bash <http://www.gnu.org/software/bash/bash.html>
# Bash <https://www.gnu.org/software/bash/>
# Korn Shell <http://www.kornshell.com/>
# Public Domain Korn Shell <http://www.cs.mun.ca/~michael/pdksh/>
# MirBSD Korn Shell <https://www.mirbsd.org/mksh.htm>
#
# For portability to Solaris 9 /bin/sh this script avoids some POSIX
# features and common extensions, such as $(...) (which works sometimes
@ -29,8 +28,8 @@ REPORT_BUGS_TO=tz@iana.org
# If your host lacks awk, or has an old awk that does not conform to Posix,
# you can use either of the following free programs instead:
#
# Gawk (GNU awk) <http://www.gnu.org/software/gawk/>
# mawk <http://invisible-island.net/mawk/>
# Gawk (GNU awk) <https://www.gnu.org/software/gawk/>
# mawk <https://invisible-island.net/mawk/>
# Specify default values for environment variables if they are unset.
@ -55,7 +54,7 @@ location_limit=10
zonetabtype=zone1970
usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT]
Select a time zone interactively.
Select a timezone interactively.
Options:
@ -327,7 +326,7 @@ while
eval '
doselect '"$quoted_continents"' \
"coord - I want to use geographical coordinates." \
"TZ - I want to specify the time zone using the Posix TZ format."
"TZ - I want to specify the timezone using the Posix TZ format."
continent=$select_result
case $continent in
Americas) continent=America;;
@ -342,8 +341,10 @@ while
while
echo >&2 'Please enter the desired value' \
'of the TZ environment variable.'
echo >&2 'For example, GST-10 is a zone named GST' \
'that is 10 hours ahead (east) of UTC.'
echo >&2 'For example, AEST-10 is abbreviated' \
'AEST and is 10 hours'
echo >&2 'ahead (east) of Greenwich,' \
'with no daylight saving time.'
read TZ
$AWK -v TZ="$TZ" 'BEGIN {
tzname = "(<[[:alnum:]+-]{3,}>|[[:alpha:]]{3,})"
@ -360,7 +361,7 @@ while
exit 0
}'
do
say >&2 "'$TZ' is not a conforming Posix time zone string."
say >&2 "'$TZ' is not a conforming Posix timezone string."
done
TZ_for_date=$TZ;;
*)
@ -386,8 +387,7 @@ while
BEGIN { FS = "\t" }
{ print $NF }
'`
echo >&2 'Please select one of the following' \
'time zone regions,'
echo >&2 'Please select one of the following timezones,' \
echo >&2 'listed roughly in increasing order' \
"of distance from $coord".
doselect $regions
@ -437,7 +437,7 @@ while
esac
# Get list of names of time zone rule regions in the country.
# Get list of timezones in the country.
regions=`$AWK \
-v country="$country" \
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
@ -460,8 +460,7 @@ while
# If there's more than one region, ask the user which one.
case $regions in
*"$newline"*)
echo >&2 'Please select one of the following' \
'time zone regions.'
echo >&2 'Please select one of the following timezones.'
doselect $regions
region=$select_result;;
*)

View File

@ -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);

File diff suppressed because it is too large Load Diff