mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-27 03:33:33 +08:00
Update timezone code from tzcode 2015g.
This patch updates the timezone code from tzcode 2015g. The Makefile and README changes are based on those in Paul's patch <https://sourceware.org/ml/libc-alpha/2015-05/msg00553.html>. Tested for x86_64 and x86. 2016-01-06 Paul Eggert <eggert@cs.ucla.edu> Joseph Myers <joseph@codesourcery.com> * timezone/private.h: Update from tzcode 2015g. * timezone/tzfile.h: Likewise. * timezone/tzselect.ksh: Likewise. * timezone/zdump.c: Likewise. * timezone/zic.c: Likewise. * timezone/ialloc.c: Remove file. * timezone/scheck.c: Likewise. * timezone/Makefile (extra-objs): Remove variable. ($(objpfx)zic): Do not depend on scheck.o and ialloc.o. (tz-cflags): Add -DHAVE_GETTEXT -DUSE_LTZ=0 -Wno-maybe-uninitialized. (CFLAGS-zdump.c): Remove -fwrapv -DNOID -DHAVE_GETTEXT. (CFLAGS-zic.c): Remove -DNOID -DHAVE_GETTEXT. (CFLAGS-ialloc.c): Remove variable. (CFLAGS-scheck.c): Likewise. * timezone/README: Update list of files from tzcode.
This commit is contained in:
parent
45c4f3665a
commit
670a687dea
20
ChangeLog
20
ChangeLog
@ -1,3 +1,23 @@
|
||||
2016-01-06 Paul Eggert <eggert@cs.ucla.edu>
|
||||
Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* timezone/private.h: Update from tzcode 2015g.
|
||||
* timezone/tzfile.h: Likewise.
|
||||
* timezone/tzselect.ksh: Likewise.
|
||||
* timezone/zdump.c: Likewise.
|
||||
* timezone/zic.c: Likewise.
|
||||
* timezone/ialloc.c: Remove file.
|
||||
* timezone/scheck.c: Likewise.
|
||||
* timezone/Makefile (extra-objs): Remove variable.
|
||||
($(objpfx)zic): Do not depend on scheck.o and ialloc.o.
|
||||
(tz-cflags): Add -DHAVE_GETTEXT -DUSE_LTZ=0
|
||||
-Wno-maybe-uninitialized.
|
||||
(CFLAGS-zdump.c): Remove -fwrapv -DNOID -DHAVE_GETTEXT.
|
||||
(CFLAGS-zic.c): Remove -DNOID -DHAVE_GETTEXT.
|
||||
(CFLAGS-ialloc.c): Remove variable.
|
||||
(CFLAGS-scheck.c): Likewise.
|
||||
* timezone/README: Update list of files from tzcode.
|
||||
|
||||
2016-01-07 Khem Raj <raj.khem@gmail.com>
|
||||
|
||||
* argp/argp-fmtstream.c (__argp_fmtstream_free): Use fwrite_unlocked
|
||||
|
@ -22,8 +22,6 @@ subdir := timezone
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
extra-objs := scheck.o ialloc.o
|
||||
|
||||
others := zdump zic
|
||||
tests := test-tz tst-timezone tst-tzset
|
||||
|
||||
@ -49,8 +47,6 @@ endif
|
||||
include ../Rules
|
||||
|
||||
|
||||
$(objpfx)zic: $(objpfx)scheck.o $(objpfx)ialloc.o
|
||||
|
||||
$(objpfx)zic.o $(objpfx)zdump.o: $(objpfx)version.h
|
||||
|
||||
$(objpfx)version.h: $(common-objpfx)config.make
|
||||
@ -61,15 +57,14 @@ $(objpfx)version.h: $(common-objpfx)config.make
|
||||
tz-cflags = -DTZDIR='"$(zonedir)"' \
|
||||
-DTZDEFAULT='"$(localtime-file)"' \
|
||||
-DTZDEFRULES='"$(posixrules-file)"' \
|
||||
-DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone
|
||||
-DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone \
|
||||
-DHAVE_GETTEXT -DUSE_LTZ=0 -Wno-maybe-uninitialized
|
||||
|
||||
# The -Wno-unused-variable flag is used to prevent GCC 6
|
||||
# from warning about time_t_min and time_t_max which are
|
||||
# defined in private.h but not used.
|
||||
CFLAGS-zdump.c = -fwrapv -DNOID $(tz-cflags) -DHAVE_GETTEXT
|
||||
CFLAGS-zic.c = -DNOID $(tz-cflags) -DHAVE_GETTEXT -Wno-unused-variable
|
||||
CFLAGS-ialloc.c = -DNOID -DHAVE_GETTEXT -Wno-unused-variable
|
||||
CFLAGS-scheck.c = -DNOID -DHAVE_GETTEXT -Wno-unused-variable
|
||||
CFLAGS-zdump.c = $(tz-cflags)
|
||||
CFLAGS-zic.c = $(tz-cflags) -Wno-unused-variable
|
||||
|
||||
# We have to make sure the data for testing the tz functions is available.
|
||||
# Don't add leapseconds here since test-tz made checks that work only without
|
||||
|
@ -1,5 +1,5 @@
|
||||
The files
|
||||
zic.c zdump.c ialloc.c scheck.c tzfile.h
|
||||
zic.c zdump.c tzfile.h
|
||||
private.h tzselect.ksh checktab.awk
|
||||
come from the tzcode package by Arthur David Olson et.al.
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** 2006-07-17 by Arthur David Olson.
|
||||
*/
|
||||
|
||||
/*LINTLIBRARY*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
char *
|
||||
icatalloc(char *const old, const char *const new)
|
||||
{
|
||||
register char * result;
|
||||
register int oldsize, newsize;
|
||||
|
||||
newsize = (new == NULL) ? 0 : strlen(new);
|
||||
if (old == NULL)
|
||||
oldsize = 0;
|
||||
else if (newsize == 0)
|
||||
return old;
|
||||
else oldsize = strlen(old);
|
||||
if ((result = realloc(old, oldsize + newsize + 1)) != NULL)
|
||||
if (new != NULL)
|
||||
(void) strcpy(result + oldsize, new);
|
||||
return result;
|
||||
}
|
||||
|
||||
char *
|
||||
icpyalloc(const char *const string)
|
||||
{
|
||||
return icatalloc(NULL, string);
|
||||
}
|
@ -19,13 +19,9 @@
|
||||
|
||||
/*
|
||||
** Defaults for preprocessor symbols.
|
||||
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
|
||||
** You can override these in your C compiler options, e.g. '-DHAVE_GETTEXT=1'.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_ADJTIME
|
||||
#define HAVE_ADJTIME 1
|
||||
#endif /* !defined HAVE_ADJTIME */
|
||||
|
||||
#ifndef HAVE_GETTEXT
|
||||
#define HAVE_GETTEXT 0
|
||||
#endif /* !defined HAVE_GETTEXT */
|
||||
@ -38,9 +34,9 @@
|
||||
#define HAVE_LINK 1
|
||||
#endif /* !defined HAVE_LINK */
|
||||
|
||||
#ifndef HAVE_SETTIMEOFDAY
|
||||
#define HAVE_SETTIMEOFDAY 3
|
||||
#endif /* !defined HAVE_SETTIMEOFDAY */
|
||||
#ifndef HAVE_STRDUP
|
||||
#define HAVE_STRDUP 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYMLINK
|
||||
#define HAVE_SYMLINK 1
|
||||
@ -59,30 +55,61 @@
|
||||
#endif /* !defined HAVE_UNISTD_H */
|
||||
|
||||
#ifndef HAVE_UTMPX_H
|
||||
#define HAVE_UTMPX_H 0
|
||||
#define HAVE_UTMPX_H 1
|
||||
#endif /* !defined HAVE_UTMPX_H */
|
||||
|
||||
#ifndef LOCALE_HOME
|
||||
#define LOCALE_HOME "/usr/lib/locale"
|
||||
#endif /* !defined LOCALE_HOME */
|
||||
#ifndef NETBSD_INSPIRED
|
||||
# define NETBSD_INSPIRED 1
|
||||
#endif
|
||||
|
||||
#if HAVE_INCOMPATIBLE_CTIME_R
|
||||
#define asctime_r _incompatible_asctime_r
|
||||
#define ctime_r _incompatible_ctime_r
|
||||
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
|
||||
|
||||
/* Enable tm_gmtoff and tm_zone on GNUish systems. */
|
||||
#define _GNU_SOURCE 1
|
||||
/* Fix asctime_r on Solaris 10. */
|
||||
#define _POSIX_PTHREAD_SEMANTICS 1
|
||||
/* Enable strtoimax on Solaris 10. */
|
||||
#define __EXTENSIONS__ 1
|
||||
|
||||
/*
|
||||
** Nested includes
|
||||
*/
|
||||
|
||||
/* Avoid clashes with NetBSD by renaming NetBSD's declarations. */
|
||||
#define localtime_rz sys_localtime_rz
|
||||
#define mktime_z sys_mktime_z
|
||||
#define posix2time_z sys_posix2time_z
|
||||
#define time2posix_z sys_time2posix_z
|
||||
#define timezone_t sys_timezone_t
|
||||
#define tzalloc sys_tzalloc
|
||||
#define tzfree sys_tzfree
|
||||
#include <time.h>
|
||||
#undef localtime_rz
|
||||
#undef mktime_z
|
||||
#undef posix2time_z
|
||||
#undef time2posix_z
|
||||
#undef timezone_t
|
||||
#undef tzalloc
|
||||
#undef tzfree
|
||||
|
||||
#include "sys/types.h" /* for time_t */
|
||||
#include "stdio.h"
|
||||
#include "errno.h"
|
||||
#include "string.h"
|
||||
#include "limits.h" /* for CHAR_BIT et al. */
|
||||
#include "time.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#include "errno.h"
|
||||
|
||||
#ifndef ENAMETOOLONG
|
||||
# define ENAMETOOLONG EINVAL
|
||||
#endif
|
||||
#ifndef EOVERFLOW
|
||||
# define EOVERFLOW EINVAL
|
||||
#endif
|
||||
|
||||
#if HAVE_GETTEXT
|
||||
#include "libintl.h"
|
||||
#endif /* HAVE_GETTEXT */
|
||||
@ -102,6 +129,14 @@
|
||||
#include "unistd.h" /* for F_OK, R_OK, and other POSIX goodness */
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
#ifndef HAVE_STRFTIME_L
|
||||
# if _POSIX_VERSION < 200809
|
||||
# define HAVE_STRFTIME_L 0
|
||||
# else
|
||||
# define HAVE_STRFTIME_L 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef F_OK
|
||||
#define F_OK 0
|
||||
#endif /* !defined F_OK */
|
||||
@ -136,65 +171,98 @@
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef INT_FAST64_MAX
|
||||
/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
|
||||
#if defined LLONG_MAX || defined __LONG_LONG_MAX__
|
||||
typedef long long int_fast64_t;
|
||||
#ifdef __LONG_LONG_MAX__
|
||||
# ifndef LLONG_MAX
|
||||
# define LLONG_MAX __LONG_LONG_MAX__
|
||||
# endif
|
||||
# ifndef LLONG_MIN
|
||||
# define LLONG_MIN (-1 - LLONG_MAX)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef INT_FAST64_MAX
|
||||
# ifdef LLONG_MAX
|
||||
typedef long long int_fast64_t;
|
||||
# define INT_FAST64_MIN LLONG_MIN
|
||||
# define INT_FAST64_MAX LLONG_MAX
|
||||
# else
|
||||
# define INT_FAST64_MIN __LONG_LONG_MIN__
|
||||
# define INT_FAST64_MAX __LONG_LONG_MAX__
|
||||
# endif
|
||||
# define SCNdFAST64 "lld"
|
||||
#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
|
||||
#if (LONG_MAX >> 31) < 0xffffffff
|
||||
# if LONG_MAX >> 31 < 0xffffffff
|
||||
Please use a compiler that supports a 64-bit integer type (or wider);
|
||||
you may need to compile with "-DHAVE_STDINT_H".
|
||||
#endif /* (LONG_MAX >> 31) < 0xffffffff */
|
||||
# endif
|
||||
typedef long int_fast64_t;
|
||||
# define INT_FAST64_MIN LONG_MIN
|
||||
# define INT_FAST64_MAX LONG_MAX
|
||||
# define SCNdFAST64 "ld"
|
||||
#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
|
||||
#endif /* !defined INT_FAST64_MAX */
|
||||
# define INT_FAST64_MIN LONG_MIN
|
||||
# define INT_FAST64_MAX LONG_MAX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SCNdFAST64
|
||||
# if INT_FAST64_MAX == LLONG_MAX
|
||||
# define SCNdFAST64 "lld"
|
||||
# else
|
||||
# define SCNdFAST64 "ld"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef INT_FAST32_MAX
|
||||
# if INT_MAX >> 31 == 0
|
||||
typedef long int_fast32_t;
|
||||
# define INT_FAST32_MAX LONG_MAX
|
||||
# define INT_FAST32_MIN LONG_MIN
|
||||
# else
|
||||
typedef int int_fast32_t;
|
||||
# define INT_FAST32_MAX INT_MAX
|
||||
# define INT_FAST32_MIN INT_MIN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef INTMAX_MAX
|
||||
# if defined LLONG_MAX || defined __LONG_LONG_MAX__
|
||||
# ifdef LLONG_MAX
|
||||
typedef long long intmax_t;
|
||||
# define strtoimax strtoll
|
||||
# define PRIdMAX "lld"
|
||||
# ifdef LLONG_MAX
|
||||
# define INTMAX_MAX LLONG_MAX
|
||||
# define INTMAX_MIN LLONG_MIN
|
||||
# else
|
||||
# define INTMAX_MAX __LONG_LONG_MAX__
|
||||
# define INTMAX_MIN __LONG_LONG_MIN__
|
||||
# endif
|
||||
# define INTMAX_MAX LLONG_MAX
|
||||
# define INTMAX_MIN LLONG_MIN
|
||||
# else
|
||||
typedef long intmax_t;
|
||||
# define strtoimax strtol
|
||||
# define PRIdMAX "ld"
|
||||
# define INTMAX_MAX LONG_MAX
|
||||
# define INTMAX_MIN LONG_MIN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef PRIdMAX
|
||||
# if INTMAX_MAX == LLONG_MAX
|
||||
# define PRIdMAX "lld"
|
||||
# else
|
||||
# define PRIdMAX "ld"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef UINT_FAST64_MAX
|
||||
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
|
||||
typedef unsigned long long uint_fast64_t;
|
||||
# else
|
||||
# if ULONG_MAX >> 31 >> 1 < 0xffffffff
|
||||
Please use a compiler that supports a 64-bit integer type (or wider);
|
||||
you may need to compile with "-DHAVE_STDINT_H".
|
||||
# endif
|
||||
typedef unsigned long uint_fast64_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef UINTMAX_MAX
|
||||
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
|
||||
typedef unsigned long long uintmax_t;
|
||||
# define PRIuMAX "llu"
|
||||
# else
|
||||
typedef unsigned long uintmax_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef PRIuMAX
|
||||
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
|
||||
# define PRIuMAX "llu"
|
||||
# else
|
||||
# define PRIuMAX "lu"
|
||||
# endif
|
||||
#endif
|
||||
@ -236,16 +304,6 @@ typedef unsigned long uintmax_t;
|
||||
** Workarounds for compilers/systems.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Some time.h implementations don't declare asctime_r.
|
||||
** Others might define it as a macro.
|
||||
** Fix the former without affecting the latter.
|
||||
*/
|
||||
|
||||
#ifndef asctime_r
|
||||
extern char * asctime_r(struct tm const *, char *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Compile with -Dtime_tz=T to build the tz package with a private
|
||||
** time_t type equivalent to T rather than the system-supplied time_t.
|
||||
@ -254,7 +312,11 @@ extern char * asctime_r(struct tm const *, char *);
|
||||
** typical platforms.
|
||||
*/
|
||||
#ifdef time_tz
|
||||
# ifdef LOCALTIME_IMPLEMENTATION
|
||||
static time_t sys_time(time_t *x) { return time(x); }
|
||||
# endif
|
||||
|
||||
typedef time_tz tz_time_t;
|
||||
|
||||
# undef ctime
|
||||
# define ctime tz_ctime
|
||||
@ -270,14 +332,40 @@ static time_t sys_time(time_t *x) { return time(x); }
|
||||
# define localtime tz_localtime
|
||||
# undef localtime_r
|
||||
# define localtime_r tz_localtime_r
|
||||
# undef localtime_rz
|
||||
# define localtime_rz tz_localtime_rz
|
||||
# undef mktime
|
||||
# define mktime tz_mktime
|
||||
# undef mktime_z
|
||||
# define mktime_z tz_mktime_z
|
||||
# undef offtime
|
||||
# define offtime tz_offtime
|
||||
# undef posix2time
|
||||
# define posix2time tz_posix2time
|
||||
# undef posix2time_z
|
||||
# define posix2time_z tz_posix2time_z
|
||||
# undef time
|
||||
# define time tz_time
|
||||
# undef time2posix
|
||||
# define time2posix tz_time2posix
|
||||
# undef time2posix_z
|
||||
# define time2posix_z tz_time2posix_z
|
||||
# undef time_t
|
||||
# define time_t tz_time_t
|
||||
|
||||
typedef time_tz time_t;
|
||||
# undef timegm
|
||||
# define timegm tz_timegm
|
||||
# undef timelocal
|
||||
# define timelocal tz_timelocal
|
||||
# undef timeoff
|
||||
# define timeoff tz_timeoff
|
||||
# undef tzalloc
|
||||
# define tzalloc tz_tzalloc
|
||||
# undef tzfree
|
||||
# define tzfree tz_tzfree
|
||||
# undef tzset
|
||||
# define tzset tz_tzset
|
||||
# undef tzsetwall
|
||||
# define tzsetwall tz_tzsetwall
|
||||
|
||||
char *ctime(time_t const *);
|
||||
char *ctime_r(time_t const *, char *);
|
||||
@ -287,36 +375,111 @@ struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
|
||||
struct tm *localtime(time_t const *);
|
||||
struct tm *localtime_r(time_t const *restrict, struct tm *restrict);
|
||||
time_t mktime(struct tm *);
|
||||
|
||||
static time_t
|
||||
time(time_t *p)
|
||||
{
|
||||
time_t r = sys_time(0);
|
||||
if (p)
|
||||
*p = r;
|
||||
return r;
|
||||
}
|
||||
time_t time(time_t *);
|
||||
void tzset(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Private function declarations.
|
||||
** Some time.h implementations don't declare asctime_r.
|
||||
** Others might define it as a macro.
|
||||
** Fix the former without affecting the latter.
|
||||
** Similarly for timezone, daylight, and altzone.
|
||||
*/
|
||||
|
||||
char * icatalloc(char * old, const char * new);
|
||||
char * icpyalloc(const char * string);
|
||||
const char * scheck(const char * string, const char * format);
|
||||
#ifndef asctime_r
|
||||
extern char * asctime_r(struct tm const *restrict, char *restrict);
|
||||
#endif
|
||||
|
||||
#ifdef USG_COMPAT
|
||||
# ifndef timezone
|
||||
extern long timezone;
|
||||
# endif
|
||||
# ifndef daylight
|
||||
extern int daylight;
|
||||
# endif
|
||||
#endif
|
||||
#if defined ALTZONE && !defined altzone
|
||||
extern long altzone;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The STD_INSPIRED functions are similar, but most also need
|
||||
** declarations if time_tz is defined.
|
||||
*/
|
||||
|
||||
#ifdef STD_INSPIRED
|
||||
# if !defined tzsetwall || defined time_tz
|
||||
void tzsetwall(void);
|
||||
# endif
|
||||
# if !defined offtime || defined time_tz
|
||||
struct tm *offtime(time_t const *, long);
|
||||
# endif
|
||||
# if !defined timegm || defined time_tz
|
||||
time_t timegm(struct tm *);
|
||||
# endif
|
||||
# if !defined timelocal || defined time_tz
|
||||
time_t timelocal(struct tm *);
|
||||
# endif
|
||||
# if !defined timeoff || defined time_tz
|
||||
time_t timeoff(struct tm *, long);
|
||||
# endif
|
||||
# if !defined time2posix || defined time_tz
|
||||
time_t time2posix(time_t);
|
||||
# endif
|
||||
# if !defined posix2time || defined time_tz
|
||||
time_t posix2time(time_t);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Infer TM_ZONE on systems where this information is known, but suppress
|
||||
guessing if NO_TM_ZONE is defined. Similarly for TM_GMTOFF. */
|
||||
#if (defined __GLIBC__ \
|
||||
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|
||||
|| (defined __APPLE__ && defined __MACH__))
|
||||
# if !defined TM_GMTOFF && !defined NO_TM_GMTOFF
|
||||
# define TM_GMTOFF tm_gmtoff
|
||||
# endif
|
||||
# if !defined TM_ZONE && !defined NO_TM_ZONE
|
||||
# define TM_ZONE tm_zone
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Define functions that are ABI compatible with NetBSD but have
|
||||
** better prototypes. NetBSD 6.1.4 defines a pointer type timezone_t
|
||||
** and labors under the misconception that 'const timezone_t' is a
|
||||
** pointer to a constant. This use of 'const' is ineffective, so it
|
||||
** is not done here. What we call 'struct state' NetBSD calls
|
||||
** 'struct __state', but this is a private name so it doesn't matter.
|
||||
*/
|
||||
#if NETBSD_INSPIRED
|
||||
typedef struct state *timezone_t;
|
||||
struct tm *localtime_rz(timezone_t restrict, time_t const *restrict,
|
||||
struct tm *restrict);
|
||||
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
|
||||
time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE;
|
||||
# endif
|
||||
# if !defined time2posix_z || defined time_tz
|
||||
time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Finally, some convenience items.
|
||||
*/
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif /* !defined TRUE */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif /* !defined FALSE */
|
||||
#if __STDC_VERSION__ < 199901
|
||||
# define true 1
|
||||
# define false 0
|
||||
# define bool int
|
||||
#else
|
||||
# include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifndef TYPE_BIT
|
||||
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
|
||||
@ -326,15 +489,20 @@ const char * scheck(const char * string, const char * format);
|
||||
#define TYPE_SIGNED(type) (((type) -1) < 0)
|
||||
#endif /* !defined TYPE_SIGNED */
|
||||
|
||||
/* The minimum and maximum finite time values. */
|
||||
static time_t const time_t_min =
|
||||
(TYPE_SIGNED(time_t)
|
||||
? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)
|
||||
: 0);
|
||||
static time_t const time_t_max =
|
||||
(TYPE_SIGNED(time_t)
|
||||
? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
|
||||
: -1);
|
||||
#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
|
||||
|
||||
/* Max and min values of the integer type T, of which only the bottom
|
||||
B bits are used, and where the highest-order used bit is considered
|
||||
to be a sign bit if T is signed. */
|
||||
#define MAXVAL(t, b) \
|
||||
((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t))) \
|
||||
- 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))))
|
||||
#define MINVAL(t, b) \
|
||||
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
|
||||
|
||||
/* The minimum and maximum finite time values. This assumes no padding. */
|
||||
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));
|
||||
|
||||
#ifndef INT_STRLEN_MAXIMUM
|
||||
/*
|
||||
@ -352,29 +520,19 @@ static time_t const time_t_max =
|
||||
** INITIALIZE(x)
|
||||
*/
|
||||
|
||||
#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 */
|
||||
# define INITIALIZE(x) ((x) = 0)
|
||||
#else
|
||||
# define INITIALIZE(x)
|
||||
#endif
|
||||
|
||||
#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 */
|
||||
#ifndef UNINIT_TRAP
|
||||
# define UNINIT_TRAP 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For the benefit of GNU folk...
|
||||
** `_(MSGID)' uses the current locale's message library string for MSGID.
|
||||
** '_(MSGID)' uses the current locale's message library string for MSGID.
|
||||
** The default is to use gettext if available, and use MSGID otherwise.
|
||||
*/
|
||||
|
||||
@ -386,9 +544,9 @@ static time_t const time_t_max =
|
||||
#endif /* !HAVE_GETTEXT */
|
||||
#endif /* !defined _ */
|
||||
|
||||
#ifndef TZ_DOMAIN
|
||||
#define TZ_DOMAIN "tz"
|
||||
#endif /* !defined TZ_DOMAIN */
|
||||
#if !defined TZ_DOMAIN && defined HAVE_GETTEXT
|
||||
# define TZ_DOMAIN "tz"
|
||||
#endif
|
||||
|
||||
#if HAVE_INCOMPATIBLE_CTIME_R
|
||||
#undef asctime_r
|
||||
@ -417,8 +575,4 @@ char *ctime_r(time_t const *, char *);
|
||||
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
|
||||
#endif /* !defined SECSPERREPEAT_BITS */
|
||||
|
||||
/*
|
||||
** UNIX was a registered trademark of The Open Group in 2003.
|
||||
*/
|
||||
|
||||
#endif /* !defined PRIVATE_H */
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** 2006-07-17 by Arthur David Olson.
|
||||
*/
|
||||
|
||||
/*LINTLIBRARY*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
const char *
|
||||
scheck(const char *const string, const char *const format)
|
||||
{
|
||||
register char * fbuf;
|
||||
register const char * fp;
|
||||
register char * tp;
|
||||
register int c;
|
||||
register const char * result;
|
||||
char dummy;
|
||||
|
||||
result = "";
|
||||
if (string == NULL || format == NULL)
|
||||
return result;
|
||||
fbuf = malloc(2 * strlen(format) + 4);
|
||||
if (fbuf == NULL)
|
||||
return result;
|
||||
fp = format;
|
||||
tp = fbuf;
|
||||
|
||||
/*
|
||||
** Copy directives, suppressing each conversion that is not
|
||||
** already suppressed. Scansets containing '%' are not
|
||||
** supported; e.g., the conversion specification "%[%]" is not
|
||||
** supported. Also, multibyte characters containing a
|
||||
** non-leading '%' byte are not supported.
|
||||
*/
|
||||
while ((*tp++ = c = *fp++) != '\0') {
|
||||
if (c != '%')
|
||||
continue;
|
||||
if (is_digit(*fp)) {
|
||||
char const *f = fp;
|
||||
char *t = tp;
|
||||
do {
|
||||
*t++ = c = *f++;
|
||||
} while (is_digit(c));
|
||||
if (c == '$') {
|
||||
fp = f;
|
||||
tp = t;
|
||||
}
|
||||
}
|
||||
*tp++ = '*';
|
||||
if (*fp == '*')
|
||||
++fp;
|
||||
if ((*tp++ = *fp++) == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
*(tp - 1) = '%';
|
||||
*tp++ = 'c';
|
||||
*tp = '\0';
|
||||
if (sscanf(string, fbuf, &dummy) != 1)
|
||||
result = format;
|
||||
free(fbuf);
|
||||
return result;
|
||||
}
|
@ -40,7 +40,7 @@
|
||||
struct tzhead {
|
||||
char tzh_magic[4]; /* TZ_MAGIC */
|
||||
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
|
||||
char tzh_reserved[15]; /* reserved--must be zero */
|
||||
char tzh_reserved[15]; /* reserved; must be zero */
|
||||
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_leapcnt[4]; /* coded number of leap seconds */
|
||||
@ -62,13 +62,13 @@ struct tzhead {
|
||||
** tzh_leapcnt repetitions of
|
||||
** one (char [4]) coded leap second transition times
|
||||
** one (char [4]) total correction after above
|
||||
** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
|
||||
** time is standard time, if FALSE,
|
||||
** tzh_ttisstdcnt (char)s indexed by type; if 1, transition
|
||||
** time is standard time, if 0,
|
||||
** transition time is wall clock time
|
||||
** if absent, transition times are
|
||||
** assumed to be wall clock time
|
||||
** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
|
||||
** time is UT, if FALSE,
|
||||
** tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
|
||||
** time is UT, if 0,
|
||||
** transition time is local time
|
||||
** if absent, transition times are
|
||||
** assumed to be local time
|
||||
|
@ -37,15 +37,22 @@ REPORT_BUGS_TO=tz@iana.org
|
||||
: ${AWK=awk}
|
||||
: ${TZDIR=`pwd`}
|
||||
|
||||
# Output one argument as-is to standard output.
|
||||
# Safer than 'echo', which can mishandle '\' or leading '-'.
|
||||
say() {
|
||||
printf '%s\n' "$1"
|
||||
}
|
||||
|
||||
# Check for awk Posix compliance.
|
||||
($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
|
||||
[ $? = 123 ] || {
|
||||
echo >&2 "$0: Sorry, your \`$AWK' program is not Posix compatible."
|
||||
say >&2 "$0: Sorry, your '$AWK' program is not Posix compatible."
|
||||
exit 1
|
||||
}
|
||||
|
||||
coord=
|
||||
location_limit=10
|
||||
zonetabtype=zone1970
|
||||
|
||||
usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT]
|
||||
Select a time zone interactively.
|
||||
@ -80,7 +87,7 @@ if
|
||||
?*) : ;;
|
||||
'')
|
||||
# '; exit' should be redundant, but Dash doesn't properly fail without it.
|
||||
(eval 'set --; select x; do break; done; exit') 2>/dev/null
|
||||
(eval 'set --; select x; do break; done; exit') </dev/null 2>/dev/null
|
||||
esac
|
||||
then
|
||||
# Do this inside 'eval', as otherwise the shell might exit when parsing it
|
||||
@ -139,41 +146,58 @@ else
|
||||
}
|
||||
fi
|
||||
|
||||
while getopts c:n:-: opt
|
||||
while getopts c:n:t:-: opt
|
||||
do
|
||||
case $opt$OPTARG in
|
||||
c*)
|
||||
coord=$OPTARG ;;
|
||||
n*)
|
||||
location_limit=$OPTARG ;;
|
||||
t*) # Undocumented option, used for developer testing.
|
||||
zonetabtype=$OPTARG ;;
|
||||
-help)
|
||||
exec echo "$usage" ;;
|
||||
-version)
|
||||
exec echo "tzselect $PKGVERSION$TZVERSION" ;;
|
||||
-*)
|
||||
echo >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;;
|
||||
say >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;;
|
||||
*)
|
||||
echo >&2 "$0: try '$0 --help'"; exit 1 ;;
|
||||
say >&2 "$0: try '$0 --help'"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift `expr $OPTIND - 1`
|
||||
case $# in
|
||||
0) ;;
|
||||
*) echo >&2 "$0: $1: unknown argument"; exit 1 ;;
|
||||
*) say >&2 "$0: $1: unknown argument"; exit 1 ;;
|
||||
esac
|
||||
|
||||
# Make sure the tables are readable.
|
||||
TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
|
||||
TZ_ZONE_TABLE=$TZDIR/zone.tab
|
||||
TZ_ZONE_TABLE=$TZDIR/$zonetabtype.tab
|
||||
for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE
|
||||
do
|
||||
<$f || {
|
||||
echo >&2 "$0: time zone files are not set up correctly"
|
||||
<"$f" || {
|
||||
say >&2 "$0: time zone files are not set up correctly"
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
# If the current locale does not support UTF-8, convert data to current
|
||||
# locale's format if possible, as the shell aligns columns better that way.
|
||||
# Check the UTF-8 of U+12345 CUNEIFORM SIGN URU TIMES KI.
|
||||
! $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) != 1 }' &&
|
||||
{ tmp=`(mktemp -d) 2>/dev/null` || {
|
||||
tmp=${TMPDIR-/tmp}/tzselect.$$ &&
|
||||
(umask 77 && mkdir -- "$tmp")
|
||||
};} &&
|
||||
trap 'status=$?; rm -fr -- "$tmp"; exit $status' 0 HUP INT PIPE TERM &&
|
||||
(iconv -f UTF-8 -t //TRANSLIT <"$TZ_COUNTRY_TABLE" >$tmp/iso3166.tab) \
|
||||
2>/dev/null &&
|
||||
TZ_COUNTRY_TABLE=$tmp/iso3166.tab &&
|
||||
iconv -f UTF-8 -t //TRANSLIT <"$TZ_ZONE_TABLE" >$tmp/$zonetabtype.tab &&
|
||||
TZ_ZONE_TABLE=$tmp/$zonetabtype.tab
|
||||
|
||||
newline='
|
||||
'
|
||||
IFS=$newline
|
||||
@ -189,7 +213,13 @@ output_distances='
|
||||
country[$1] = $2
|
||||
country["US"] = "US" # Otherwise the strings get too long.
|
||||
}
|
||||
function convert_coord(coord, deg, min, ilen, sign, sec) {
|
||||
function abs(x) {
|
||||
return x < 0 ? -x : x;
|
||||
}
|
||||
function min(x, y) {
|
||||
return x < y ? x : y;
|
||||
}
|
||||
function convert_coord(coord, deg, minute, ilen, sign, sec) {
|
||||
if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9][0-9][0-9]([^0-9]|$)/) {
|
||||
degminsec = coord
|
||||
intdeg = degminsec < 0 ? -int(-degminsec / 10000) : int(degminsec / 10000)
|
||||
@ -200,8 +230,8 @@ output_distances='
|
||||
} else if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9]([^0-9]|$)/) {
|
||||
degmin = coord
|
||||
intdeg = degmin < 0 ? -int(-degmin / 100) : int(degmin / 100)
|
||||
min = degmin - intdeg * 100
|
||||
deg = (intdeg * 60 + min) / 60
|
||||
minute = degmin - intdeg * 100
|
||||
deg = (intdeg * 60 + minute) / 60
|
||||
} else
|
||||
deg = coord
|
||||
return deg * 0.017453292519943296
|
||||
@ -217,14 +247,27 @@ output_distances='
|
||||
# Great-circle distance between points with given latitude and longitude.
|
||||
# Inputs and output are in radians. This uses the great-circle special
|
||||
# case of the Vicenty formula for distances on ellipsoids.
|
||||
function dist(lat1, long1, lat2, long2, dlong, x, y, num, denom) {
|
||||
function gcdist(lat1, long1, lat2, long2, dlong, x, y, num, denom) {
|
||||
dlong = long2 - long1
|
||||
x = cos (lat2) * sin (dlong)
|
||||
y = cos (lat1) * sin (lat2) - sin (lat1) * cos (lat2) * cos (dlong)
|
||||
num = sqrt (x * x + y * y)
|
||||
denom = sin (lat1) * sin (lat2) + cos (lat1) * cos (lat2) * cos (dlong)
|
||||
x = cos(lat2) * sin(dlong)
|
||||
y = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlong)
|
||||
num = sqrt(x * x + y * y)
|
||||
denom = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(dlong)
|
||||
return atan2(num, denom)
|
||||
}
|
||||
# Parallel distance between points with given latitude and longitude.
|
||||
# This is the product of the longitude difference and the cosine
|
||||
# of the latitude of the point that is further from the equator.
|
||||
# I.e., it considers longitudes to be further apart if they are
|
||||
# nearer the equator.
|
||||
function pardist(lat1, long1, lat2, long2) {
|
||||
return abs(long1 - long2) * min(cos(lat1), cos(lat2))
|
||||
}
|
||||
# The distance function is the sum of the great-circle distance and
|
||||
# the parallel distance. It could be weighted.
|
||||
function dist(lat1, long1, lat2, long2) {
|
||||
return gcdist(lat1, long1, lat2, long2) + pardist(lat1, long1, lat2, long2)
|
||||
}
|
||||
BEGIN {
|
||||
coord_lat = convert_latitude(coord)
|
||||
coord_long = convert_longitude(coord)
|
||||
@ -232,7 +275,13 @@ output_distances='
|
||||
/^[^#]/ {
|
||||
here_lat = convert_latitude($2)
|
||||
here_long = convert_longitude($2)
|
||||
line = $1 "\t" $2 "\t" $3 "\t" country[$1]
|
||||
line = $1 "\t" $2 "\t" $3
|
||||
sep = "\t"
|
||||
ncc = split($1, cc, /,/)
|
||||
for (i = 1; i <= ncc; i++) {
|
||||
line = line sep country[cc[i]]
|
||||
sep = ", "
|
||||
}
|
||||
if (NF == 4)
|
||||
line = line " - " $4
|
||||
printf "%g\t%s\n", dist(coord_lat, coord_long, here_lat, here_long), line
|
||||
@ -269,7 +318,7 @@ while
|
||||
entry = entry " Ocean"
|
||||
printf "'\''%s'\''\n", entry
|
||||
}
|
||||
' $TZ_ZONE_TABLE |
|
||||
' <"$TZ_ZONE_TABLE" |
|
||||
sort -u |
|
||||
tr '\n' ' '
|
||||
echo ''
|
||||
@ -300,7 +349,7 @@ while
|
||||
tzname = "[^-+,0-9][^-+,0-9][^-+,0-9]+"
|
||||
time = "[0-2]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?"
|
||||
offset = "[-+]?" time
|
||||
date = "(J?[0-9]+|M[0-9]+\.[0-9]+\.[0-9]+)"
|
||||
date = "(J?[0-9]+|M[0-9]+\\.[0-9]+\\.[0-9]+)"
|
||||
datetime = "," date "(/" time ")?"
|
||||
tzpattern = "^(:.*|" tzname offset "(" tzname \
|
||||
"(" offset ")?(" datetime datetime ")?)?)$"
|
||||
@ -308,8 +357,7 @@ while
|
||||
exit 0
|
||||
}'
|
||||
do
|
||||
echo >&2 "\`$TZ' is not a conforming" \
|
||||
'Posix time zone string.'
|
||||
say >&2 "'$TZ' is not a conforming Posix time zone string."
|
||||
done
|
||||
TZ_for_date=$TZ;;
|
||||
*)
|
||||
@ -327,11 +375,11 @@ while
|
||||
distance_table=`$AWK \
|
||||
-v coord="$coord" \
|
||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||
"$output_distances" <$TZ_ZONE_TABLE |
|
||||
"$output_distances" <"$TZ_ZONE_TABLE" |
|
||||
sort -n |
|
||||
sed "${location_limit}q"
|
||||
`
|
||||
regions=`echo "$distance_table" | $AWK '
|
||||
regions=`say "$distance_table" | $AWK '
|
||||
BEGIN { FS = "\t" }
|
||||
{ print $NF }
|
||||
'`
|
||||
@ -341,7 +389,7 @@ while
|
||||
"of distance from $coord".
|
||||
doselect $regions
|
||||
region=$select_result
|
||||
TZ=`echo "$distance_table" | $AWK -v region="$region" '
|
||||
TZ=`say "$distance_table" | $AWK -v region="$region" '
|
||||
BEGIN { FS="\t" }
|
||||
$NF == region { print $4 }
|
||||
'`
|
||||
@ -355,7 +403,9 @@ while
|
||||
BEGIN { FS = "\t" }
|
||||
/^#/ { next }
|
||||
$3 ~ ("^" continent "/") {
|
||||
if (!cc_seen[$1]++) cc_list[++ccs] = $1
|
||||
ncc = split($1, cc, /,/)
|
||||
for (i = 1; i <= ncc; i++)
|
||||
if (!cc_seen[cc[i]]++) cc_list[++ccs] = cc[i]
|
||||
}
|
||||
END {
|
||||
while (getline <TZ_COUNTRY_TABLE) {
|
||||
@ -369,7 +419,7 @@ while
|
||||
print country
|
||||
}
|
||||
}
|
||||
' <$TZ_ZONE_TABLE | sort -f`
|
||||
' <"$TZ_ZONE_TABLE" | sort -f`
|
||||
|
||||
|
||||
# If there's more than one country, ask the user which one.
|
||||
@ -399,8 +449,9 @@ while
|
||||
}
|
||||
}
|
||||
}
|
||||
$1 == cc { print $4 }
|
||||
' <$TZ_ZONE_TABLE`
|
||||
/^#/ { next }
|
||||
$1 ~ cc { print $4 }
|
||||
' <"$TZ_ZONE_TABLE"`
|
||||
|
||||
|
||||
# If there's more than one region, ask the user which one.
|
||||
@ -430,14 +481,15 @@ while
|
||||
}
|
||||
}
|
||||
}
|
||||
$1 == cc && $4 == region { print $3 }
|
||||
' <$TZ_ZONE_TABLE`
|
||||
/^#/ { next }
|
||||
$1 ~ cc && $4 == region { print $3 }
|
||||
' <"$TZ_ZONE_TABLE"`
|
||||
esac
|
||||
|
||||
# Make sure the corresponding zoneinfo file exists.
|
||||
TZ_for_date=$TZDIR/$TZ
|
||||
<$TZ_for_date || {
|
||||
echo >&2 "$0: time zone files are not set up correctly"
|
||||
<"$TZ_for_date" || {
|
||||
say >&2 "$0: time zone files are not set up correctly"
|
||||
exit 1
|
||||
}
|
||||
esac
|
||||
@ -470,15 +522,15 @@ Universal Time is now: $UTdate."
|
||||
echo >&2 "The following information has been given:"
|
||||
echo >&2 ""
|
||||
case $country%$region%$coord in
|
||||
?*%?*%) echo >&2 " $country$newline $region";;
|
||||
?*%%) echo >&2 " $country";;
|
||||
%?*%?*) echo >&2 " coord $coord$newline $region";;
|
||||
%%?*) echo >&2 " coord $coord";;
|
||||
+) echo >&2 " TZ='$TZ'"
|
||||
?*%?*%) say >&2 " $country$newline $region";;
|
||||
?*%%) say >&2 " $country";;
|
||||
%?*%?*) say >&2 " coord $coord$newline $region";;
|
||||
%%?*) say >&2 " coord $coord";;
|
||||
*) say >&2 " TZ='$TZ'"
|
||||
esac
|
||||
echo >&2 ""
|
||||
echo >&2 "Therefore TZ='$TZ' will be used.$extra_info"
|
||||
echo >&2 "Is the above information OK?"
|
||||
say >&2 ""
|
||||
say >&2 "Therefore TZ='$TZ' will be used.$extra_info"
|
||||
say >&2 "Is the above information OK?"
|
||||
|
||||
doselect Yes No
|
||||
ok=$select_result
|
||||
@ -493,7 +545,7 @@ case $SHELL in
|
||||
*) file=.profile line="TZ='$TZ'; export TZ"
|
||||
esac
|
||||
|
||||
echo >&2 "
|
||||
say >&2 "
|
||||
You can make this change permanent for yourself by appending the line
|
||||
$line
|
||||
to the file '$file' in your home directory; then log out and log in again.
|
||||
@ -501,4 +553,4 @@ to the file '$file' in your home directory; then log out and log in again.
|
||||
Here is that TZ value again, this time on standard output so that you
|
||||
can use the $0 command in shell scripts:"
|
||||
|
||||
echo "$TZ"
|
||||
say "$TZ"
|
||||
|
690
timezone/zdump.c
690
timezone/zdump.c
@ -9,25 +9,32 @@
|
||||
** 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.
|
||||
**
|
||||
** However, include private.h when debugging, so that it overrides
|
||||
** time_t consistently with the rest of the package.
|
||||
** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
|
||||
*/
|
||||
|
||||
#ifdef time_tz
|
||||
#ifndef NETBSD_INSPIRED
|
||||
# define NETBSD_INSPIRED 1
|
||||
#endif
|
||||
#ifndef USE_LTZ
|
||||
# define USE_LTZ 1
|
||||
#endif
|
||||
|
||||
#if USE_LTZ
|
||||
# include "private.h"
|
||||
#endif
|
||||
|
||||
/* Enable tm_gmtoff and tm_zone on GNUish systems. */
|
||||
#define _GNU_SOURCE 1
|
||||
/* Enable strtoimax on Solaris 10. */
|
||||
#define __EXTENSIONS__ 1
|
||||
|
||||
#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 */
|
||||
#include "limits.h" /* for CHAR_BIT, LLONG_MAX */
|
||||
#include "ctype.h" /* for isalpha et al. */
|
||||
#ifndef isascii
|
||||
#define isascii(x) 1
|
||||
#endif /* !defined isascii */
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
** Substitutes for pre-C99 compilers.
|
||||
@ -58,24 +65,59 @@ typedef int int_fast32_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
|
||||
#if !defined LLONG_MAX && defined __LONG_LONG_MAX__
|
||||
# define LLONG_MAX __LONG_LONG_MAX__
|
||||
#endif
|
||||
|
||||
#ifndef INTMAX_MAX
|
||||
# if defined LLONG_MAX || defined __LONG_LONG_MAX__
|
||||
# ifdef LLONG_MAX
|
||||
typedef long long intmax_t;
|
||||
# define strtoimax strtoll
|
||||
# define PRIdMAX "lld"
|
||||
# ifdef LLONG_MAX
|
||||
# define INTMAX_MAX LLONG_MAX
|
||||
# else
|
||||
# define INTMAX_MAX __LONG_LONG_MAX__
|
||||
# endif
|
||||
# define INTMAX_MAX LLONG_MAX
|
||||
# else
|
||||
typedef long intmax_t;
|
||||
# define strtoimax strtol
|
||||
# define PRIdMAX "ld"
|
||||
# define INTMAX_MAX LONG_MAX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef PRIdMAX
|
||||
# if INTMAX_MAX == LLONG_MAX
|
||||
# define PRIdMAX "lld"
|
||||
# else
|
||||
# define PRIdMAX "ld"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Infer TM_ZONE on systems where this information is known, but suppress
|
||||
guessing if NO_TM_ZONE is defined. Similarly for TM_GMTOFF. */
|
||||
#if (defined __GLIBC__ \
|
||||
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|
||||
|| (defined __APPLE__ && defined __MACH__))
|
||||
# if !defined TM_GMTOFF && !defined NO_TM_GMTOFF
|
||||
# define TM_GMTOFF tm_gmtoff
|
||||
# endif
|
||||
# if !defined TM_ZONE && !defined NO_TM_ZONE
|
||||
# define TM_ZONE tm_zone
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
# define HAVE_LOCALTIME_R 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LOCALTIME_RZ
|
||||
# ifdef TM_ZONE
|
||||
# define HAVE_LOCALTIME_RZ (NETBSD_INSPIRED && USE_LTZ)
|
||||
# else
|
||||
# define HAVE_LOCALTIME_RZ 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_TZSET
|
||||
# define HAVE_TZSET 1
|
||||
#endif
|
||||
|
||||
#ifndef ZDUMP_LO_YEAR
|
||||
#define ZDUMP_LO_YEAR (-500)
|
||||
@ -89,13 +131,13 @@ typedef long intmax_t;
|
||||
#define MAX_STRING_LENGTH 1024
|
||||
#endif /* !defined MAX_STRING_LENGTH */
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif /* !defined TRUE */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif /* !defined FALSE */
|
||||
#if __STDC_VERSION__ < 199901
|
||||
# define true 1
|
||||
# define false 0
|
||||
# define bool int
|
||||
#else
|
||||
# include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_SUCCESS
|
||||
#define EXIT_SUCCESS 0
|
||||
@ -167,16 +209,6 @@ enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 };
|
||||
#include "libintl.h"
|
||||
#endif /* HAVE_GETTEXT */
|
||||
|
||||
#ifndef GNUC_or_lint
|
||||
#ifdef lint
|
||||
#define GNUC_or_lint
|
||||
#else /* !defined lint */
|
||||
#ifdef __GNUC__
|
||||
#define GNUC_or_lint
|
||||
#endif /* defined __GNUC__ */
|
||||
#endif /* !defined lint */
|
||||
#endif /* !defined GNUC_or_lint */
|
||||
|
||||
#if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
|
||||
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
|
||||
#else
|
||||
@ -185,7 +217,7 @@ enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 };
|
||||
|
||||
/*
|
||||
** For the benefit of GNU folk...
|
||||
** `_(MSGID)' uses the current locale's message library string for MSGID.
|
||||
** '_(MSGID)' uses the current locale's message library string for MSGID.
|
||||
** The default is to use gettext if available, and use MSGID otherwise.
|
||||
*/
|
||||
|
||||
@ -197,9 +229,14 @@ enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 };
|
||||
#endif /* !HAVE_GETTEXT */
|
||||
#endif /* !defined _ */
|
||||
|
||||
#ifndef TZ_DOMAIN
|
||||
#define TZ_DOMAIN "tz"
|
||||
#endif /* !defined TZ_DOMAIN */
|
||||
#if !defined TZ_DOMAIN && defined HAVE_GETTEXT
|
||||
# define TZ_DOMAIN "tz"
|
||||
#endif
|
||||
|
||||
#if ! HAVE_LOCALTIME_RZ
|
||||
# undef timezone_t
|
||||
# define timezone_t char **
|
||||
#endif
|
||||
|
||||
extern char ** environ;
|
||||
extern int getopt(int argc, char * const argv[],
|
||||
@ -209,57 +246,233 @@ extern int optind;
|
||||
extern char * tzname[2];
|
||||
|
||||
/* The minimum and maximum finite time values. */
|
||||
enum { atime_shift = CHAR_BIT * sizeof (time_t) - 2 };
|
||||
static time_t const absolute_min_time =
|
||||
((time_t) -1 < 0
|
||||
? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)
|
||||
? (- ((time_t) ~ (time_t) 0 < 0)
|
||||
- (((time_t) 1 << atime_shift) - 1 + ((time_t) 1 << atime_shift)))
|
||||
: 0);
|
||||
static time_t const absolute_max_time =
|
||||
((time_t) -1 < 0
|
||||
? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
|
||||
? (((time_t) 1 << atime_shift) - 1 + ((time_t) 1 << atime_shift))
|
||||
: -1);
|
||||
static size_t longest;
|
||||
static int longest;
|
||||
static char * progname;
|
||||
static int warned;
|
||||
static bool warned;
|
||||
static bool errout;
|
||||
|
||||
static char * abbr(struct tm * tmp);
|
||||
static void abbrok(const char * abbrp, const char * zone);
|
||||
static intmax_t delta(struct tm * newp, struct tm * oldp) ATTRIBUTE_PURE;
|
||||
static void dumptime(const struct tm * tmp);
|
||||
static time_t hunt(char * name, time_t lot, time_t hit);
|
||||
static void show(char * zone, time_t t, int v);
|
||||
static const char * tformat(void);
|
||||
static time_t yeartot(intmax_t y) ATTRIBUTE_PURE;
|
||||
static char const *abbr(struct tm const *);
|
||||
static intmax_t delta(struct tm *, struct tm *) ATTRIBUTE_PURE;
|
||||
static void dumptime(struct tm const *);
|
||||
static time_t hunt(timezone_t, char *, time_t, time_t);
|
||||
static void show(timezone_t, char *, time_t, bool);
|
||||
static const char *tformat(void);
|
||||
static time_t yeartot(intmax_t) ATTRIBUTE_PURE;
|
||||
|
||||
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
|
||||
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
|
||||
|
||||
/* Is A an alphabetic character in the C locale? */
|
||||
static bool
|
||||
is_alpha(char a)
|
||||
{
|
||||
switch (a) {
|
||||
default:
|
||||
return false;
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
|
||||
case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
|
||||
case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
|
||||
case 'V': case 'W': case 'X': case 'Y': case 'Z':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
|
||||
case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
|
||||
case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
|
||||
case 'v': case 'w': case 'x': case 'y': case 'z':
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return A + B, exiting if the result would overflow. */
|
||||
static size_t
|
||||
sumsize(size_t a, size_t b)
|
||||
{
|
||||
size_t sum = a + b;
|
||||
if (sum < a) {
|
||||
fprintf(stderr, "%s: size overflow\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
#if ! HAVE_TZSET
|
||||
# undef tzset
|
||||
# define tzset zdump_tzset
|
||||
static void tzset(void) { }
|
||||
#endif
|
||||
|
||||
/* Assume gmtime_r works if localtime_r does.
|
||||
A replacement localtime_r is defined below if needed. */
|
||||
#if ! HAVE_LOCALTIME_R
|
||||
|
||||
# undef gmtime_r
|
||||
# define gmtime_r zdump_gmtime_r
|
||||
|
||||
static struct tm *
|
||||
gmtime_r(time_t *tp, struct tm *tmp)
|
||||
{
|
||||
struct tm *r = gmtime(tp);
|
||||
if (r) {
|
||||
*tmp = *r;
|
||||
r = tmp;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Platforms with TM_ZONE don't need tzname, so they can use the
|
||||
faster localtime_rz or localtime_r if available. */
|
||||
|
||||
#if defined TM_ZONE && HAVE_LOCALTIME_RZ
|
||||
# define USE_LOCALTIME_RZ true
|
||||
#else
|
||||
# define USE_LOCALTIME_RZ false
|
||||
#endif
|
||||
|
||||
#if ! USE_LOCALTIME_RZ
|
||||
|
||||
# if !defined TM_ZONE || ! HAVE_LOCALTIME_R || ! HAVE_TZSET
|
||||
# undef localtime_r
|
||||
# define localtime_r zdump_localtime_r
|
||||
static struct tm *
|
||||
localtime_r(time_t *tp, struct tm *tmp)
|
||||
{
|
||||
struct tm *r = localtime(tp);
|
||||
if (r) {
|
||||
*tmp = *r;
|
||||
r = tmp;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
# endif
|
||||
|
||||
# undef localtime_rz
|
||||
# define localtime_rz zdump_localtime_rz
|
||||
static struct tm *
|
||||
localtime_rz(timezone_t rz, time_t *tp, struct tm *tmp)
|
||||
{
|
||||
return localtime_r(tp, tmp);
|
||||
}
|
||||
|
||||
# ifdef TYPECHECK
|
||||
# undef mktime_z
|
||||
# define mktime_z zdump_mktime_z
|
||||
static time_t
|
||||
mktime_z(timezone_t tz, struct tm *tmp)
|
||||
{
|
||||
return mktime(tmp);
|
||||
}
|
||||
# endif
|
||||
|
||||
# undef tzalloc
|
||||
# undef tzfree
|
||||
# define tzalloc zdump_tzalloc
|
||||
# define tzfree zdump_tzfree
|
||||
|
||||
static timezone_t
|
||||
tzalloc(char const *val)
|
||||
{
|
||||
static char **fakeenv;
|
||||
char **env = fakeenv;
|
||||
char *env0;
|
||||
if (! env) {
|
||||
char **e = environ;
|
||||
int to;
|
||||
|
||||
while (*e++)
|
||||
continue;
|
||||
env = malloc(sumsize(sizeof *environ,
|
||||
(e - environ) * sizeof *environ));
|
||||
if (! env) {
|
||||
perror(progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
to = 1;
|
||||
for (e = environ; (env[to] = *e); e++)
|
||||
to += strncmp(*e, "TZ=", 3) != 0;
|
||||
}
|
||||
env0 = malloc(sumsize(sizeof "TZ=", strlen(val)));
|
||||
if (! env0) {
|
||||
perror(progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
env[0] = strcat(strcpy(env0, "TZ="), val);
|
||||
environ = fakeenv = env;
|
||||
tzset();
|
||||
return env;
|
||||
}
|
||||
|
||||
static void
|
||||
tzfree(timezone_t env)
|
||||
{
|
||||
environ = env + 1;
|
||||
free(env[0]);
|
||||
}
|
||||
#endif /* ! USE_LOCALTIME_RZ */
|
||||
|
||||
/* A UTC time zone, and its initializer. */
|
||||
static timezone_t gmtz;
|
||||
static void
|
||||
gmtzinit(void)
|
||||
{
|
||||
if (USE_LOCALTIME_RZ) {
|
||||
static char const utc[] = "UTC0";
|
||||
gmtz = tzalloc(utc);
|
||||
if (!gmtz) {
|
||||
perror(utc);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert *TP to UTC, 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 *
|
||||
my_gmtime_r(time_t *tp, struct tm *tmp)
|
||||
{
|
||||
return USE_LOCALTIME_RZ ? localtime_rz(gmtz, tp, tmp) : gmtime_r(tp, tmp);
|
||||
}
|
||||
|
||||
#ifndef TYPECHECK
|
||||
#define my_localtime localtime
|
||||
# define my_localtime_rz localtime_rz
|
||||
#else /* !defined TYPECHECK */
|
||||
static struct tm *
|
||||
my_localtime(time_t *tp)
|
||||
{
|
||||
register struct tm * tmp;
|
||||
|
||||
tmp = localtime(tp);
|
||||
if (tp != NULL && tmp != NULL) {
|
||||
static struct tm *
|
||||
my_localtime_rz(timezone_t tz, time_t *tp, struct tm *tmp)
|
||||
{
|
||||
tmp = localtime_rz(tz, tp, tmp);
|
||||
if (tmp) {
|
||||
struct tm tm;
|
||||
register time_t t;
|
||||
|
||||
tm = *tmp;
|
||||
t = mktime(&tm);
|
||||
t = mktime_z(tz, &tm);
|
||||
if (t != *tp) {
|
||||
(void) fflush(stdout);
|
||||
(void) fprintf(stderr, "\n%s: ", progname);
|
||||
(void) fprintf(stderr, tformat(), *tp);
|
||||
(void) fprintf(stderr, " ->");
|
||||
(void) fprintf(stderr, " year=%d", tmp->tm_year);
|
||||
(void) fprintf(stderr, " mon=%d", tmp->tm_mon);
|
||||
(void) fprintf(stderr, " mday=%d", tmp->tm_mday);
|
||||
(void) fprintf(stderr, " hour=%d", tmp->tm_hour);
|
||||
(void) fprintf(stderr, " min=%d", tmp->tm_min);
|
||||
(void) fprintf(stderr, " sec=%d", tmp->tm_sec);
|
||||
(void) fprintf(stderr, " isdst=%d", tmp->tm_isdst);
|
||||
(void) fprintf(stderr, " -> ");
|
||||
(void) fprintf(stderr, tformat(), t);
|
||||
(void) fprintf(stderr, "\n");
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "\n%s: ", progname);
|
||||
fprintf(stderr, tformat(), *tp);
|
||||
fprintf(stderr, " ->");
|
||||
fprintf(stderr, " year=%d", tmp->tm_year);
|
||||
fprintf(stderr, " mon=%d", tmp->tm_mon);
|
||||
fprintf(stderr, " mday=%d", tmp->tm_mday);
|
||||
fprintf(stderr, " hour=%d", tmp->tm_hour);
|
||||
fprintf(stderr, " min=%d", tmp->tm_min);
|
||||
fprintf(stderr, " sec=%d", tmp->tm_sec);
|
||||
fprintf(stderr, " isdst=%d", tmp->tm_isdst);
|
||||
fprintf(stderr, " -> ");
|
||||
fprintf(stderr, tformat(), t);
|
||||
fprintf(stderr, "\n");
|
||||
errout = true;
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
@ -275,88 +488,124 @@ abbrok(const char *const abbrp, const char *const zone)
|
||||
if (warned)
|
||||
return;
|
||||
cp = abbrp;
|
||||
wp = NULL;
|
||||
while (isascii((unsigned char) *cp) && isalpha((unsigned char) *cp))
|
||||
while (is_alpha(*cp) || is_digit(*cp) || *cp == '-' || *cp == '+')
|
||||
++cp;
|
||||
if (cp - abbrp == 0)
|
||||
wp = _("lacks alphabetic at start");
|
||||
else if (cp - abbrp < 3)
|
||||
wp = _("has fewer than 3 alphabetics");
|
||||
if (cp - abbrp < 3)
|
||||
wp = _("has fewer than 3 characters");
|
||||
else if (cp - abbrp > 6)
|
||||
wp = _("has more than 6 alphabetics");
|
||||
if (wp == NULL && (*cp == '+' || *cp == '-')) {
|
||||
++cp;
|
||||
if (isascii((unsigned char) *cp) &&
|
||||
isdigit((unsigned char) *cp))
|
||||
if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
|
||||
++cp;
|
||||
if (*cp != '\0')
|
||||
wp = _("differs from POSIX standard");
|
||||
}
|
||||
if (wp == NULL)
|
||||
return;
|
||||
(void) fflush(stdout);
|
||||
(void) fprintf(stderr,
|
||||
wp = _("has more than 6 characters");
|
||||
else if (*cp)
|
||||
wp = _("has characters other than ASCII alphanumerics, '-' or '+'");
|
||||
else
|
||||
return;
|
||||
fflush(stdout);
|
||||
fprintf(stderr,
|
||||
_("%s: warning: zone \"%s\" abbreviation \"%s\" %s\n"),
|
||||
progname, zone, abbrp, wp);
|
||||
warned = TRUE;
|
||||
warned = errout = true;
|
||||
}
|
||||
|
||||
/* Return a time zone abbreviation. If the abbreviation needs to be
|
||||
saved, use *BUF (of size *BUFALLOC) to save it, and return the
|
||||
abbreviation in the possibly-reallocated *BUF. Otherwise, just
|
||||
return the abbreviation. Get the abbreviation from TMP.
|
||||
Exit on memory allocation failure. */
|
||||
static char const *
|
||||
saveabbr(char **buf, size_t *bufalloc, struct tm const *tmp)
|
||||
{
|
||||
char const *ab = abbr(tmp);
|
||||
if (HAVE_LOCALTIME_RZ)
|
||||
return ab;
|
||||
else {
|
||||
size_t ablen = strlen(ab);
|
||||
if (*bufalloc <= ablen) {
|
||||
free(*buf);
|
||||
|
||||
/* Make the new buffer at least twice as long as the old,
|
||||
to avoid O(N**2) behavior on repeated calls. */
|
||||
*bufalloc = sumsize(*bufalloc, ablen + 1);
|
||||
|
||||
*buf = malloc(*bufalloc);
|
||||
if (! *buf) {
|
||||
perror(progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return strcpy(*buf, ab);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
close_file(FILE *stream)
|
||||
{
|
||||
char const *e = (ferror(stream) ? _("I/O error")
|
||||
: fclose(stream) != 0 ? strerror(errno) : NULL);
|
||||
if (e) {
|
||||
fprintf(stderr, "%s: %s\n", progname, e);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(FILE * const stream, const int status)
|
||||
{
|
||||
(void) fprintf(stream,
|
||||
fprintf(stream,
|
||||
_("%s: usage: %s [--version] [--help] [-{vV}] [-{ct} [lo,]hi] zonename ...\n"
|
||||
"\n"
|
||||
"Report bugs to %s.\n"),
|
||||
progname, progname, REPORT_BUGS_TO);
|
||||
if (status == EXIT_SUCCESS)
|
||||
close_file(stream);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
/* These are static so that they're initially zero. */
|
||||
static char * abbrev;
|
||||
static size_t abbrevsize;
|
||||
static struct tm newtm;
|
||||
|
||||
register int i;
|
||||
register int vflag;
|
||||
register int Vflag;
|
||||
register bool vflag;
|
||||
register bool Vflag;
|
||||
register char * cutarg;
|
||||
register char * cuttimes;
|
||||
register time_t cutlotime;
|
||||
register time_t cuthitime;
|
||||
register char ** fakeenv;
|
||||
time_t now;
|
||||
time_t t;
|
||||
time_t newt;
|
||||
struct tm tm;
|
||||
struct tm newtm;
|
||||
register struct tm * tmp;
|
||||
register struct tm * newtmp;
|
||||
|
||||
cutlotime = absolute_min_time;
|
||||
cuthitime = absolute_max_time;
|
||||
#if HAVE_GETTEXT
|
||||
(void) setlocale(LC_ALL, "");
|
||||
setlocale(LC_ALL, "");
|
||||
#ifdef TZ_DOMAINDIR
|
||||
(void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
|
||||
bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
|
||||
#endif /* defined TEXTDOMAINDIR */
|
||||
(void) textdomain(TZ_DOMAIN);
|
||||
textdomain(TZ_DOMAIN);
|
||||
#endif /* HAVE_GETTEXT */
|
||||
progname = argv[0];
|
||||
for (i = 1; i < argc; ++i)
|
||||
if (strcmp(argv[i], "--version") == 0) {
|
||||
(void) printf("zdump %s%s\n", PKGVERSION, TZVERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
printf("zdump %s%s\n", PKGVERSION, TZVERSION);
|
||||
return EXIT_SUCCESS;
|
||||
} else if (strcmp(argv[i], "--help") == 0) {
|
||||
usage(stdout, EXIT_SUCCESS);
|
||||
}
|
||||
vflag = Vflag = 0;
|
||||
vflag = Vflag = false;
|
||||
cutarg = cuttimes = NULL;
|
||||
for (;;)
|
||||
switch (getopt(argc, argv, "c:t:vV")) {
|
||||
case 'c': cutarg = optarg; break;
|
||||
case 't': cuttimes = optarg; break;
|
||||
case 'v': vflag = 1; break;
|
||||
case 'V': Vflag = 1; break;
|
||||
case 'v': vflag = true; break;
|
||||
case 'V': Vflag = true; break;
|
||||
case -1:
|
||||
if (! (optind == argc - 1 && strcmp(argv[optind], "=") == 0))
|
||||
goto arg_processing_done;
|
||||
@ -383,9 +632,9 @@ main(int argc, char *argv[])
|
||||
cutloyear = lo;
|
||||
cuthiyear = hi;
|
||||
} else {
|
||||
(void) fprintf(stderr, _("%s: wild -c argument %s\n"),
|
||||
fprintf(stderr, _("%s: wild -c argument %s\n"),
|
||||
progname, cutarg);
|
||||
exit(EXIT_FAILURE);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
if (cutarg != NULL || cuttimes == NULL) {
|
||||
@ -415,81 +664,61 @@ main(int argc, char *argv[])
|
||||
cuthitime = hi;
|
||||
}
|
||||
} else {
|
||||
(void) fprintf(stderr,
|
||||
fprintf(stderr,
|
||||
_("%s: wild -t argument %s\n"),
|
||||
progname, cuttimes);
|
||||
exit(EXIT_FAILURE);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
(void) time(&now);
|
||||
gmtzinit();
|
||||
now = time(NULL);
|
||||
longest = 0;
|
||||
for (i = optind; i < argc; ++i)
|
||||
if (strlen(argv[i]) > longest)
|
||||
longest = strlen(argv[i]);
|
||||
{
|
||||
register int from;
|
||||
register int to;
|
||||
|
||||
for (i = 0; environ[i] != NULL; ++i)
|
||||
continue;
|
||||
fakeenv = malloc((i + 2) * sizeof *fakeenv);
|
||||
if (fakeenv == NULL
|
||||
|| (fakeenv[0] = malloc(longest + 4)) == NULL) {
|
||||
(void) perror(progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
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;
|
||||
for (i = optind; i < argc; i++) {
|
||||
size_t arglen = strlen(argv[i]);
|
||||
if (longest < arglen)
|
||||
longest = arglen < INT_MAX ? arglen : INT_MAX;
|
||||
}
|
||||
for (i = optind; i < argc; ++i) {
|
||||
static char buf[MAX_STRING_LENGTH];
|
||||
|
||||
(void) strcpy(&fakeenv[0][3], argv[i]);
|
||||
for (i = optind; i < argc; ++i) {
|
||||
timezone_t tz = tzalloc(argv[i]);
|
||||
char const *ab;
|
||||
if (!tz) {
|
||||
perror(argv[i]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (! (vflag | Vflag)) {
|
||||
show(argv[i], now, FALSE);
|
||||
show(tz, argv[i], now, false);
|
||||
tzfree(tz);
|
||||
continue;
|
||||
}
|
||||
warned = FALSE;
|
||||
warned = false;
|
||||
t = absolute_min_time;
|
||||
if (!Vflag) {
|
||||
show(argv[i], t, TRUE);
|
||||
show(tz, argv[i], t, true);
|
||||
t += SECSPERDAY;
|
||||
show(argv[i], t, TRUE);
|
||||
show(tz, argv[i], t, true);
|
||||
}
|
||||
if (t < cutlotime)
|
||||
t = cutlotime;
|
||||
tmp = my_localtime(&t);
|
||||
if (tmp != NULL) {
|
||||
tm = *tmp;
|
||||
(void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
|
||||
}
|
||||
for ( ; ; ) {
|
||||
newt = (t < absolute_max_time - SECSPERDAY / 2
|
||||
tmp = my_localtime_rz(tz, &t, &tm);
|
||||
if (tmp)
|
||||
ab = saveabbr(&abbrev, &abbrevsize, &tm);
|
||||
while (t < cuthitime) {
|
||||
newt = ((t < absolute_max_time - SECSPERDAY / 2
|
||||
&& t + SECSPERDAY / 2 < cuthitime)
|
||||
? t + SECSPERDAY / 2
|
||||
: absolute_max_time);
|
||||
if (cuthitime <= newt)
|
||||
break;
|
||||
newtmp = localtime(&newt);
|
||||
if (newtmp != NULL)
|
||||
newtm = *newtmp;
|
||||
: cuthitime);
|
||||
newtmp = localtime_rz(tz, &newt, &newtm);
|
||||
if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) :
|
||||
(delta(&newtm, &tm) != (newt - t) ||
|
||||
newtm.tm_isdst != tm.tm_isdst ||
|
||||
strcmp(abbr(&newtm), buf) != 0)) {
|
||||
newt = hunt(argv[i], t, newt);
|
||||
newtmp = localtime(&newt);
|
||||
if (newtmp != NULL) {
|
||||
newtm = *newtmp;
|
||||
(void) strncpy(buf,
|
||||
abbr(&newtm),
|
||||
(sizeof buf) - 1);
|
||||
}
|
||||
strcmp(abbr(&newtm), ab) != 0)) {
|
||||
newt = hunt(tz, argv[i], t, newt);
|
||||
newtmp = localtime_rz(tz, &newt, &newtm);
|
||||
if (newtmp)
|
||||
ab = saveabbr(&abbrev, &abbrevsize,
|
||||
&newtm);
|
||||
}
|
||||
t = newt;
|
||||
tm = newtm;
|
||||
@ -498,23 +727,20 @@ main(int argc, char *argv[])
|
||||
if (!Vflag) {
|
||||
t = absolute_max_time;
|
||||
t -= SECSPERDAY;
|
||||
show(argv[i], t, TRUE);
|
||||
show(tz, argv[i], t, true);
|
||||
t += SECSPERDAY;
|
||||
show(argv[i], t, TRUE);
|
||||
show(tz, argv[i], t, true);
|
||||
}
|
||||
tzfree(tz);
|
||||
}
|
||||
if (fflush(stdout) || ferror(stdout)) {
|
||||
(void) fprintf(stderr, "%s: ", progname);
|
||||
(void) perror(_("Error writing to standard output"));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
/* If exit fails to exit... */
|
||||
return EXIT_FAILURE;
|
||||
close_file(stdout);
|
||||
if (errout && (ferror(stderr) || fclose(stderr) != 0))
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static time_t
|
||||
yeartot(const intmax_t y)
|
||||
yeartot(intmax_t y)
|
||||
{
|
||||
register intmax_t myy, seconds, years;
|
||||
register time_t t;
|
||||
@ -557,20 +783,20 @@ yeartot(const intmax_t y)
|
||||
}
|
||||
|
||||
static time_t
|
||||
hunt(char *name, time_t lot, time_t hit)
|
||||
hunt(timezone_t tz, char *name, time_t lot, time_t hit)
|
||||
{
|
||||
static char * loab;
|
||||
static size_t loabsize;
|
||||
char const * ab;
|
||||
time_t t;
|
||||
struct tm lotm;
|
||||
register struct tm * lotmp;
|
||||
struct tm tm;
|
||||
register struct tm * tmp;
|
||||
char loab[MAX_STRING_LENGTH];
|
||||
|
||||
lotmp = my_localtime(&lot);
|
||||
if (lotmp != NULL) {
|
||||
lotm = *lotmp;
|
||||
(void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
|
||||
}
|
||||
lotmp = my_localtime_rz(tz, &lot, &lotm);
|
||||
if (lotmp)
|
||||
ab = saveabbr(&loab, &loabsize, &lotm);
|
||||
for ( ; ; ) {
|
||||
time_t diff = hit - lot;
|
||||
if (diff < 2)
|
||||
@ -581,20 +807,18 @@ hunt(char *name, time_t lot, time_t hit)
|
||||
++t;
|
||||
else if (t >= hit)
|
||||
--t;
|
||||
tmp = my_localtime(&t);
|
||||
if (tmp != NULL)
|
||||
tm = *tmp;
|
||||
tmp = my_localtime_rz(tz, &t, &tm);
|
||||
if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) :
|
||||
(delta(&tm, &lotm) == (t - lot) &&
|
||||
tm.tm_isdst == lotm.tm_isdst &&
|
||||
strcmp(abbr(&tm), loab) == 0)) {
|
||||
strcmp(abbr(&tm), ab) == 0)) {
|
||||
lot = t;
|
||||
lotm = tm;
|
||||
lotmp = tmp;
|
||||
} else hit = t;
|
||||
}
|
||||
show(name, lot, TRUE);
|
||||
show(name, hit, TRUE);
|
||||
show(tz, name, lot, true);
|
||||
show(tz, name, hit, true);
|
||||
return hit;
|
||||
}
|
||||
|
||||
@ -623,49 +847,87 @@ delta(struct tm * newp, struct tm *oldp)
|
||||
return result;
|
||||
}
|
||||
|
||||
#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. */
|
||||
static int
|
||||
adjusted_yday(struct tm const *a, struct tm const *b)
|
||||
{
|
||||
int yday = a->tm_yday;
|
||||
if (b->tm_year < a->tm_year)
|
||||
yday += 365 + isleap_sum(b->tm_year, TM_YEAR_BASE);
|
||||
return yday;
|
||||
}
|
||||
#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
|
||||
offsets are east of Greenwich. On failure, return LONG_MIN. */
|
||||
static long
|
||||
gmtoff(struct tm const *a, struct tm const *b)
|
||||
{
|
||||
#ifdef TM_GMTOFF
|
||||
return a->TM_GMTOFF;
|
||||
#else
|
||||
if (! b)
|
||||
return LONG_MIN;
|
||||
else {
|
||||
int ayday = adjusted_yday(a, b);
|
||||
int byday = adjusted_yday(b, a);
|
||||
int days = ayday - byday;
|
||||
long hours = a->tm_hour - b->tm_hour + 24 * days;
|
||||
long minutes = a->tm_min - b->tm_min + 60 * hours;
|
||||
long seconds = a->tm_sec - b->tm_sec + 60 * minutes;
|
||||
return seconds;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
show(char *zone, time_t t, int v)
|
||||
show(timezone_t tz, char *zone, time_t t, bool v)
|
||||
{
|
||||
register struct tm * tmp;
|
||||
register struct tm * gmtmp;
|
||||
struct tm tm, gmtm;
|
||||
|
||||
(void) printf("%-*s ", (int) longest, zone);
|
||||
printf("%-*s ", longest, zone);
|
||||
if (v) {
|
||||
tmp = gmtime(&t);
|
||||
if (tmp == NULL) {
|
||||
(void) printf(tformat(), t);
|
||||
gmtmp = my_gmtime_r(&t, &gmtm);
|
||||
if (gmtmp == NULL) {
|
||||
printf(tformat(), t);
|
||||
} else {
|
||||
dumptime(tmp);
|
||||
(void) printf(" UT");
|
||||
dumptime(gmtmp);
|
||||
printf(" UT");
|
||||
}
|
||||
(void) printf(" = ");
|
||||
printf(" = ");
|
||||
}
|
||||
tmp = my_localtime(&t);
|
||||
tmp = my_localtime_rz(tz, &t, &tm);
|
||||
dumptime(tmp);
|
||||
if (tmp != NULL) {
|
||||
if (*abbr(tmp) != '\0')
|
||||
(void) printf(" %s", abbr(tmp));
|
||||
printf(" %s", abbr(tmp));
|
||||
if (v) {
|
||||
(void) printf(" isdst=%d", tmp->tm_isdst);
|
||||
#ifdef TM_GMTOFF
|
||||
(void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
|
||||
#endif /* defined TM_GMTOFF */
|
||||
long off = gmtoff(tmp, gmtmp);
|
||||
printf(" isdst=%d", tmp->tm_isdst);
|
||||
if (off != LONG_MIN)
|
||||
printf(" gmtoff=%ld", off);
|
||||
}
|
||||
}
|
||||
(void) printf("\n");
|
||||
printf("\n");
|
||||
if (tmp != NULL && *abbr(tmp) != '\0')
|
||||
abbrok(abbr(tmp), zone);
|
||||
}
|
||||
|
||||
static char *
|
||||
abbr(struct tm *tmp)
|
||||
static char const *
|
||||
abbr(struct tm const *tmp)
|
||||
{
|
||||
register char * result;
|
||||
static char nada;
|
||||
|
||||
if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
|
||||
return &nada;
|
||||
result = tzname[tmp->tm_isdst];
|
||||
return (result == NULL) ? &nada : result;
|
||||
#ifdef TM_ZONE
|
||||
return tmp->TM_ZONE;
|
||||
#else
|
||||
return (0 <= tmp->tm_isdst && tzname[0 < tmp->tm_isdst]
|
||||
? tzname[0 < tmp->tm_isdst]
|
||||
: "");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -712,11 +974,11 @@ dumptime(register const struct tm *timeptr)
|
||||
register int trail;
|
||||
|
||||
if (timeptr == NULL) {
|
||||
(void) printf("NULL");
|
||||
printf("NULL");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
** The packaged versions of localtime and gmtime never put out-of-range
|
||||
** The packaged localtime_rz and gmtime_r never put out-of-range
|
||||
** values in tm_wday or tm_mon, but since this code might be compiled
|
||||
** with other (perhaps experimental) versions, paranoia is in order.
|
||||
*/
|
||||
@ -728,7 +990,7 @@ dumptime(register const struct tm *timeptr)
|
||||
(int) (sizeof mon_name / sizeof mon_name[0]))
|
||||
mn = "???";
|
||||
else mn = mon_name[timeptr->tm_mon];
|
||||
(void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
|
||||
printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
|
||||
wn, mn,
|
||||
timeptr->tm_mday, timeptr->tm_hour,
|
||||
timeptr->tm_min, timeptr->tm_sec);
|
||||
@ -745,6 +1007,6 @@ dumptime(register const struct tm *timeptr)
|
||||
++lead;
|
||||
}
|
||||
if (lead == 0)
|
||||
(void) printf("%d", trail);
|
||||
else (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail));
|
||||
printf("%d", trail);
|
||||
else printf("%d%d", lead, ((trail < 0) ? -trail : trail));
|
||||
}
|
||||
|
1063
timezone/zic.c
1063
timezone/zic.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user