aboutsummaryrefslogtreecommitdiff
path: root/REORG.TODO/time
diff options
context:
space:
mode:
Diffstat (limited to 'REORG.TODO/time')
-rw-r--r--REORG.TODO/time/Depend1
-rw-r--r--REORG.TODO/time/Makefile75
-rw-r--r--REORG.TODO/time/Versions68
-rw-r--r--REORG.TODO/time/adjtime.c33
-rw-r--r--REORG.TODO/time/alt_digit.c193
-rw-r--r--REORG.TODO/time/asctime.c89
-rw-r--r--REORG.TODO/time/bits/types/clock_t.h9
-rw-r--r--REORG.TODO/time/bits/types/clockid_t.h9
-rw-r--r--REORG.TODO/time/bits/types/struct_itimerspec.h14
-rw-r--r--REORG.TODO/time/bits/types/struct_timespec.h14
-rw-r--r--REORG.TODO/time/bits/types/struct_timeval.h13
-rw-r--r--REORG.TODO/time/bits/types/struct_tm.h28
-rw-r--r--REORG.TODO/time/bits/types/time_t.h9
-rw-r--r--REORG.TODO/time/bits/types/timer_t.h9
-rw-r--r--REORG.TODO/time/bug-asctime.c33
-rw-r--r--REORG.TODO/time/bug-asctime_r.c32
-rw-r--r--REORG.TODO/time/bug-getdate1.c152
-rw-r--r--REORG.TODO/time/bug-mktime1.c17
-rw-r--r--REORG.TODO/time/clock.c30
-rw-r--r--REORG.TODO/time/clocktest.c37
-rw-r--r--REORG.TODO/time/ctime.c28
-rw-r--r--REORG.TODO/time/ctime_r.c29
-rw-r--r--REORG.TODO/time/datemsk2
-rw-r--r--REORG.TODO/time/difftime.c121
-rw-r--r--REORG.TODO/time/dysize.c24
-rw-r--r--REORG.TODO/time/era.c177
-rw-r--r--REORG.TODO/time/ftime.c41
-rw-r--r--REORG.TODO/time/getdate.c312
-rw-r--r--REORG.TODO/time/getitimer.c38
-rw-r--r--REORG.TODO/time/gettimeofday.c34
-rw-r--r--REORG.TODO/time/gmtime.c37
-rw-r--r--REORG.TODO/time/lc-time-cleanup.c37
-rw-r--r--REORG.TODO/time/localtime.c41
-rw-r--r--REORG.TODO/time/mktime.c741
-rw-r--r--REORG.TODO/time/offtime.c86
-rw-r--r--REORG.TODO/time/setitimer.c40
-rw-r--r--REORG.TODO/time/settimeofday.c31
-rw-r--r--REORG.TODO/time/stime.c37
-rw-r--r--REORG.TODO/time/strftime.c27
-rw-r--r--REORG.TODO/time/strftime_l.c1425
-rw-r--r--REORG.TODO/time/strptime.c34
-rw-r--r--REORG.TODO/time/strptime_l.c1211
-rw-r--r--REORG.TODO/time/sys/time.h188
-rw-r--r--REORG.TODO/time/sys/timeb.h43
-rw-r--r--REORG.TODO/time/test_time.c115
-rw-r--r--REORG.TODO/time/time.c33
-rw-r--r--REORG.TODO/time/time.h309
-rw-r--r--REORG.TODO/time/timegm.c47
-rw-r--r--REORG.TODO/time/timespec_get.c37
-rw-r--r--REORG.TODO/time/tst-ftime.c59
-rw-r--r--REORG.TODO/time/tst-ftime_l.c129
-rw-r--r--REORG.TODO/time/tst-getdate.c126
-rw-r--r--REORG.TODO/time/tst-mktime.c73
-rw-r--r--REORG.TODO/time/tst-mktime2.c158
-rw-r--r--REORG.TODO/time/tst-mktime3.c53
-rw-r--r--REORG.TODO/time/tst-posixtz.c123
-rw-r--r--REORG.TODO/time/tst-strftime.c161
-rw-r--r--REORG.TODO/time/tst-strptime-whitespace.c43
-rw-r--r--REORG.TODO/time/tst-strptime.c199
-rw-r--r--REORG.TODO/time/tst-strptime2.c235
-rw-r--r--REORG.TODO/time/tst-strptime3.c55
-rw-r--r--REORG.TODO/time/tst-tzname.c50
-rw-r--r--REORG.TODO/time/tst_wcsftime.c28
-rw-r--r--REORG.TODO/time/tzfile.c832
-rw-r--r--REORG.TODO/time/tzset.c632
-rw-r--r--REORG.TODO/time/wcsftime.c28
-rw-r--r--REORG.TODO/time/wcsftime_l.c25
67 files changed, 9199 insertions, 0 deletions
diff --git a/REORG.TODO/time/Depend b/REORG.TODO/time/Depend
new file mode 100644
index 0000000000..79b246903c
--- /dev/null
+++ b/REORG.TODO/time/Depend
@@ -0,0 +1 @@
+timezone
diff --git a/REORG.TODO/time/Makefile b/REORG.TODO/time/Makefile
new file mode 100644
index 0000000000..317c4d8901
--- /dev/null
+++ b/REORG.TODO/time/Makefile
@@ -0,0 +1,75 @@
+# Copyright (C) 1991-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+#
+# Makefile for time routines
+#
+subdir := time
+
+include ../Makeconfig
+
+headers := time.h sys/time.h sys/timeb.h bits/time.h \
+ bits/types/clockid_t.h bits/types/clock_t.h \
+ bits/types/struct_itimerspec.h \
+ bits/types/struct_timespec.h bits/types/struct_timeval.h \
+ bits/types/struct_tm.h bits/types/timer_t.h \
+ bits/types/time_t.h
+
+routines := offtime asctime clock ctime ctime_r difftime \
+ gmtime localtime mktime time \
+ gettimeofday settimeofday adjtime tzset \
+ tzfile getitimer setitimer \
+ stime dysize timegm ftime \
+ getdate strptime strptime_l \
+ strftime wcsftime strftime_l wcsftime_l \
+ timespec_get
+aux := era alt_digit lc-time-cleanup
+
+tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
+ tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
+ tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \
+ tst-strptime3 bug-getdate1 tst-strptime-whitespace tst-ftime \
+ tst-tzname
+
+include ../Rules
+
+ifeq ($(run-built-tests),yes)
+LOCALES := de_DE.ISO-8859-1 en_US.ISO-8859-1 ja_JP.EUC-JP
+include ../gen-locales.mk
+
+$(objpfx)tst-ftime_l.out: $(gen-locales)
+$(objpfx)tst-strptime.out: $(gen-locales)
+endif
+
+tz-cflags = -DTZDIR='"$(zonedir)"' \
+ -DTZDEFAULT='"$(localtime-file)"' \
+ -DTZDEFRULES='"$(posixrules-file)"'
+
+CFLAGS-tzfile.c = $(tz-cflags)
+CFLAGS-tzset.c = $(tz-cflags)
+CFLAGS-getdate.c = -fexceptions
+
+# Don't warn about Y2k problem in strftime format string.
+CFLAGS-test_time.c = -Wno-format
+
+tst-getdate-ENV= DATEMSK=datemsk TZDIR=${common-objpfx}timezone/testdata
+test_time-ARGS= EST5EDT CST
+
+tst-tzname-ENV = TZDIR=${common-objpfx}timezone/testdata
+CPPFLAGS-tst-tzname.c = -DTZDEFRULES='"$(posixrules-file)"'
+
+bug-getdate1-ARGS = ${objpfx}bug-getdate1-fmt
diff --git a/REORG.TODO/time/Versions b/REORG.TODO/time/Versions
new file mode 100644
index 0000000000..fd838181e4
--- /dev/null
+++ b/REORG.TODO/time/Versions
@@ -0,0 +1,68 @@
+libc {
+ GLIBC_2.0 {
+ # global variables
+ __daylight; __timezone; __tzname;
+
+ # functions with special/multiple interfaces
+ __adjtimex;
+
+ # functions used in other libraries
+ __gmtime_r; __gettimeofday;
+
+ # variables in normal name space
+ daylight; timezone; tzname;
+
+ # a*
+ adjtime; adjtimex; asctime; asctime_r;
+
+ # c*
+ clock; ctime; ctime_r;
+
+ # d*
+ difftime; dysize;
+
+ # f*
+ ftime;
+
+ # g*
+ getitimer; gettimeofday; gmtime; gmtime_r;
+
+ # l*
+ localtime; localtime_r;
+
+ # m*
+ mktime;
+
+ # s*
+ setitimer; settimeofday; stime; strftime; strptime;
+
+ # t*
+ time; timegm; timelocal; tzset;
+ }
+ GLIBC_2.1 {
+ # variables in normal name space
+ getdate_err;
+
+ # g*
+ getdate; getdate_r;
+ }
+ GLIBC_2.2 {
+ # w*
+ wcsftime;
+ }
+ GLIBC_2.3 {
+ # these internal names are used by libstdc++
+ __strftime_l; __wcsftime_l;
+
+ # s*
+ strftime_l;
+ # w*
+ wcsftime_l;
+ }
+ GLIBC_2.3.2 {
+ strptime_l;
+ }
+ GLIBC_2.16 {
+ timespec_get;
+ }
+}
diff --git a/REORG.TODO/time/adjtime.c b/REORG.TODO/time/adjtime.c
new file mode 100644
index 0000000000..180bf48e13
--- /dev/null
+++ b/REORG.TODO/time/adjtime.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sys/time.h>
+
+/* Adjust the current time of day by the amount in DELTA.
+ If OLDDELTA is not NULL, it is filled in with the amount
+ of time adjustment remaining to be done from the last `__adjtime' call.
+ This call is restricted to the super-user. */
+int
+__adjtime (const struct timeval *delta, struct timeval *olddelta)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (adjtime)
+
+weak_alias (__adjtime, adjtime)
diff --git a/REORG.TODO/time/alt_digit.c b/REORG.TODO/time/alt_digit.c
new file mode 100644
index 0000000000..e3bcea4414
--- /dev/null
+++ b/REORG.TODO/time/alt_digit.c
@@ -0,0 +1,193 @@
+/* Helper functions used by strftime/strptime to handle alternate digits.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "../locale/localeinfo.h"
+#include <libc-lock.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdint.h>
+
+/* Some of the functions here must not be used while setlocale is called. */
+__libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
+
+#define CURRENT(item) (current->values[_NL_ITEM_INDEX (item)].string)
+#define CURRENT_WSTR(item) \
+ ((wchar_t *) current->values[_NL_ITEM_INDEX (item)].wstr)
+
+static void
+_nl_init_alt_digit (struct __locale_data *current)
+{
+ struct lc_time_data *data;
+
+ if (current->private.time == NULL)
+ {
+ current->private.time = malloc (sizeof *current->private.time);
+ if (current->private.time == NULL)
+ return;
+ memset (current->private.time, 0, sizeof *current->private.time);
+ current->private.cleanup = &_nl_cleanup_time;
+ }
+ data = current->private.time;
+
+ if (! data->alt_digits_initialized)
+ {
+ const char *ptr = CURRENT (ALT_DIGITS);
+ size_t cnt;
+
+ data->alt_digits_initialized = 1;
+
+ if (ptr != NULL)
+ {
+ data->alt_digits = malloc (100 * sizeof (const char *));
+ if (data->alt_digits != NULL)
+ for (cnt = 0; cnt < 100; ++cnt)
+ {
+ data->alt_digits[cnt] = ptr;
+
+ /* Skip digit format. */
+ ptr = strchr (ptr, '\0') + 1;
+ }
+ }
+ }
+
+}
+
+const char *
+internal_function
+_nl_get_alt_digit (unsigned int number, struct __locale_data *current)
+{
+ const char *result;
+
+ if (number >= 100 || CURRENT (ALT_DIGITS)[0] == '\0')
+ return NULL;
+
+ __libc_rwlock_wrlock (__libc_setlocale_lock);
+
+ if (current->private.time == NULL
+ || ! current->private.time->alt_digits_initialized)
+ _nl_init_alt_digit (current);
+
+ result = ((current->private.time != NULL
+ && current->private.time->alt_digits != NULL)
+ ? current->private.time->alt_digits[number]
+ : NULL);
+
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+
+ return result;
+}
+
+
+const wchar_t *
+internal_function
+_nl_get_walt_digit (unsigned int number, struct __locale_data *current)
+{
+ const wchar_t *result = NULL;
+ struct lc_time_data *data;
+
+ if (number >= 100 || CURRENT_WSTR (_NL_WALT_DIGITS)[0] == L'\0')
+ return NULL;
+
+ __libc_rwlock_wrlock (__libc_setlocale_lock);
+
+ if (current->private.time == NULL)
+ {
+ current->private.time = malloc (sizeof *current->private.time);
+ if (current->private.time == NULL)
+ goto out;
+ memset (current->private.time, 0, sizeof *current->private.time);
+ current->private.cleanup = &_nl_cleanup_time;
+ }
+ data = current->private.time;
+
+ if (! data->walt_digits_initialized)
+ {
+ const wchar_t *ptr = CURRENT_WSTR (_NL_WALT_DIGITS);
+ size_t cnt;
+
+ data->walt_digits_initialized = 1;
+
+ if (ptr != NULL)
+ {
+ data->walt_digits = malloc (100 * sizeof (const uint32_t *));
+ if (data->walt_digits != NULL)
+ for (cnt = 0; cnt < 100; ++cnt)
+ {
+ data->walt_digits[cnt] = ptr;
+
+ /* Skip digit format. */
+ ptr = __wcschr (ptr, L'\0') + 1;
+ }
+ }
+ }
+
+ if (data->walt_digits != NULL)
+ result = data->walt_digits[number];
+
+ out:
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+
+ return (wchar_t *) result;
+}
+
+
+int
+internal_function
+_nl_parse_alt_digit (const char **strp, struct __locale_data *current)
+{
+ const char *str = *strp;
+ int result = -1;
+ size_t cnt;
+ size_t maxlen = 0;
+
+ if (CURRENT_WSTR (_NL_WALT_DIGITS)[0] == L'\0')
+ return result;
+
+ __libc_rwlock_wrlock (__libc_setlocale_lock);
+
+ if (current->private.time == NULL
+ || ! current->private.time->alt_digits_initialized)
+ _nl_init_alt_digit (current);
+
+ if (current->private.time != NULL &&
+ current->private.time->alt_digits != NULL)
+ /* Matching is not unambiguous. The alternative digits could be like
+ I, II, III, ... and the first one is a substring of the second
+ and third. Therefore we must keep on searching until we found
+ the longest possible match. Note that this is not specified in
+ the standard. */
+ for (cnt = 0; cnt < 100; ++cnt)
+ {
+ const char *const dig = current->private.time->alt_digits[cnt];
+ size_t len = strlen (dig);
+
+ if (len > maxlen && strncmp (dig, str, len) == 0)
+ {
+ maxlen = len;
+ result = (int) cnt;
+ }
+ }
+
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+
+ if (result != -1)
+ *strp += maxlen;
+
+ return result;
+}
diff --git a/REORG.TODO/time/asctime.c b/REORG.TODO/time/asctime.c
new file mode 100644
index 0000000000..b57de7dc8b
--- /dev/null
+++ b/REORG.TODO/time/asctime.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "../locale/localeinfo.h"
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+
+/* This is defined in locale/C-time.c in the GNU libc. */
+extern const struct __locale_data _nl_C_LC_TIME attribute_hidden;
+#define ab_day_name(DAY) (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)+(DAY)].string)
+#define ab_month_name(MON) (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)+(MON)].string)
+
+static const char format[] = "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n";
+static char result[ 3+1+ 3+1+20+1+20+1+20+1+20+1+20+1 + 1];
+
+
+static char *
+asctime_internal (const struct tm *tp, char *buf, size_t buflen)
+{
+ if (tp == NULL)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ /* We limit the size of the year which can be printed. Using the %d
+ format specifier used the addition of 1900 would overflow the
+ number and a negative vaue is printed. For some architectures we
+ could in theory use %ld or an evern larger integer format but
+ this would mean the output needs more space. This would not be a
+ problem if the 'asctime_r' interface would be defined sanely and
+ a buffer size would be passed. */
+ if (__glibc_unlikely (tp->tm_year > INT_MAX - 1900))
+ {
+ eoverflow:
+ __set_errno (EOVERFLOW);
+ return NULL;
+ }
+
+ int n = __snprintf (buf, buflen, format,
+ (tp->tm_wday < 0 || tp->tm_wday >= 7 ?
+ "???" : ab_day_name (tp->tm_wday)),
+ (tp->tm_mon < 0 || tp->tm_mon >= 12 ?
+ "???" : ab_month_name (tp->tm_mon)),
+ tp->tm_mday, tp->tm_hour, tp->tm_min,
+ tp->tm_sec, 1900 + tp->tm_year);
+ if (n < 0)
+ return NULL;
+ if (n >= buflen)
+ goto eoverflow;
+
+ return buf;
+}
+
+
+/* Like asctime, but write result to the user supplied buffer. The
+ buffer is only guaranteed to be 26 bytes in length. */
+char *
+__asctime_r (const struct tm *tp, char *buf)
+{
+ return asctime_internal (tp, buf, 26);
+}
+weak_alias (__asctime_r, asctime_r)
+
+
+/* Returns a string of the form "Day Mon dd hh:mm:ss yyyy\n"
+ which is the representation of TP in that form. */
+char *
+asctime (const struct tm *tp)
+{
+ return asctime_internal (tp, result, sizeof (result));
+}
+libc_hidden_def (asctime)
diff --git a/REORG.TODO/time/bits/types/clock_t.h b/REORG.TODO/time/bits/types/clock_t.h
new file mode 100644
index 0000000000..ce97248f88
--- /dev/null
+++ b/REORG.TODO/time/bits/types/clock_t.h
@@ -0,0 +1,9 @@
+#ifndef __clock_t_defined
+#define __clock_t_defined 1
+
+#include <bits/types.h>
+
+/* Returned by `clock'. */
+typedef __clock_t clock_t;
+
+#endif
diff --git a/REORG.TODO/time/bits/types/clockid_t.h b/REORG.TODO/time/bits/types/clockid_t.h
new file mode 100644
index 0000000000..b17c7da853
--- /dev/null
+++ b/REORG.TODO/time/bits/types/clockid_t.h
@@ -0,0 +1,9 @@
+#ifndef __clockid_t_defined
+#define __clockid_t_defined 1
+
+#include <bits/types.h>
+
+/* Clock ID used in clock and timer functions. */
+typedef __clockid_t clockid_t;
+
+#endif
diff --git a/REORG.TODO/time/bits/types/struct_itimerspec.h b/REORG.TODO/time/bits/types/struct_itimerspec.h
new file mode 100644
index 0000000000..17cc1ac86d
--- /dev/null
+++ b/REORG.TODO/time/bits/types/struct_itimerspec.h
@@ -0,0 +1,14 @@
+#ifndef __itimerspec_defined
+#define __itimerspec_defined 1
+
+#include <bits/types.h>
+#include <bits/types/struct_timespec.h>
+
+/* POSIX.1b structure for timer start values and intervals. */
+struct itimerspec
+ {
+ struct timespec it_interval;
+ struct timespec it_value;
+ };
+
+#endif
diff --git a/REORG.TODO/time/bits/types/struct_timespec.h b/REORG.TODO/time/bits/types/struct_timespec.h
new file mode 100644
index 0000000000..644db9fdb6
--- /dev/null
+++ b/REORG.TODO/time/bits/types/struct_timespec.h
@@ -0,0 +1,14 @@
+#ifndef __timespec_defined
+#define __timespec_defined 1
+
+#include <bits/types.h>
+
+/* POSIX.1b structure for a time value. This is like a `struct timeval' but
+ has nanoseconds instead of microseconds. */
+struct timespec
+{
+ __time_t tv_sec; /* Seconds. */
+ __syscall_slong_t tv_nsec; /* Nanoseconds. */
+};
+
+#endif
diff --git a/REORG.TODO/time/bits/types/struct_timeval.h b/REORG.TODO/time/bits/types/struct_timeval.h
new file mode 100644
index 0000000000..70394ce886
--- /dev/null
+++ b/REORG.TODO/time/bits/types/struct_timeval.h
@@ -0,0 +1,13 @@
+#ifndef __timeval_defined
+#define __timeval_defined 1
+
+#include <bits/types.h>
+
+/* A time value that is accurate to the nearest
+ microsecond but also has a range of years. */
+struct timeval
+{
+ __time_t tv_sec; /* Seconds. */
+ __suseconds_t tv_usec; /* Microseconds. */
+};
+#endif
diff --git a/REORG.TODO/time/bits/types/struct_tm.h b/REORG.TODO/time/bits/types/struct_tm.h
new file mode 100644
index 0000000000..b13b631228
--- /dev/null
+++ b/REORG.TODO/time/bits/types/struct_tm.h
@@ -0,0 +1,28 @@
+#ifndef __struct_tm_defined
+#define __struct_tm_defined 1
+
+#include <bits/types.h>
+
+/* ISO C `broken-down time' structure. */
+struct tm
+{
+ int tm_sec; /* Seconds. [0-60] (1 leap second) */
+ int tm_min; /* Minutes. [0-59] */
+ int tm_hour; /* Hours. [0-23] */
+ int tm_mday; /* Day. [1-31] */
+ int tm_mon; /* Month. [0-11] */
+ int tm_year; /* Year - 1900. */
+ int tm_wday; /* Day of week. [0-6] */
+ int tm_yday; /* Days in year.[0-365] */
+ int tm_isdst; /* DST. [-1/0/1]*/
+
+# ifdef __USE_MISC
+ long int tm_gmtoff; /* Seconds east of UTC. */
+ const char *tm_zone; /* Timezone abbreviation. */
+# else
+ long int __tm_gmtoff; /* Seconds east of UTC. */
+ const char *__tm_zone; /* Timezone abbreviation. */
+# endif
+};
+
+#endif
diff --git a/REORG.TODO/time/bits/types/time_t.h b/REORG.TODO/time/bits/types/time_t.h
new file mode 100644
index 0000000000..ab8287c6fe
--- /dev/null
+++ b/REORG.TODO/time/bits/types/time_t.h
@@ -0,0 +1,9 @@
+#ifndef __time_t_defined
+#define __time_t_defined 1
+
+#include <bits/types.h>
+
+/* Returned by `time'. */
+typedef __time_t time_t;
+
+#endif
diff --git a/REORG.TODO/time/bits/types/timer_t.h b/REORG.TODO/time/bits/types/timer_t.h
new file mode 100644
index 0000000000..d71a4130e2
--- /dev/null
+++ b/REORG.TODO/time/bits/types/timer_t.h
@@ -0,0 +1,9 @@
+#ifndef __timer_t_defined
+#define __timer_t_defined 1
+
+#include <bits/types.h>
+
+/* Timer ID returned by `timer_create'. */
+typedef __timer_t timer_t;
+
+#endif
diff --git a/REORG.TODO/time/bug-asctime.c b/REORG.TODO/time/bug-asctime.c
new file mode 100644
index 0000000000..0b04b475a8
--- /dev/null
+++ b/REORG.TODO/time/bug-asctime.c
@@ -0,0 +1,33 @@
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+ time_t t = time (NULL);
+ struct tm *tp = localtime (&t);
+ tp->tm_year = INT_MAX;
+ errno = 0;
+ char *s = asctime (tp);
+ if (s != NULL || errno != EOVERFLOW)
+ {
+ puts ("asctime did not fail correctly");
+ result = 1;
+ }
+ char buf[1000];
+ errno = 0;
+ s = asctime_r (tp, buf);
+ if (s != NULL || errno != EOVERFLOW)
+ {
+ puts ("asctime_r did not fail correctly");
+ result = 1;
+ }
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/bug-asctime_r.c b/REORG.TODO/time/bug-asctime_r.c
new file mode 100644
index 0000000000..86651ef1c5
--- /dev/null
+++ b/REORG.TODO/time/bug-asctime_r.c
@@ -0,0 +1,32 @@
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+ time_t t = time (NULL);
+ struct tm *tp = localtime (&t);
+ tp->tm_year = 10000 - 1900;
+ char buf[1000];
+ errno = 0;
+ buf[26] = '\xff';
+ char *s = asctime_r (tp, buf);
+ if (s != NULL || errno != EOVERFLOW)
+ {
+ puts ("asctime_r did not fail correctly");
+ result = 1;
+ }
+ if (buf[26] != '\xff')
+ {
+ puts ("asctime_r overwrote 27th byte in buffer");
+ result = 1;
+ }
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/bug-getdate1.c b/REORG.TODO/time/bug-getdate1.c
new file mode 100644
index 0000000000..9afafba5be
--- /dev/null
+++ b/REORG.TODO/time/bug-getdate1.c
@@ -0,0 +1,152 @@
+/* BZ #5451 */
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <support/temp_file.h>
+
+static char *templ_filename;
+
+// Writes template given as parameter to file,
+// specified as the argument
+static void
+output_to_template_file (const char *str)
+{
+ FILE *fd = fopen (templ_filename, "w");
+ if (fd == NULL)
+ {
+ printf ("Can not open file for writing\n");
+ exit (1);
+ }
+
+ fprintf (fd, "%s\n", str);
+ fclose (fd);
+}
+
+// Calls getdate() function with specified parameter,
+// specified as the argument, also checks the contents of
+// file with template and prints the result
+static int
+process_getdate_on (const char *str)
+{
+ struct tm *res;
+ char templ[1000];
+ FILE *fd = fopen (templ_filename, "r");
+
+ if (fd == NULL)
+ {
+ printf ("Can not open file for reading\n");
+ exit (1);
+ }
+
+ if (fgets (templ, 1000, fd) == NULL)
+ {
+ printf ("Can not read file\n");
+ exit (1);
+ }
+ fclose (fd);
+
+ res = getdate (str);
+ if (res == NULL)
+ {
+ printf ("Failed on getdate(\"%s\"), template is: %s", str, templ);
+ printf ("Error number: %d\n\n", getdate_err);
+ return 1;
+ }
+ printf ("Success on getdate(\"%s\"), template is: %s\n", str, templ);
+ printf ("Result is\n");
+ printf ("Seconds: %d\n", res->tm_sec);
+ printf ("Minutes: %d\n", res->tm_min);
+ printf ("Hour: %d\n", res->tm_hour);
+ printf ("Day of month: %d\n", res->tm_mday);
+ printf ("Month of year: %d\n", res->tm_mon);
+ printf ("Years since 1900: %d\n", res->tm_year);
+ printf ("Day of week: %d\n", res->tm_wday);
+ printf ("Day of year: %d\n", res->tm_yday);
+ printf ("Daylight Savings flag: %d\n\n", res->tm_isdst);
+ return 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+
+ templ_filename = argv[1];
+
+ setenv ("DATEMSK", templ_filename, 1);
+
+ /*
+ * The following 4 testcases reproduce the problem:
+ * 1. Templates "%S" and "%M" are not processed,
+ * when used without "%H" template
+ */
+ int res = 0;
+ output_to_template_file ("%M");
+ res |= process_getdate_on ("1");
+
+ output_to_template_file ("%M %H");
+ res |= process_getdate_on ("1 2");
+
+ output_to_template_file ("%S");
+ res |= process_getdate_on ("1");
+
+ output_to_template_file ("%S %H");
+ res |= process_getdate_on ("1 2");
+
+ /*
+ * The following 9 testcases reproduce the problem:
+ * 2. Templates "%Y", "%y", "%d", "%C", "%C %y"
+ * are not processed separately
+ */
+ output_to_template_file ("%Y");
+ process_getdate_on ("2001");
+
+ output_to_template_file ("%Y %m");
+ res |= process_getdate_on ("2001 3");
+
+ output_to_template_file ("%y");
+ res |= process_getdate_on ("70");
+
+ output_to_template_file ("%y %m");
+ res |= process_getdate_on ("70 3");
+
+ output_to_template_file ("%d");
+ res |= process_getdate_on ("06");
+
+ output_to_template_file ("%d %m");
+ res |= process_getdate_on ("25 3");
+
+ output_to_template_file ("%C");
+ res |= process_getdate_on ("20");
+
+ output_to_template_file ("%C %y %m");
+ res |= process_getdate_on ("20 3 2");
+
+ output_to_template_file ("%C %y");
+ res |= process_getdate_on ("20 5");
+
+ /*
+ * The following testcase reproduces the problem:
+ * 3. When template is "%Y %m", day of month is not set
+ * to 1 as standard requires
+ */
+ output_to_template_file ("%Y %m");
+ res |= process_getdate_on ("2008 3");
+
+ return res;
+}
+#define TEST_FUNCTION_ARGV do_test
+
+static void
+do_prepare (int argc, char **argv)
+{
+ if (argc < 2)
+ {
+ puts ("Command line: progname template_filename_full_path");
+ exit (1);
+ }
+ add_temp_file (argv[1]);
+}
+#define PREPARE do_prepare
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/time/bug-mktime1.c b/REORG.TODO/time/bug-mktime1.c
new file mode 100644
index 0000000000..e071273f05
--- /dev/null
+++ b/REORG.TODO/time/bug-mktime1.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <time.h>
+
+
+static int
+do_test (void)
+{
+ struct tm t2 = { 0, 0, 0, 1, 1, 2050 - 1900, 1, 1, 1 };
+ time_t tt2 = mktime (&t2);
+ printf ("%ld\n", (long int) tt2);
+ if (sizeof (time_t) == 4 && tt2 != -1)
+ return 1;
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/clock.c b/REORG.TODO/time/clock.c
new file mode 100644
index 0000000000..bb8e9d323e
--- /dev/null
+++ b/REORG.TODO/time/clock.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/times.h>
+#include <time.h>
+#include <errno.h>
+
+/* Return the time used by the program so far (user time + system time). */
+clock_t
+clock (void)
+{
+ __set_errno (ENOSYS);
+ return (clock_t) -1;
+}
+
+stub_warning (clock)
diff --git a/REORG.TODO/time/clocktest.c b/REORG.TODO/time/clocktest.c
new file mode 100644
index 0000000000..779c05d8d9
--- /dev/null
+++ b/REORG.TODO/time/clocktest.c
@@ -0,0 +1,37 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdint.h>
+
+volatile int gotit = 0;
+
+static void
+alarm_handler (int signal)
+{
+ gotit = 1;
+}
+
+
+int
+main (int argc, char ** argv)
+{
+ clock_t start, stop;
+
+ if (signal(SIGALRM, alarm_handler) == SIG_ERR)
+ {
+ perror ("signal");
+ exit (1);
+ }
+ alarm(1);
+ start = clock ();
+ while (!gotit);
+ stop = clock ();
+
+ printf ("%jd clock ticks per second (start=%jd,stop=%jd)\n",
+ (intmax_t) (stop - start), (intmax_t) start, (intmax_t) stop);
+ printf ("CLOCKS_PER_SEC=%jd, sysconf(_SC_CLK_TCK)=%ld\n",
+ (intmax_t) CLOCKS_PER_SEC, sysconf(_SC_CLK_TCK));
+ return 0;
+}
diff --git a/REORG.TODO/time/ctime.c b/REORG.TODO/time/ctime.c
new file mode 100644
index 0000000000..7baca1bb57
--- /dev/null
+++ b/REORG.TODO/time/ctime.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <time.h>
+
+/* Return a string as returned by asctime which
+ is the representation of *T in that form. */
+char *
+ctime (const time_t *t)
+{
+ /* The C Standard says ctime (t) is equivalent to asctime (localtime (t)).
+ In particular, ctime and asctime must yield the same pointer. */
+ return asctime (localtime (t));
+}
diff --git a/REORG.TODO/time/ctime_r.c b/REORG.TODO/time/ctime_r.c
new file mode 100644
index 0000000000..ecd7731038
--- /dev/null
+++ b/REORG.TODO/time/ctime_r.c
@@ -0,0 +1,29 @@
+/* Return in BUF representation of time T in form of asctime
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <time.h>
+
+/* Return a string as returned by asctime which is the representation
+ of *T in that form. Reentrant version. */
+char *
+ctime_r (const time_t *t, char *buf)
+{
+ struct tm tm;
+ return __asctime_r (__localtime_r (t, &tm), buf);
+}
diff --git a/REORG.TODO/time/datemsk b/REORG.TODO/time/datemsk
new file mode 100644
index 0000000000..3dc4d417fe
--- /dev/null
+++ b/REORG.TODO/time/datemsk
@@ -0,0 +1,2 @@
+%H:%M:%S %F
+%d-%m-%Y %T
diff --git a/REORG.TODO/time/difftime.c b/REORG.TODO/time/difftime.c
new file mode 100644
index 0000000000..e5e3311744
--- /dev/null
+++ b/REORG.TODO/time/difftime.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert <eggert@cs.ucla.edu>. */
+
+#include <time.h>
+
+#include <limits.h>
+#include <float.h>
+#include <stdint.h>
+
+#define TYPE_BITS(type) (sizeof (type) * CHAR_BIT)
+#define TYPE_FLOATING(type) ((type) 0.5 == 0.5)
+#define TYPE_SIGNED(type) ((type) -1 < 0)
+
+/* Return the difference between TIME1 and TIME0, where TIME0 <= TIME1.
+ time_t is known to be an integer type. */
+
+static double
+subtract (time_t time1, time_t time0)
+{
+ if (! TYPE_SIGNED (time_t))
+ return time1 - time0;
+ else
+ {
+ /* Optimize the common special cases where time_t
+ can be converted to uintmax_t without losing information. */
+ uintmax_t dt = (uintmax_t) time1 - (uintmax_t) time0;
+ double delta = dt;
+
+ if (UINTMAX_MAX / 2 < INTMAX_MAX)
+ {
+ /* This is a rare host where uintmax_t has padding bits, and possibly
+ information was lost when converting time_t to uintmax_t.
+ Check for overflow by comparing dt/2 to (time1/2 - time0/2).
+ Overflow occurred if they differ by more than a small slop.
+ Thanks to Clive D.W. Feather for detailed technical advice about
+ hosts with padding bits.
+
+ In the following code the "h" prefix means half. By range
+ analysis, we have:
+
+ -0.5 <= ht1 - 0.5*time1 <= 0.5
+ -0.5 <= ht0 - 0.5*time0 <= 0.5
+ -1.0 <= dht - 0.5*(time1 - time0) <= 1.0
+
+ If overflow has not occurred, we also have:
+
+ -0.5 <= hdt - 0.5*(time1 - time0) <= 0
+ -1.0 <= dht - hdt <= 1.5
+
+ and since dht - hdt is an integer, we also have:
+
+ -1 <= dht - hdt <= 1
+
+ or equivalently:
+
+ 0 <= dht - hdt + 1 <= 2
+
+ In the above analysis, all the operators have their exact
+ mathematical semantics, not C semantics. However, dht - hdt +
+ 1 is unsigned in C, so it need not be compared to zero. */
+
+ uintmax_t hdt = dt / 2;
+ time_t ht1 = time1 / 2;
+ time_t ht0 = time0 / 2;
+ time_t dht = ht1 - ht0;
+
+ if (2 < dht - hdt + 1)
+ {
+ /* Repair delta overflow.
+
+ The following expression contains a second rounding,
+ so the result may not be the closest to the true answer.
+ This problem occurs only with very large differences.
+ It's too painful to fix this portably. */
+
+ delta = dt + 2.0L * (UINTMAX_MAX - UINTMAX_MAX / 2);
+ }
+ }
+
+ return delta;
+ }
+}
+
+/* Return the difference between TIME1 and TIME0. */
+double
+__difftime (time_t time1, time_t time0)
+{
+ /* Convert to double and then subtract if no double-rounding error could
+ result. */
+
+ if (TYPE_BITS (time_t) <= DBL_MANT_DIG
+ || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double)))
+ return (double) time1 - (double) time0;
+
+ /* Likewise for long double. */
+
+ if (TYPE_BITS (time_t) <= LDBL_MANT_DIG || TYPE_FLOATING (time_t))
+ return (long double) time1 - (long double) time0;
+
+ /* Subtract the smaller integer from the larger, convert the difference to
+ double, and then negate if needed. */
+
+ return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);
+}
+strong_alias (__difftime, difftime)
diff --git a/REORG.TODO/time/dysize.c b/REORG.TODO/time/dysize.c
new file mode 100644
index 0000000000..feed19c2d7
--- /dev/null
+++ b/REORG.TODO/time/dysize.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 1994-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <time.h>
+
+int
+dysize (int year)
+{
+ return __isleap (year) ? 366 : 365;
+}
diff --git a/REORG.TODO/time/era.c b/REORG.TODO/time/era.c
new file mode 100644
index 0000000000..b5743c621a
--- /dev/null
+++ b/REORG.TODO/time/era.c
@@ -0,0 +1,177 @@
+/* Helper functions used by strftime/strptime to handle locale-specific "eras".
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "../locale/localeinfo.h"
+#include <libc-lock.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdint.h>
+
+/* Some of the functions here must not be used while setlocale is called. */
+__libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
+
+#define CURRENT(item) (current->values[_NL_ITEM_INDEX (item)].string)
+#define CURRENT_WORD(item) (current->values[_NL_ITEM_INDEX (item)].word)
+
+#define ERA_DATE_CMP(a, b) \
+ (a[0] < b[0] || (a[0] == b[0] && (a[1] < b[1] \
+ || (a[1] == b[1] && a[2] <= b[2]))))
+
+/* Look up the era information in CURRENT's locale strings and
+ cache it in CURRENT->private. */
+static void internal_function
+_nl_init_era_entries (struct __locale_data *current)
+{
+ size_t cnt;
+ struct lc_time_data *data;
+
+ /* Avoid touching CURRENT if there is no data at all, for _nl_C_LC_TIME. */
+ if (CURRENT_WORD (_NL_TIME_ERA_NUM_ENTRIES) == 0)
+ return;
+
+ __libc_rwlock_wrlock (__libc_setlocale_lock);
+
+ if (current->private.time == NULL)
+ {
+ current->private.time = malloc (sizeof *current->private.time);
+ if (current->private.time == NULL)
+ goto out;
+ memset (current->private.time, 0, sizeof *current->private.time);
+ current->private.cleanup = &_nl_cleanup_time;
+ }
+ data = current->private.time;
+
+ if (! data->era_initialized)
+ {
+ size_t new_num_eras = CURRENT_WORD (_NL_TIME_ERA_NUM_ENTRIES);
+ if (new_num_eras == 0)
+ {
+ if (data->eras != NULL)
+ {
+ free (data->eras);
+ data->eras = NULL;
+ }
+ }
+ else
+ {
+ struct era_entry *new_eras = data->eras;
+
+ if (data->num_eras != new_num_eras)
+ new_eras =
+ (struct era_entry *) realloc (data->eras,
+ new_num_eras
+ * sizeof (struct era_entry));
+ if (new_eras == NULL)
+ {
+ free (data->eras);
+ data->num_eras = 0;
+ data->eras = NULL;
+ }
+ else
+ {
+ const char *ptr = CURRENT (_NL_TIME_ERA_ENTRIES);
+ data->num_eras = new_num_eras;
+ data->eras = new_eras;
+
+ for (cnt = 0; cnt < new_num_eras; ++cnt)
+ {
+ const char *base_ptr = ptr;
+ memcpy ((void *) (new_eras + cnt), (const void *) ptr,
+ sizeof (uint32_t) * 8);
+
+ if (ERA_DATE_CMP(new_eras[cnt].start_date,
+ new_eras[cnt].stop_date))
+ if (new_eras[cnt].direction == (uint32_t) '+')
+ new_eras[cnt].absolute_direction = 1;
+ else
+ new_eras[cnt].absolute_direction = -1;
+ else
+ if (new_eras[cnt].direction == (uint32_t) '+')
+ new_eras[cnt].absolute_direction = -1;
+ else
+ new_eras[cnt].absolute_direction = 1;
+
+ /* Skip numeric values. */
+ ptr += sizeof (uint32_t) * 8;
+
+ /* Set and skip era name. */
+ new_eras[cnt].era_name = ptr;
+ ptr = strchr (ptr, '\0') + 1;
+
+ /* Set and skip era format. */
+ new_eras[cnt].era_format = ptr;
+ ptr = strchr (ptr, '\0') + 1;
+
+ ptr += 3 - (((ptr - (const char *) base_ptr) + 3) & 3);
+
+ /* Set and skip wide era name. */
+ new_eras[cnt].era_wname = (wchar_t *) ptr;
+ ptr = (char *) (__wcschr ((wchar_t *) ptr, L'\0') + 1);
+
+ /* Set and skip wide era format. */
+ new_eras[cnt].era_wformat = (wchar_t *) ptr;
+ ptr = (char *) (__wcschr ((wchar_t *) ptr, L'\0') + 1);
+ }
+ }
+ }
+
+ data->era_initialized = 1;
+ }
+
+ out:
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+}
+
+struct era_entry *
+internal_function
+_nl_get_era_entry (const struct tm *tp, struct __locale_data *current)
+{
+ if (current->private.time == NULL || !current->private.time->era_initialized)
+ _nl_init_era_entries (current);
+
+ if (current->private.time != NULL)
+ {
+ /* Now compare date with the available eras. */
+ const int32_t tdate[3] = { tp->tm_year, tp->tm_mon, tp->tm_mday };
+ size_t cnt;
+ for (cnt = 0; cnt < current->private.time->num_eras; ++cnt)
+ if ((ERA_DATE_CMP (current->private.time->eras[cnt].start_date, tdate)
+ && ERA_DATE_CMP (tdate,
+ current->private.time->eras[cnt].stop_date))
+ || (ERA_DATE_CMP (current->private.time->eras[cnt].stop_date,
+ tdate)
+ && ERA_DATE_CMP (tdate,
+ current->private.time->eras[cnt].start_date)))
+ return &current->private.time->eras[cnt];
+ }
+
+ return NULL;
+}
+
+
+struct era_entry *
+internal_function
+_nl_select_era_entry (int cnt, struct __locale_data *current)
+{
+ if (current->private.time == NULL || !current->private.time->era_initialized)
+ _nl_init_era_entries (current);
+
+ return (current->private.time == NULL
+ ? NULL : &current->private.time->eras[cnt]);
+}
diff --git a/REORG.TODO/time/ftime.c b/REORG.TODO/time/ftime.c
new file mode 100644
index 0000000000..1cfb53cc04
--- /dev/null
+++ b/REORG.TODO/time/ftime.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 1994-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <time.h>
+#include <sys/timeb.h>
+
+int
+ftime (struct timeb *timebuf)
+{
+ int save = errno;
+ struct tm tp;
+
+ __set_errno (0);
+ if (time (&timebuf->time) == (time_t) -1 && errno != 0)
+ return -1;
+ timebuf->millitm = 0;
+
+ if (__localtime_r (&timebuf->time, &tp) == NULL)
+ return -1;
+
+ timebuf->timezone = tp.tm_gmtoff / 60;
+ timebuf->dstflag = tp.tm_isdst;
+
+ __set_errno (save);
+ return 0;
+}
diff --git a/REORG.TODO/time/getdate.c b/REORG.TODO/time/getdate.c
new file mode 100644
index 0000000000..28ea48287f
--- /dev/null
+++ b/REORG.TODO/time/getdate.c
@@ -0,0 +1,312 @@
+/* Convert a string representation of time to a time value.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <alloca.h>
+
+#define TM_YEAR_BASE 1900
+
+
+/* Prototypes for local functions. */
+static int first_wday (int year, int mon, int wday);
+static int check_mday (int year, int mon, int mday);
+
+
+/* Set to one of the following values to indicate an error.
+ 1 the DATEMSK environment variable is null or undefined,
+ 2 the template file cannot be opened for reading,
+ 3 failed to get file status information,
+ 4 the template file is not a regular file,
+ 5 an error is encountered while reading the template file,
+ 6 memory allication failed (not enough memory available),
+ 7 there is no line in the template that matches the input,
+ 8 invalid input specification Example: February 31 or a time is
+ specified that can not be represented in a time_t (representing
+ the time in seconds since 00:00:00 UTC, January 1, 1970) */
+int getdate_err;
+
+
+/* Returns the first weekday WDAY of month MON in the year YEAR. */
+static int
+first_wday (int year, int mon, int wday)
+{
+ struct tm tm;
+
+ if (wday == INT_MIN)
+ return 1;
+
+ memset (&tm, 0, sizeof (struct tm));
+ tm.tm_year = year;
+ tm.tm_mon = mon;
+ tm.tm_mday = 1;
+ mktime (&tm);
+
+ return (1 + (wday - tm.tm_wday + 7) % 7);
+}
+
+
+/* Returns 1 if MDAY is a valid day of the month in month MON of year
+ YEAR, and 0 if it is not. */
+static int
+check_mday (int year, int mon, int mday)
+{
+ switch (mon)
+ {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ case 7:
+ case 9:
+ case 11:
+ if (mday >= 1 && mday <= 31)
+ return 1;
+ break;
+ case 3:
+ case 5:
+ case 8:
+ case 10:
+ if (mday >= 1 && mday <= 30)
+ return 1;
+ break;
+ case 1:
+ if (mday >= 1 && mday <= (__isleap (year) ? 29 : 28))
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+
+int
+__getdate_r (const char *string, struct tm *tp)
+{
+ FILE *fp;
+ char *line;
+ size_t len;
+ char *datemsk;
+ char *result = NULL;
+ time_t timer;
+ struct tm tm;
+ struct stat64 st;
+ int mday_ok = 0;
+
+ datemsk = getenv ("DATEMSK");
+ if (datemsk == NULL || *datemsk == '\0')
+ return 1;
+
+ if (stat64 (datemsk, &st) < 0)
+ return 3;
+
+ if (!S_ISREG (st.st_mode))
+ return 4;
+
+ if (__access (datemsk, R_OK) < 0)
+ return 2;
+
+ /* Open the template file. */
+ fp = fopen (datemsk, "rce");
+ if (fp == NULL)
+ return 2;
+
+ /* No threads reading this stream. */
+ __fsetlocking (fp, FSETLOCKING_BYCALLER);
+
+ /* Skip leading whitespace. */
+ while (isspace (*string))
+ string++;
+
+ size_t inlen, oldlen;
+
+ oldlen = inlen = strlen (string);
+
+ /* Skip trailing whitespace. */
+ while (inlen > 0 && isspace (string[inlen - 1]))
+ inlen--;
+
+ char *instr = NULL;
+
+ if (inlen < oldlen)
+ {
+ bool using_malloc = false;
+
+ if (__libc_use_alloca (inlen + 1))
+ instr = alloca (inlen + 1);
+ else
+ {
+ instr = malloc (inlen + 1);
+ if (instr == NULL)
+ {
+ fclose (fp);
+ return 6;
+ }
+ using_malloc = true;
+ }
+ memcpy (instr, string, inlen);
+ instr[inlen] = '\0';
+ string = instr;
+
+ if (!using_malloc)
+ instr = NULL;
+ }
+
+ line = NULL;
+ len = 0;
+ do
+ {
+ ssize_t n;
+
+ n = __getline (&line, &len, fp);
+ if (n < 0)
+ break;
+ if (line[n - 1] == '\n')
+ line[n - 1] = '\0';
+
+ /* Do the conversion. */
+ tp->tm_year = tp->tm_mon = tp->tm_mday = tp->tm_wday = INT_MIN;
+ tp->tm_hour = tp->tm_sec = tp->tm_min = INT_MIN;
+ tp->tm_isdst = -1;
+ tp->tm_gmtoff = 0;
+ tp->tm_zone = NULL;
+ result = strptime (string, line, tp);
+ if (result && *result == '\0')
+ break;
+ }
+ while (!feof_unlocked (fp));
+
+ free (instr);
+
+ /* Free the buffer. */
+ free (line);
+
+ /* Check for errors. */
+ if (ferror_unlocked (fp))
+ {
+ fclose (fp);
+ return 5;
+ }
+
+ /* Close template file. */
+ fclose (fp);
+
+ if (result == NULL || *result != '\0')
+ return 7;
+
+ /* Get current time. */
+ time (&timer);
+ __localtime_r (&timer, &tm);
+
+ /* If only the weekday is given, today is assumed if the given day
+ is equal to the current day and next week if it is less. */
+ if (tp->tm_wday >= 0 && tp->tm_wday <= 6 && tp->tm_year == INT_MIN
+ && tp->tm_mon == INT_MIN && tp->tm_mday == INT_MIN)
+ {
+ tp->tm_year = tm.tm_year;
+ tp->tm_mon = tm.tm_mon;
+ tp->tm_mday = tm.tm_mday + (tp->tm_wday - tm.tm_wday + 7) % 7;
+ mday_ok = 1;
+ }
+
+ /* If only the month is given, the current month is assumed if the
+ given month is equal to the current month and next year if it is
+ less and no year is given (the first day of month is assumed if
+ no day is given. */
+ if (tp->tm_mon >= 0 && tp->tm_mon <= 11 && tp->tm_mday == INT_MIN)
+ {
+ if (tp->tm_year == INT_MIN)
+ tp->tm_year = tm.tm_year + (((tp->tm_mon - tm.tm_mon) < 0) ? 1 : 0);
+ tp->tm_mday = first_wday (tp->tm_year, tp->tm_mon, tp->tm_wday);
+ mday_ok = 1;
+ }
+
+ /* If no hour, minute and second are given the current hour, minute
+ and second are assumed. */
+ if (tp->tm_hour == INT_MIN && tp->tm_min == INT_MIN && tp->tm_sec == INT_MIN)
+ {
+ tp->tm_hour = tm.tm_hour;
+ tp->tm_min = tm.tm_min;
+ tp->tm_sec = tm.tm_sec;
+ }
+
+ /* Fill in the gaps. */
+ if (tp->tm_hour == INT_MIN)
+ tp->tm_hour = 0;
+ if (tp->tm_min == INT_MIN)
+ tp->tm_min = 0;
+ if (tp->tm_sec == INT_MIN)
+ tp->tm_sec = 0;
+
+ /* If no date is given, today is assumed if the given hour is
+ greater than the current hour and tomorrow is assumed if
+ it is less. */
+ if (tp->tm_hour >= 0 && tp->tm_hour <= 23
+ && tp->tm_mon == INT_MIN
+ && tp->tm_mday == INT_MIN && tp->tm_wday == INT_MIN)
+ {
+ tp->tm_mon = tm.tm_mon;
+ tp->tm_mday = tm.tm_mday + ((tp->tm_hour - tm.tm_hour) < 0 ? 1 : 0);
+ mday_ok = 1;
+ }
+
+ /* More fillers. */
+ if (tp->tm_year == INT_MIN)
+ tp->tm_year = tm.tm_year;
+ if (tp->tm_mon == INT_MIN)
+ tp->tm_mon = tm.tm_mon;
+
+ /* Check if the day of month is within range, and if the time can be
+ represented in a time_t. We make use of the fact that the mktime
+ call normalizes the struct tm. */
+ if ((!mday_ok && !check_mday (TM_YEAR_BASE + tp->tm_year, tp->tm_mon,
+ tp->tm_mday))
+ || mktime (tp) == (time_t) -1)
+ return 8;
+
+ return 0;
+}
+#ifdef weak_alias
+weak_alias (__getdate_r, getdate_r)
+#endif
+
+
+struct tm *
+getdate (const char *string)
+{
+ /* Buffer returned by getdate. */
+ static struct tm tmbuf;
+ int errval = __getdate_r (string, &tmbuf);
+
+ if (errval != 0)
+ {
+ getdate_err = errval;
+ return NULL;
+ }
+
+ return &tmbuf;
+}
diff --git a/REORG.TODO/time/getitimer.c b/REORG.TODO/time/getitimer.c
new file mode 100644
index 0000000000..f42e728bdf
--- /dev/null
+++ b/REORG.TODO/time/getitimer.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+
+/* Set *VALUE to the current setting of timer WHICH.
+ Return 0 on success, -1 on errors. */
+int
+__getitimer (enum __itimer_which which, struct itimerval *value)
+{
+ if (value == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (getitimer)
+
+weak_alias (__getitimer, getitimer)
diff --git a/REORG.TODO/time/gettimeofday.c b/REORG.TODO/time/gettimeofday.c
new file mode 100644
index 0000000000..1d675b6b23
--- /dev/null
+++ b/REORG.TODO/time/gettimeofday.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sys/time.h>
+
+/* Get the current time of day and timezone information,
+ putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled.
+ Returns 0 on success, -1 on errors. */
+int
+__gettimeofday (struct timeval *tv, struct timezone *tz)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+libc_hidden_def (__gettimeofday)
+weak_alias (__gettimeofday, gettimeofday)
+libc_hidden_weak (gettimeofday)
+
+stub_warning (gettimeofday)
diff --git a/REORG.TODO/time/gmtime.c b/REORG.TODO/time/gmtime.c
new file mode 100644
index 0000000000..049d551cdf
--- /dev/null
+++ b/REORG.TODO/time/gmtime.c
@@ -0,0 +1,37 @@
+/* Convert `time_t' to `struct tm' in UTC.
+ Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <time.h>
+
+/* Return the `struct tm' representation of *T in UTC,
+ using *TP to store the result. */
+struct tm *
+__gmtime_r (const time_t *t, struct tm *tp)
+{
+ return __tz_convert (t, 0, tp);
+}
+libc_hidden_def (__gmtime_r)
+weak_alias (__gmtime_r, gmtime_r)
+
+
+/* Return the `struct tm' representation of *T in UTC. */
+struct tm *
+gmtime (const time_t *t)
+{
+ return __tz_convert (t, 0, &_tmbuf);
+}
diff --git a/REORG.TODO/time/lc-time-cleanup.c b/REORG.TODO/time/lc-time-cleanup.c
new file mode 100644
index 0000000000..92b5be5818
--- /dev/null
+++ b/REORG.TODO/time/lc-time-cleanup.c
@@ -0,0 +1,37 @@
+/* Cleanup code for data structures kept by strftime/strptime helper functions.
+ Copyright (C) 2002-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "../locale/localeinfo.h"
+#include <stdlib.h>
+
+void internal_function
+_nl_cleanup_time (struct __locale_data *locale)
+{
+ struct lc_time_data *const data = locale->private.time;
+ if (data != NULL)
+ {
+ locale->private.time = NULL;
+ locale->private.cleanup = NULL;
+
+ free (data->eras);
+ free (data->alt_digits);
+ free (data->walt_digits);
+
+ free (data);
+ }
+}
diff --git a/REORG.TODO/time/localtime.c b/REORG.TODO/time/localtime.c
new file mode 100644
index 0000000000..07dd67ca71
--- /dev/null
+++ b/REORG.TODO/time/localtime.c
@@ -0,0 +1,41 @@
+/* Convert `time_t' to `struct tm' in local time zone.
+ Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <time.h>
+
+/* The C Standard says that localtime and gmtime return the same pointer. */
+struct tm _tmbuf;
+
+
+/* Return the `struct tm' representation of *T in local time,
+ using *TP to store the result. */
+struct tm *
+__localtime_r (const time_t *t, struct tm *tp)
+{
+ return __tz_convert (t, 1, tp);
+}
+weak_alias (__localtime_r, localtime_r)
+
+
+/* Return the `struct tm' representation of *T in local time. */
+struct tm *
+localtime (const time_t *t)
+{
+ return __tz_convert (t, 1, &_tmbuf);
+}
+libc_hidden_def (localtime)
diff --git a/REORG.TODO/time/mktime.c b/REORG.TODO/time/mktime.c
new file mode 100644
index 0000000000..4c48d358a1
--- /dev/null
+++ b/REORG.TODO/time/mktime.c
@@ -0,0 +1,741 @@
+/* Convert a 'struct tm' to a time_t value.
+ Copyright (C) 1993-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Paul Eggert <eggert@twinsun.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Define this to have a standalone program to test this implementation of
+ mktime. */
+/* #define DEBUG_MKTIME 1 */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+/* Assume that leap seconds are possible, unless told otherwise.
+ If the host has a 'zic' command with a '-L leapsecondfilename' option,
+ then it supports leap seconds; otherwise it probably doesn't. */
+#ifndef LEAP_SECONDS_POSSIBLE
+# define LEAP_SECONDS_POSSIBLE 1
+#endif
+
+#include <time.h>
+
+#include <limits.h>
+
+#include <string.h> /* For the real memcpy prototype. */
+
+#if defined DEBUG_MKTIME && DEBUG_MKTIME
+# include <stdio.h>
+# include <stdlib.h>
+/* Make it work even if the system's libc has its own mktime routine. */
+# undef mktime
+# define mktime my_mktime
+#endif /* DEBUG_MKTIME */
+
+/* Some of the code in this file assumes that signed integer overflow
+ silently wraps around. This assumption can't easily be programmed
+ around, nor can it be checked for portably at compile-time or
+ easily eliminated at run-time.
+
+ Define WRAPV to 1 if the assumption is valid and if
+ #pragma GCC optimize ("wrapv")
+ does not trigger GCC bug 51793
+ <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51793>.
+ Otherwise, define it to 0; this forces the use of slower code that,
+ while not guaranteed by the C Standard, works on all production
+ platforms that we know about. */
+#ifndef WRAPV
+# if (((__GNUC__ == 4 && 4 <= __GNUC_MINOR__) || 4 < __GNUC__) \
+ && defined __GLIBC__)
+# pragma GCC optimize ("wrapv")
+# define WRAPV 1
+# else
+# define WRAPV 0
+# endif
+#endif
+
+/* Verify a requirement at compile-time (unlike assert, which is runtime). */
+#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
+
+/* A signed type that is at least one bit wider than int. */
+#if INT_MAX <= LONG_MAX / 2
+typedef long int long_int;
+#else
+typedef long long int long_int;
+#endif
+verify (long_int_is_wide_enough, INT_MAX == INT_MAX * (long_int) 2 / 2);
+
+/* Shift A right by B bits portably, by dividing A by 2**B and
+ truncating towards minus infinity. A and B should be free of side
+ effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
+ INT_BITS is the number of useful bits in an int. GNU code can
+ assume that INT_BITS is at least 32.
+
+ ISO C99 says that A >> B is implementation-defined if A < 0. Some
+ implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
+ right in the usual way when A < 0, so SHR falls back on division if
+ ordinary A >> B doesn't seem to be the usual signed shift. */
+#define SHR(a, b) \
+ ((-1 >> 1 == -1 \
+ && (long_int) -1 >> 1 == -1 \
+ && ((time_t) -1 >> 1 == -1 || ! TYPE_SIGNED (time_t))) \
+ ? (a) >> (b) \
+ : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
+
+/* The extra casts in the following macros work around compiler bugs,
+ e.g., in Cray C 5.0.3.0. */
+
+/* True if the arithmetic type T is an integer type. bool counts as
+ an integer. */
+#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
+
+/* True if negative values of the signed integer type T use two's
+ complement, or if T is an unsigned integer type. */
+#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
+
+/* True if the arithmetic type T is signed. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* The maximum and minimum values for the integer type T. These
+ macros have undefined behavior if T is signed and has padding bits.
+ If this is a problem for you, please let us know how to fix it for
+ your host. */
+#define TYPE_MINIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) 0 \
+ : ~ TYPE_MAXIMUM (t)))
+#define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
+
+#ifndef TIME_T_MIN
+# define TIME_T_MIN TYPE_MINIMUM (time_t)
+#endif
+#ifndef TIME_T_MAX
+# define TIME_T_MAX TYPE_MAXIMUM (time_t)
+#endif
+#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
+
+verify (time_t_is_integer, TYPE_IS_INTEGER (time_t));
+verify (twos_complement_arithmetic,
+ (TYPE_TWOS_COMPLEMENT (int)
+ && TYPE_TWOS_COMPLEMENT (long_int)
+ && TYPE_TWOS_COMPLEMENT (time_t)));
+
+#define EPOCH_YEAR 1970
+#define TM_YEAR_BASE 1900
+verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0);
+
+/* Return 1 if YEAR + TM_YEAR_BASE is a leap year. */
+static int
+leapyear (long_int year)
+{
+ /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
+ Also, work even if YEAR is negative. */
+ return
+ ((year & 3) == 0
+ && (year % 100 != 0
+ || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
+}
+
+/* How many days come before each month (0-12). */
+#ifndef _LIBC
+static
+#endif
+const unsigned short int __mon_yday[2][13] =
+ {
+ /* Normal years. */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ /* Leap years. */
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+ };
+
+
+#ifndef _LIBC
+/* Portable standalone applications should supply a <time.h> that
+ declares a POSIX-compliant localtime_r, for the benefit of older
+ implementations that lack localtime_r or have a nonstandard one.
+ See the gnulib time_r module for one way to implement this. */
+# undef __localtime_r
+# define __localtime_r localtime_r
+# define __mktime_internal mktime_internal
+# include "mktime-internal.h"
+#endif
+
+/* Return 1 if the values A and B differ according to the rules for
+ tm_isdst: A and B differ if one is zero and the other positive. */
+static int
+isdst_differ (int a, int b)
+{
+ return (!a != !b) && (0 <= a) && (0 <= b);
+}
+
+/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
+ (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
+ were not adjusted between the time stamps.
+
+ The YEAR values uses the same numbering as TP->tm_year. Values
+ need not be in the usual range. However, YEAR1 must not be less
+ than 2 * INT_MIN or greater than 2 * INT_MAX.
+
+ The result may overflow. It is the caller's responsibility to
+ detect overflow. */
+
+static time_t
+ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
+ int year0, int yday0, int hour0, int min0, int sec0)
+{
+ verify (C99_integer_division, -1 / 2 == 0);
+
+ /* Compute intervening leap days correctly even if year is negative.
+ Take care to avoid integer overflow here. */
+ int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
+ int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
+ int a100 = a4 / 25 - (a4 % 25 < 0);
+ int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a400 = SHR (a100, 2);
+ int b400 = SHR (b100, 2);
+ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+
+ /* Compute the desired time in time_t precision. Overflow might
+ occur here. */
+ time_t tyear1 = year1;
+ time_t years = tyear1 - year0;
+ time_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
+ time_t hours = 24 * days + hour1 - hour0;
+ time_t minutes = 60 * hours + min1 - min0;
+ time_t seconds = 60 * minutes + sec1 - sec0;
+ return seconds;
+}
+
+/* Return the average of A and B, even if A + B would overflow. */
+static time_t
+time_t_avg (time_t a, time_t b)
+{
+ return SHR (a, 1) + SHR (b, 1) + (a & b & 1);
+}
+
+/* Return 1 if A + B does not overflow. If time_t is unsigned and if
+ B's top bit is set, assume that the sum represents A - -B, and
+ return 1 if the subtraction does not wrap around. */
+static int
+time_t_add_ok (time_t a, time_t b)
+{
+ if (! TYPE_SIGNED (time_t))
+ {
+ time_t sum = a + b;
+ return (sum < a) == (TIME_T_MIDPOINT <= b);
+ }
+ else if (WRAPV)
+ {
+ time_t sum = a + b;
+ return (sum < a) == (b < 0);
+ }
+ else
+ {
+ time_t avg = time_t_avg (a, b);
+ return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+ }
+}
+
+/* Return 1 if A + B does not overflow. */
+static int
+time_t_int_add_ok (time_t a, int b)
+{
+ verify (int_no_wider_than_time_t, INT_MAX <= TIME_T_MAX);
+ if (WRAPV)
+ {
+ time_t sum = a + b;
+ return (sum < a) == (b < 0);
+ }
+ else
+ {
+ int a_odd = a & 1;
+ time_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
+ return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+ }
+}
+
+/* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
+ assuming that *T corresponds to *TP and that no clock adjustments
+ occurred between *TP and the desired time.
+ If TP is null, return a value not equal to *T; this avoids false matches.
+ If overflow occurs, yield the minimal or maximal value, except do not
+ yield a value equal to *T. */
+static time_t
+guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
+ const time_t *t, const struct tm *tp)
+{
+ if (tp)
+ {
+ time_t d = ydhms_diff (year, yday, hour, min, sec,
+ tp->tm_year, tp->tm_yday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ if (time_t_add_ok (*t, d))
+ return *t + d;
+ }
+
+ /* Overflow occurred one way or another. Return the nearest result
+ that is actually in range, except don't report a zero difference
+ if the actual difference is nonzero, as that would cause a false
+ match; and don't oscillate between two values, as that would
+ confuse the spring-forward gap detector. */
+ return (*t < TIME_T_MIDPOINT
+ ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
+ : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
+}
+
+/* Use CONVERT to convert *T to a broken down time in *TP.
+ If *T is out of range for conversion, adjust it so that
+ it is the nearest in-range value and then convert that. */
+static struct tm *
+ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
+ time_t *t, struct tm *tp)
+{
+ struct tm *r = convert (t, tp);
+
+ if (!r && *t)
+ {
+ time_t bad = *t;
+ time_t ok = 0;
+
+ /* BAD is a known unconvertible time_t, and OK is a known good one.
+ Use binary search to narrow the range between BAD and OK until
+ they differ by 1. */
+ while (bad != ok + (bad < 0 ? -1 : 1))
+ {
+ time_t mid = *t = time_t_avg (ok, bad);
+ r = convert (t, tp);
+ if (r)
+ ok = mid;
+ else
+ bad = mid;
+ }
+
+ if (!r && ok)
+ {
+ /* The last conversion attempt failed;
+ revert to the most recent successful attempt. */
+ *t = ok;
+ r = convert (t, tp);
+ }
+ }
+
+ return r;
+}
+
+
+/* Convert *TP to a time_t value, inverting
+ the monotonic and mostly-unit-linear conversion function CONVERT.
+ Use *OFFSET to keep track of a guess at the offset of the result,
+ compared to what the result would be for UTC without leap seconds.
+ If *OFFSET's guess is correct, only one CONVERT call is needed.
+ This function is external because it is used also by timegm.c. */
+time_t
+__mktime_internal (struct tm *tp,
+ struct tm *(*convert) (const time_t *, struct tm *),
+ time_t *offset)
+{
+ time_t t, gt, t0, t1, t2;
+ struct tm tm;
+
+ /* The maximum number of probes (calls to CONVERT) should be enough
+ to handle any combinations of time zone rule changes, solar time,
+ leap seconds, and oscillations around a spring-forward gap.
+ POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
+ int remaining_probes = 6;
+
+ /* Time requested. Copy it in case CONVERT modifies *TP; this can
+ occur if TP is localtime's returned value and CONVERT is localtime. */
+ int sec = tp->tm_sec;
+ int min = tp->tm_min;
+ int hour = tp->tm_hour;
+ int mday = tp->tm_mday;
+ int mon = tp->tm_mon;
+ int year_requested = tp->tm_year;
+ int isdst = tp->tm_isdst;
+
+ /* 1 if the previous probe was DST. */
+ int dst2;
+
+ /* Ensure that mon is in range, and set year accordingly. */
+ int mon_remainder = mon % 12;
+ int negative_mon_remainder = mon_remainder < 0;
+ int mon_years = mon / 12 - negative_mon_remainder;
+ long_int lyear_requested = year_requested;
+ long_int year = lyear_requested + mon_years;
+
+ /* The other values need not be in range:
+ the remaining code handles minor overflows correctly,
+ assuming int and time_t arithmetic wraps around.
+ Major overflows are caught at the end. */
+
+ /* Calculate day of year from year, month, and day of month.
+ The result need not be in range. */
+ int mon_yday = ((__mon_yday[leapyear (year)]
+ [mon_remainder + 12 * negative_mon_remainder])
+ - 1);
+ long_int lmday = mday;
+ long_int yday = mon_yday + lmday;
+
+ time_t guessed_offset = *offset;
+
+ int sec_requested = sec;
+
+ if (LEAP_SECONDS_POSSIBLE)
+ {
+ /* Handle out-of-range seconds specially,
+ since ydhms_tm_diff assumes every minute has 60 seconds. */
+ if (sec < 0)
+ sec = 0;
+ if (59 < sec)
+ sec = 59;
+ }
+
+ /* Invert CONVERT by probing. First assume the same offset as last
+ time. */
+
+ t0 = ydhms_diff (year, yday, hour, min, sec,
+ EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
+
+ if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
+ {
+ /* time_t isn't large enough to rule out overflows, so check
+ for major overflows. A gross check suffices, since if t0
+ has overflowed, it is off by a multiple of TIME_T_MAX -
+ TIME_T_MIN + 1. So ignore any component of the difference
+ that is bounded by a small value. */
+
+ /* Approximate log base 2 of the number of time units per
+ biennium. A biennium is 2 years; use this unit instead of
+ years to avoid integer overflow. For example, 2 average
+ Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
+ which is 63113904 seconds, and rint (log2 (63113904)) is
+ 26. */
+ int ALOG2_SECONDS_PER_BIENNIUM = 26;
+ int ALOG2_MINUTES_PER_BIENNIUM = 20;
+ int ALOG2_HOURS_PER_BIENNIUM = 14;
+ int ALOG2_DAYS_PER_BIENNIUM = 10;
+ int LOG2_YEARS_PER_BIENNIUM = 1;
+
+ int approx_requested_biennia =
+ (SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
+ - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
+ + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
+ + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
+ + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
+ + (LEAP_SECONDS_POSSIBLE
+ ? 0
+ : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
+
+ int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
+ int diff = approx_biennia - approx_requested_biennia;
+ int approx_abs_diff = diff < 0 ? -1 - diff : diff;
+
+ /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
+ gives a positive value of 715827882. Setting a variable
+ first then doing math on it seems to work.
+ (ghazi@caip.rutgers.edu) */
+ time_t time_t_max = TIME_T_MAX;
+ time_t time_t_min = TIME_T_MIN;
+ time_t overflow_threshold =
+ (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
+
+ if (overflow_threshold < approx_abs_diff)
+ {
+ /* Overflow occurred. Try repairing it; this might work if
+ the time zone offset is enough to undo the overflow. */
+ time_t repaired_t0 = -1 - t0;
+ approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
+ diff = approx_biennia - approx_requested_biennia;
+ approx_abs_diff = diff < 0 ? -1 - diff : diff;
+ if (overflow_threshold < approx_abs_diff)
+ return -1;
+ guessed_offset += repaired_t0 - t0;
+ t0 = repaired_t0;
+ }
+ }
+
+ /* Repeatedly use the error to improve the guess. */
+
+ for (t = t1 = t2 = t0, dst2 = 0;
+ (gt = guess_time_tm (year, yday, hour, min, sec, &t,
+ ranged_convert (convert, &t, &tm)),
+ t != gt);
+ t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
+ if (t == t1 && t != t2
+ && (tm.tm_isdst < 0
+ || (isdst < 0
+ ? dst2 <= (tm.tm_isdst != 0)
+ : (isdst != 0) != (tm.tm_isdst != 0))))
+ /* We can't possibly find a match, as we are oscillating
+ between two values. The requested time probably falls
+ within a spring-forward gap of size GT - T. Follow the common
+ practice in this case, which is to return a time that is GT - T
+ away from the requested time, preferring a time whose
+ tm_isdst differs from the requested value. (If no tm_isdst
+ was requested and only one of the two values has a nonzero
+ tm_isdst, prefer that value.) In practice, this is more
+ useful than returning -1. */
+ goto offset_found;
+ else if (--remaining_probes == 0)
+ return -1;
+
+ /* We have a match. Check whether tm.tm_isdst has the requested
+ value, if any. */
+ if (isdst_differ (isdst, tm.tm_isdst))
+ {
+ /* tm.tm_isdst has the wrong value. Look for a neighboring
+ time with the right value, and use its UTC offset.
+
+ Heuristic: probe the adjacent timestamps in both directions,
+ looking for the desired isdst. This should work for all real
+ time zone histories in the tz database. */
+
+ /* Distance between probes when looking for a DST boundary. In
+ tzdata2003a, the shortest period of DST is 601200 seconds
+ (e.g., America/Recife starting 2000-10-08 01:00), and the
+ shortest period of non-DST surrounded by DST is 694800
+ seconds (Africa/Tunis starting 1943-04-17 01:00). Use the
+ minimum of these two values, so we don't miss these short
+ periods when probing. */
+ int stride = 601200;
+
+ /* The longest period of DST in tzdata2003a is 536454000 seconds
+ (e.g., America/Jujuy starting 1946-10-01 01:00). The longest
+ period of non-DST is much longer, but it makes no real sense
+ to search for more than a year of non-DST, so use the DST
+ max. */
+ int duration_max = 536454000;
+
+ /* Search in both directions, so the maximum distance is half
+ the duration; add the stride to avoid off-by-1 problems. */
+ int delta_bound = duration_max / 2 + stride;
+
+ int delta, direction;
+
+ for (delta = stride; delta < delta_bound; delta += stride)
+ for (direction = -1; direction <= 1; direction += 2)
+ if (time_t_int_add_ok (t, delta * direction))
+ {
+ time_t ot = t + delta * direction;
+ struct tm otm;
+ ranged_convert (convert, &ot, &otm);
+ if (! isdst_differ (isdst, otm.tm_isdst))
+ {
+ /* We found the desired tm_isdst.
+ Extrapolate back to the desired time. */
+ t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm);
+ ranged_convert (convert, &t, &tm);
+ goto offset_found;
+ }
+ }
+ }
+
+ offset_found:
+ *offset = guessed_offset + t - t0;
+
+ if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
+ {
+ /* Adjust time to reflect the tm_sec requested, not the normalized value.
+ Also, repair any damage from a false match due to a leap second. */
+ int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
+ if (! time_t_int_add_ok (t, sec_requested))
+ return -1;
+ t1 = t + sec_requested;
+ if (! time_t_int_add_ok (t1, sec_adjustment))
+ return -1;
+ t2 = t1 + sec_adjustment;
+ if (! convert (&t2, &tm))
+ return -1;
+ t = t2;
+ }
+
+ *tp = tm;
+ return t;
+}
+
+
+/* FIXME: This should use a signed type wide enough to hold any UTC
+ offset in seconds. 'int' should be good enough for GNU code. We
+ can't fix this unilaterally though, as other modules invoke
+ __mktime_internal. */
+static time_t localtime_offset;
+
+/* Convert *TP to a time_t value. */
+time_t
+mktime (struct tm *tp)
+{
+#ifdef _LIBC
+ /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
+ time zone names contained in the external variable 'tzname' shall
+ be set as if the tzset() function had been called. */
+ __tzset ();
+#endif
+
+ return __mktime_internal (tp, __localtime_r, &localtime_offset);
+}
+
+#ifdef weak_alias
+weak_alias (mktime, timelocal)
+#endif
+
+#ifdef _LIBC
+libc_hidden_def (mktime)
+libc_hidden_weak (timelocal)
+#endif
+
+#if defined DEBUG_MKTIME && DEBUG_MKTIME
+
+static int
+not_equal_tm (const struct tm *a, const struct tm *b)
+{
+ return ((a->tm_sec ^ b->tm_sec)
+ | (a->tm_min ^ b->tm_min)
+ | (a->tm_hour ^ b->tm_hour)
+ | (a->tm_mday ^ b->tm_mday)
+ | (a->tm_mon ^ b->tm_mon)
+ | (a->tm_year ^ b->tm_year)
+ | (a->tm_yday ^ b->tm_yday)
+ | isdst_differ (a->tm_isdst, b->tm_isdst));
+}
+
+static void
+print_tm (const struct tm *tp)
+{
+ if (tp)
+ printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
+ tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec,
+ tp->tm_yday, tp->tm_wday, tp->tm_isdst);
+ else
+ printf ("0");
+}
+
+static int
+check_result (time_t tk, struct tm tmk, time_t tl, const struct tm *lt)
+{
+ if (tk != tl || !lt || not_equal_tm (&tmk, lt))
+ {
+ printf ("mktime (");
+ print_tm (lt);
+ printf (")\nyields (");
+ print_tm (&tmk);
+ printf (") == %ld, should be %ld\n", (long int) tk, (long int) tl);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ int status = 0;
+ struct tm tm, tmk, tml;
+ struct tm *lt;
+ time_t tk, tl, tl1;
+ char trailer;
+
+ if ((argc == 3 || argc == 4)
+ && (sscanf (argv[1], "%d-%d-%d%c",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
+ == 3)
+ && (sscanf (argv[2], "%d:%d:%d%c",
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
+ == 3))
+ {
+ tm.tm_year -= TM_YEAR_BASE;
+ tm.tm_mon--;
+ tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
+ tmk = tm;
+ tl = mktime (&tmk);
+ lt = localtime (&tl);
+ if (lt)
+ {
+ tml = *lt;
+ lt = &tml;
+ }
+ printf ("mktime returns %ld == ", (long int) tl);
+ print_tm (&tmk);
+ printf ("\n");
+ status = check_result (tl, tmk, tl, lt);
+ }
+ else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
+ {
+ time_t from = atol (argv[1]);
+ time_t by = atol (argv[2]);
+ time_t to = atol (argv[3]);
+
+ if (argc == 4)
+ for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
+ {
+ lt = localtime (&tl);
+ if (lt)
+ {
+ tmk = tml = *lt;
+ tk = mktime (&tmk);
+ status |= check_result (tk, tmk, tl, &tml);
+ }
+ else
+ {
+ printf ("localtime (%ld) yields 0\n", (long int) tl);
+ status = 1;
+ }
+ tl1 = tl + by;
+ if ((tl1 < tl) != (by < 0))
+ break;
+ }
+ else
+ for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
+ {
+ /* Null benchmark. */
+ lt = localtime (&tl);
+ if (lt)
+ {
+ tmk = tml = *lt;
+ tk = tl;
+ status |= check_result (tk, tmk, tl, &tml);
+ }
+ else
+ {
+ printf ("localtime (%ld) yields 0\n", (long int) tl);
+ status = 1;
+ }
+ tl1 = tl + by;
+ if ((tl1 < tl) != (by < 0))
+ break;
+ }
+ }
+ else
+ printf ("Usage:\
+\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
+\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
+\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
+ argv[0], argv[0], argv[0]);
+
+ return status;
+}
+
+#endif /* DEBUG_MKTIME */
+
+/*
+Local Variables:
+compile-command: "gcc -DDEBUG_MKTIME -I. -Wall -W -O2 -g mktime.c -o mktime"
+End:
+*/
diff --git a/REORG.TODO/time/offtime.c b/REORG.TODO/time/offtime.c
new file mode 100644
index 0000000000..75a28fed84
--- /dev/null
+++ b/REORG.TODO/time/offtime.c
@@ -0,0 +1,86 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <time.h>
+
+#define SECS_PER_HOUR (60 * 60)
+#define SECS_PER_DAY (SECS_PER_HOUR * 24)
+
+/* Compute the `struct tm' representation of *T,
+ offset OFFSET seconds east of UTC,
+ and store year, yday, mon, mday, wday, hour, min, sec into *TP.
+ Return nonzero if successful. */
+int
+__offtime (const time_t *t, long int offset, struct tm *tp)
+{
+ time_t days, rem, y;
+ const unsigned short int *ip;
+
+ days = *t / SECS_PER_DAY;
+ rem = *t % SECS_PER_DAY;
+ rem += offset;
+ while (rem < 0)
+ {
+ rem += SECS_PER_DAY;
+ --days;
+ }
+ while (rem >= SECS_PER_DAY)
+ {
+ rem -= SECS_PER_DAY;
+ ++days;
+ }
+ tp->tm_hour = rem / SECS_PER_HOUR;
+ rem %= SECS_PER_HOUR;
+ tp->tm_min = rem / 60;
+ tp->tm_sec = rem % 60;
+ /* January 1, 1970 was a Thursday. */
+ tp->tm_wday = (4 + days) % 7;
+ if (tp->tm_wday < 0)
+ tp->tm_wday += 7;
+ y = 1970;
+
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
+
+ while (days < 0 || days >= (__isleap (y) ? 366 : 365))
+ {
+ /* Guess a corrected year, assuming 365 days per year. */
+ time_t yg = y + days / 365 - (days % 365 < 0);
+
+ /* Adjust DAYS and Y to match the guessed year. */
+ days -= ((yg - y) * 365
+ + LEAPS_THRU_END_OF (yg - 1)
+ - LEAPS_THRU_END_OF (y - 1));
+ y = yg;
+ }
+ tp->tm_year = y - 1900;
+ if (tp->tm_year != y - 1900)
+ {
+ /* The year cannot be represented due to overflow. */
+ __set_errno (EOVERFLOW);
+ return 0;
+ }
+ tp->tm_yday = days;
+ ip = __mon_yday[__isleap(y)];
+ for (y = 11; days < (long int) ip[y]; --y)
+ continue;
+ days -= ip[y];
+ tp->tm_mon = y;
+ tp->tm_mday = days + 1;
+ return 1;
+}
diff --git a/REORG.TODO/time/setitimer.c b/REORG.TODO/time/setitimer.c
new file mode 100644
index 0000000000..65d85a79af
--- /dev/null
+++ b/REORG.TODO/time/setitimer.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+
+/* Set the timer WHICH to *NEW. If OLD is not NULL,
+ set *OLD to the old value of timer WHICH.
+ Returns 0 on success, -1 on errors. */
+int
+__setitimer (enum __itimer_which which, const struct itimerval *new,
+ struct itimerval *old)
+{
+ if (new == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (setitimer)
+
+weak_alias (__setitimer, setitimer)
diff --git a/REORG.TODO/time/settimeofday.c b/REORG.TODO/time/settimeofday.c
new file mode 100644
index 0000000000..317c93d35f
--- /dev/null
+++ b/REORG.TODO/time/settimeofday.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sys/time.h>
+
+/* Set the current time of day and timezone information.
+ This call is restricted to the super-user. */
+int
+__settimeofday (const struct timeval *tv, const struct timezone *tz)
+{
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (settimeofday)
+
+weak_alias (__settimeofday, settimeofday)
diff --git a/REORG.TODO/time/stime.c b/REORG.TODO/time/stime.c
new file mode 100644
index 0000000000..723eedacf1
--- /dev/null
+++ b/REORG.TODO/time/stime.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1992-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <time.h>
+#include <stddef.h>
+
+/* Set the system clock to *WHEN. */
+
+int
+stime (const time_t *when)
+{
+ if (when == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+
+stub_warning (stime)
diff --git a/REORG.TODO/time/strftime.c b/REORG.TODO/time/strftime.c
new file mode 100644
index 0000000000..eeab20e2b3
--- /dev/null
+++ b/REORG.TODO/time/strftime.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <time.h>
+#include <locale/localeinfo.h>
+
+
+size_t
+strftime (char *s, size_t maxsize, const char *format, const struct tm *tp)
+{
+ return __strftime_l (s, maxsize, format, tp, _NL_CURRENT_LOCALE);
+}
+libc_hidden_def (strftime)
diff --git a/REORG.TODO/time/strftime_l.c b/REORG.TODO/time/strftime_l.c
new file mode 100644
index 0000000000..eb3efb8129
--- /dev/null
+++ b/REORG.TODO/time/strftime_l.c
@@ -0,0 +1,1425 @@
+/* Copyright (C) 2002-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define USE_IN_EXTENDED_LOCALE_MODEL 1
+# define HAVE_LIMITS_H 1
+# define HAVE_MBLEN 1
+# define HAVE_MBRLEN 1
+# define HAVE_STRUCT_ERA_ENTRY 1
+# define HAVE_TM_GMTOFF 1
+# define HAVE_TM_ZONE 1
+# define HAVE_TZNAME 1
+# define HAVE_TZSET 1
+# define HAVE_STRFTIME 0
+# define MULTIBYTE_IS_FORMAT_SAFE 1
+# define STDC_HEADERS 1
+# include "../locale/localeinfo.h"
+#endif
+
+#if defined emacs && !defined HAVE_BCOPY
+# define HAVE_MEMCPY 1
+#endif
+
+#include <ctype.h>
+#include <sys/types.h> /* Some systems define `time_t' here. */
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#if HAVE_TZNAME
+extern char *tzname[];
+#endif
+
+/* Do multibyte processing if multibytes are supported, unless
+ multibyte sequences are safe in formats. Multibyte sequences are
+ safe if they cannot contain byte sequences that look like format
+ conversion specifications. The GNU C Library uses UTF8 multibyte
+ encoding, which is safe for formats, but strftime.c can be used
+ with other C libraries that use unsafe encodings. */
+#define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
+
+#if DO_MULTIBYTE
+# if HAVE_MBRLEN
+# include <wchar.h>
+# else
+ /* Simulate mbrlen with mblen as best we can. */
+# define mbstate_t int
+# define mbrlen(s, n, ps) mblen (s, n)
+# define mbsinit(ps) (*(ps) == 0)
+# endif
+ static const mbstate_t mbstate_zero;
+#endif
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#if STDC_HEADERS
+# include <stddef.h>
+# include <stdlib.h>
+# include <string.h>
+# include <stdbool.h>
+#else
+# ifndef HAVE_MEMCPY
+# define memcpy(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#ifdef COMPILE_WIDE
+# include <endian.h>
+# define CHAR_T wchar_t
+# define UCHAR_T unsigned int
+# define L_(Str) L##Str
+# define NLW(Sym) _NL_W##Sym
+
+# define MEMCPY(d, s, n) __wmemcpy (d, s, n)
+# define STRLEN(s) __wcslen (s)
+
+#else
+# define CHAR_T char
+# define UCHAR_T unsigned char
+# define L_(Str) Str
+# define NLW(Sym) Sym
+
+# if !defined STDC_HEADERS && !defined HAVE_MEMCPY
+# define MEMCPY(d, s, n) bcopy ((s), (d), (n))
+# else
+# define MEMCPY(d, s, n) memcpy ((d), (s), (n))
+# endif
+# define STRLEN(s) strlen (s)
+
+# ifdef _LIBC
+# define MEMPCPY(d, s, n) __mempcpy (d, s, n)
+# else
+# ifndef HAVE_MEMPCPY
+# define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
+# endif
+# endif
+#endif
+
+#ifndef PTR
+# define PTR void *
+#endif
+
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+#ifndef NULL
+# define NULL 0
+#endif
+
+#define TYPE_SIGNED(t) ((t) -1 < 0)
+
+/* Bound on length of the string representing an integer value of type t.
+ Subtract one for the sign bit if t is signed;
+ 302 / 1000 is log10 (2) rounded up;
+ add one for integer division truncation;
+ add one more for a minus sign if t is signed. */
+#define INT_STRLEN_BOUND(t) \
+ ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
+
+#define TM_YEAR_BASE 1900
+
+#ifndef __isleap
+/* Nonzero if YEAR is a leap year (every 4 years,
+ except every 100th isn't, and every 400th is). */
+# define __isleap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+#endif
+
+
+#ifdef _LIBC
+# define tzname __tzname
+# define tzset __tzset
+#endif
+
+#if !HAVE_TM_GMTOFF
+/* Portable standalone applications should supply a "time_r.h" that
+ declares a POSIX-compliant localtime_r, for the benefit of older
+ implementations that lack localtime_r or have a nonstandard one.
+ Similarly for gmtime_r. See the gnulib time_r module for one way
+ to implement this. */
+# include "time_r.h"
+# undef __gmtime_r
+# undef __localtime_r
+# define __gmtime_r gmtime_r
+# define __localtime_r localtime_r
+#endif
+
+
+#if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
+/* Some systems lack the `memset' function and we don't want to
+ introduce additional dependencies. */
+/* The SGI compiler reportedly barfs on the trailing null
+ if we use a string constant as the initializer. 28 June 1997, rms. */
+static const CHAR_T spaces[16] = /* " " */
+{
+ L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
+ L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
+};
+static const CHAR_T zeroes[16] = /* "0000000000000000" */
+{
+ L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
+ L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
+};
+
+# define memset_space(P, Len) \
+ do { \
+ int _len = (Len); \
+ \
+ do \
+ { \
+ int _this = _len > 16 ? 16 : _len; \
+ (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
+ _len -= _this; \
+ } \
+ while (_len > 0); \
+ } while (0)
+
+# define memset_zero(P, Len) \
+ do { \
+ int _len = (Len); \
+ \
+ do \
+ { \
+ int _this = _len > 16 ? 16 : _len; \
+ (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
+ _len -= _this; \
+ } \
+ while (_len > 0); \
+ } while (0)
+#else
+# ifdef COMPILE_WIDE
+# define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
+# define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
+# else
+# define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
+# define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
+# endif
+#endif
+
+#define add(n, f) \
+ do \
+ { \
+ int _n = (n); \
+ int _delta = width - _n; \
+ int _incr = _n + (_delta > 0 ? _delta : 0); \
+ if ((size_t) _incr >= maxsize - i) \
+ return 0; \
+ if (p) \
+ { \
+ if (_delta > 0) \
+ { \
+ if (pad == L_('0')) \
+ memset_zero (p, _delta); \
+ else \
+ memset_space (p, _delta); \
+ } \
+ f; \
+ p += _n; \
+ } \
+ i += _incr; \
+ } while (0)
+
+#define cpy(n, s) \
+ add ((n), \
+ if (to_lowcase) \
+ memcpy_lowcase (p, (s), _n LOCALE_ARG); \
+ else if (to_uppcase) \
+ memcpy_uppcase (p, (s), _n LOCALE_ARG); \
+ else \
+ MEMCPY ((PTR) p, (const PTR) (s), _n))
+
+#ifdef COMPILE_WIDE
+# ifndef USE_IN_EXTENDED_LOCALE_MODEL
+# undef __mbsrtowcs_l
+# define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
+# endif
+# define widen(os, ws, l) \
+ { \
+ mbstate_t __st; \
+ const char *__s = os; \
+ memset (&__st, '\0', sizeof (__st)); \
+ l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
+ ws = alloca ((l + 1) * sizeof (wchar_t)); \
+ (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
+ }
+#endif
+
+
+#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
+/* We use this code also for the extended locale handling where the
+ function gets as an additional argument the locale which has to be
+ used. To access the values we have to redefine the _NL_CURRENT
+ macro. */
+# define strftime __strftime_l
+# define wcsftime __wcsftime_l
+# undef _NL_CURRENT
+# define _NL_CURRENT(category, item) \
+ (current->values[_NL_ITEM_INDEX (item)].string)
+# define LOCALE_PARAM , __locale_t loc
+# define LOCALE_ARG , loc
+# define HELPER_LOCALE_ARG , current
+#else
+# define LOCALE_PARAM
+# define LOCALE_ARG
+# ifdef _LIBC
+# define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
+# else
+# define HELPER_LOCALE_ARG
+# endif
+#endif
+
+#ifdef COMPILE_WIDE
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define TOUPPER(Ch, L) __towupper_l (Ch, L)
+# define TOLOWER(Ch, L) __towlower_l (Ch, L)
+# else
+# define TOUPPER(Ch, L) towupper (Ch)
+# define TOLOWER(Ch, L) towlower (Ch)
+# endif
+#else
+# ifdef _LIBC
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define TOUPPER(Ch, L) __toupper_l (Ch, L)
+# define TOLOWER(Ch, L) __tolower_l (Ch, L)
+# else
+# define TOUPPER(Ch, L) toupper (Ch)
+# define TOLOWER(Ch, L) tolower (Ch)
+# endif
+# else
+# define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
+# define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
+# endif
+#endif
+/* We don't use `isdigit' here since the locale dependent
+ interpretation is not what we want here. We only need to accept
+ the arabic digits in the ASCII range. One day there is perhaps a
+ more reliable way to accept other sets of digits. */
+#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
+
+static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
+ size_t len LOCALE_PARAM) __THROW;
+
+static CHAR_T *
+memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
+{
+ while (len-- > 0)
+ dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
+ return dest;
+}
+
+static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
+ size_t len LOCALE_PARAM) __THROW;
+
+static CHAR_T *
+memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
+{
+ while (len-- > 0)
+ dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
+ return dest;
+}
+
+
+#if ! HAVE_TM_GMTOFF
+/* Yield the difference between *A and *B,
+ measured in seconds, ignoring leap seconds. */
+# define tm_diff ftime_tm_diff
+static int tm_diff (const struct tm *, const struct tm *) __THROW;
+static int
+tm_diff (const struct tm *a, const struct tm *b)
+{
+ /* Compute intervening leap days correctly even if year is negative.
+ Take care to avoid int overflow in leap day calculations,
+ but it's OK to assume that A and B are close to each other. */
+ int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
+ int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
+ int a100 = a4 / 25 - (a4 % 25 < 0);
+ int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a400 = a100 >> 2;
+ int b400 = b100 >> 2;
+ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+ int years = a->tm_year - b->tm_year;
+ int days = (365 * years + intervening_leap_days
+ + (a->tm_yday - b->tm_yday));
+ return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+#endif /* ! HAVE_TM_GMTOFF */
+
+
+
+/* The number of days from the first day of the first ISO week of this
+ year to the year day YDAY with week day WDAY. ISO weeks start on
+ Monday; the first ISO week has the year's first Thursday. YDAY may
+ be as small as YDAY_MINIMUM. */
+#define ISO_WEEK_START_WDAY 1 /* Monday */
+#define ISO_WEEK1_WDAY 4 /* Thursday */
+#define YDAY_MINIMUM (-366)
+static int iso_week_days (int, int) __THROW;
+#ifdef __GNUC__
+__inline__
+#endif
+static int
+iso_week_days (int yday, int wday)
+{
+ /* Add enough to the first operand of % to make it nonnegative. */
+ int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
+ return (yday
+ - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
+ + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
+}
+
+
+#if !(defined _NL_CURRENT || HAVE_STRFTIME)
+static CHAR_T const weekday_name[][10] =
+ {
+ L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
+ L_("Thursday"), L_("Friday"), L_("Saturday")
+ };
+static CHAR_T const month_name[][10] =
+ {
+ L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
+ L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
+ L_("November"), L_("December")
+ };
+#endif
+
+
+#ifdef emacs
+# define my_strftime emacs_strftimeu
+# define ut_argument , ut
+# define ut_argument_spec , int ut
+#else
+# ifdef COMPILE_WIDE
+# define my_strftime wcsftime
+# define nl_get_alt_digit _nl_get_walt_digit
+# else
+# define my_strftime strftime
+# define nl_get_alt_digit _nl_get_alt_digit
+# endif
+# define ut_argument
+# define ut_argument_spec
+/* We don't have this information in general. */
+# define ut 0
+#endif
+
+static size_t __strftime_internal (CHAR_T *, size_t, const CHAR_T *,
+ const struct tm *, bool *
+ ut_argument_spec
+ LOCALE_PARAM) __THROW;
+
+/* Write information from TP into S according to the format
+ string FORMAT, writing no more that MAXSIZE characters
+ (including the terminating '\0') and returning number of
+ characters written. If S is NULL, nothing will be written
+ anywhere, so to determine how many characters would be
+ written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
+
+size_t
+my_strftime (CHAR_T *s, size_t maxsize, const CHAR_T *format,
+ const struct tm *tp ut_argument_spec LOCALE_PARAM)
+{
+#if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
+ /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
+ Work around this bug by copying *tp before it might be munged. */
+ struct tm tmcopy;
+ tmcopy = *tp;
+ tp = &tmcopy;
+#endif
+ bool tzset_called = false;
+ return __strftime_internal (s, maxsize, format, tp, &tzset_called
+ ut_argument LOCALE_ARG);
+}
+#ifdef _LIBC
+libc_hidden_def (my_strftime)
+#endif
+
+static size_t
+__strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format,
+ const struct tm *tp, bool *tzset_called
+ ut_argument_spec LOCALE_PARAM)
+{
+#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
+ struct __locale_data *const current = loc->__locales[LC_TIME];
+#endif
+
+ int hour12 = tp->tm_hour;
+#ifdef _NL_CURRENT
+ /* We cannot make the following values variables since we must delay
+ the evaluation of these values until really needed since some
+ expressions might not be valid in every situation. The `struct tm'
+ might be generated by a strptime() call that initialized
+ only a few elements. Dereference the pointers only if the format
+ requires this. Then it is ok to fail if the pointers are invalid. */
+# define a_wkday \
+ ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
+# define f_wkday \
+ ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
+# define a_month \
+ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
+# define f_month \
+ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
+# define ampm \
+ ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
+ ? NLW(PM_STR) : NLW(AM_STR)))
+
+# define aw_len STRLEN (a_wkday)
+# define am_len STRLEN (a_month)
+# define ap_len STRLEN (ampm)
+#else
+# if !HAVE_STRFTIME
+# define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6 \
+ ? "?" : weekday_name[tp->tm_wday])
+# define f_month (tp->tm_mon < 0 || tp->tm_mon > 11 \
+ ? "?" : month_name[tp->tm_mon])
+# define a_wkday f_wkday
+# define a_month f_month
+# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
+
+ size_t aw_len = 3;
+ size_t am_len = 3;
+ size_t ap_len = 2;
+# endif
+#endif
+ const char *zone;
+ size_t i = 0;
+ CHAR_T *p = s;
+ const CHAR_T *f;
+#if DO_MULTIBYTE && !defined COMPILE_WIDE
+ const char *format_end = NULL;
+#endif
+
+ zone = NULL;
+#if HAVE_TM_ZONE
+ /* The POSIX test suite assumes that setting
+ the environment variable TZ to a new value before calling strftime()
+ will influence the result (the %Z format) even if the information in
+ TP is computed with a totally different time zone.
+ This is bogus: though POSIX allows bad behavior like this,
+ POSIX does not require it. Do the right thing instead. */
+ zone = (const char *) tp->tm_zone;
+#endif
+#if HAVE_TZNAME
+ if (ut)
+ {
+ if (! (zone && *zone))
+ zone = "GMT";
+ }
+#endif
+
+ if (hour12 > 12)
+ hour12 -= 12;
+ else
+ if (hour12 == 0)
+ hour12 = 12;
+
+ for (f = format; *f != '\0'; ++f)
+ {
+ int pad = 0; /* Padding for number ('-', '_', or 0). */
+ int modifier; /* Field modifier ('E', 'O', or 0). */
+ int digits; /* Max digits for numeric format. */
+ int number_value; /* Numeric value to be printed. */
+ int negative_number; /* 1 if the number is negative. */
+ const CHAR_T *subfmt;
+ CHAR_T *bufp;
+ CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
+ ? INT_STRLEN_BOUND (time_t)
+ : INT_STRLEN_BOUND (int))];
+ int width = -1;
+ int to_lowcase = 0;
+ int to_uppcase = 0;
+ int change_case = 0;
+ int format_char;
+
+#if DO_MULTIBYTE && !defined COMPILE_WIDE
+ switch (*f)
+ {
+ case L_('%'):
+ break;
+
+ case L_('\b'): case L_('\t'): case L_('\n'):
+ case L_('\v'): case L_('\f'): case L_('\r'):
+ case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
+ case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
+ case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
+ case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
+ case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
+ case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
+ case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
+ case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
+ case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
+ case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
+ case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
+ case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
+ case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
+ case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
+ case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
+ case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
+ case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
+ case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
+ case L_('~'):
+ /* The C Standard requires these 98 characters (plus '%') to
+ be in the basic execution character set. None of these
+ characters can start a multibyte sequence, so they need
+ not be analyzed further. */
+ add (1, *p = *f);
+ continue;
+
+ default:
+ /* Copy this multibyte sequence until we reach its end, find
+ an error, or come back to the initial shift state. */
+ {
+ mbstate_t mbstate = mbstate_zero;
+ size_t len = 0;
+ size_t fsize;
+
+ if (! format_end)
+ format_end = f + strlen (f) + 1;
+ fsize = format_end - f;
+
+ do
+ {
+ size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
+
+ if (bytes == 0)
+ break;
+
+ if (bytes == (size_t) -2)
+ {
+ len += strlen (f + len);
+ break;
+ }
+
+ if (bytes == (size_t) -1)
+ {
+ len++;
+ break;
+ }
+
+ len += bytes;
+ }
+ while (! mbsinit (&mbstate));
+
+ cpy (len, f);
+ f += len - 1;
+ continue;
+ }
+ }
+
+#else /* ! DO_MULTIBYTE */
+
+ /* Either multibyte encodings are not supported, they are
+ safe for formats, so any non-'%' byte can be copied through,
+ or this is the wide character version. */
+ if (*f != L_('%'))
+ {
+ add (1, *p = *f);
+ continue;
+ }
+
+#endif /* ! DO_MULTIBYTE */
+
+ /* Check for flags that can modify a format. */
+ while (1)
+ {
+ switch (*++f)
+ {
+ /* This influences the number formats. */
+ case L_('_'):
+ case L_('-'):
+ case L_('0'):
+ pad = *f;
+ continue;
+
+ /* This changes textual output. */
+ case L_('^'):
+ to_uppcase = 1;
+ continue;
+ case L_('#'):
+ change_case = 1;
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ /* As a GNU extension we allow to specify the field width. */
+ if (ISDIGIT (*f))
+ {
+ width = 0;
+ do
+ {
+ if (width > INT_MAX / 10
+ || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
+ /* Avoid overflow. */
+ width = INT_MAX;
+ else
+ {
+ width *= 10;
+ width += *f - L_('0');
+ }
+ ++f;
+ }
+ while (ISDIGIT (*f));
+ }
+
+ /* Check for modifiers. */
+ switch (*f)
+ {
+ case L_('E'):
+ case L_('O'):
+ modifier = *f++;
+ break;
+
+ default:
+ modifier = 0;
+ break;
+ }
+
+ /* Now do the specified format. */
+ format_char = *f;
+ switch (format_char)
+ {
+#define DO_NUMBER(d, v) \
+ digits = d > width ? d : width; \
+ number_value = v; goto do_number
+#define DO_NUMBER_SPACEPAD(d, v) \
+ digits = d > width ? d : width; \
+ number_value = v; goto do_number_spacepad
+
+ case L_('%'):
+ if (modifier != 0)
+ goto bad_format;
+ add (1, *p = *f);
+ break;
+
+ case L_('a'):
+ if (modifier != 0)
+ goto bad_format;
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (aw_len, a_wkday);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case 'A':
+ if (modifier != 0)
+ goto bad_format;
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (STRLEN (f_wkday), f_wkday);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('b'):
+ case L_('h'):
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+ if (modifier != 0)
+ goto bad_format;
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (am_len, a_month);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('B'):
+ if (modifier != 0)
+ goto bad_format;
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (STRLEN (f_month), f_month);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('c'):
+ if (modifier == L_('O'))
+ goto bad_format;
+#ifdef _NL_CURRENT
+ if (! (modifier == 'E'
+ && (*(subfmt =
+ (const CHAR_T *) _NL_CURRENT (LC_TIME,
+ NLW(ERA_D_T_FMT)))
+ != '\0')))
+ subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# else
+ subfmt = L_("%a %b %e %H:%M:%S %Y");
+# endif
+#endif
+
+ subformat:
+ {
+ CHAR_T *old_start = p;
+ size_t len = __strftime_internal (NULL, (size_t) -1, subfmt,
+ tp, tzset_called ut_argument
+ LOCALE_ARG);
+ add (len, __strftime_internal (p, maxsize - i, subfmt,
+ tp, tzset_called ut_argument
+ LOCALE_ARG));
+
+ if (to_uppcase)
+ while (old_start < p)
+ {
+ *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
+ ++old_start;
+ }
+ }
+ break;
+
+#if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
+ underlying_strftime:
+ {
+ /* The relevant information is available only via the
+ underlying strftime implementation, so use that. */
+ char ufmt[4];
+ char *u = ufmt;
+ char ubuf[1024]; /* enough for any single format in practice */
+ size_t len;
+ /* Make sure we're calling the actual underlying strftime.
+ In some cases, config.h contains something like
+ "#define strftime rpl_strftime". */
+# ifdef strftime
+# undef strftime
+ size_t strftime ();
+# endif
+
+ *u++ = '%';
+ if (modifier != 0)
+ *u++ = modifier;
+ *u++ = format_char;
+ *u = '\0';
+ len = strftime (ubuf, sizeof ubuf, ufmt, tp);
+ if (len == 0 && ubuf[0] != '\0')
+ return 0;
+ cpy (len, ubuf);
+ }
+ break;
+#endif
+
+ case L_('C'):
+ if (modifier == L_('E'))
+ {
+#if HAVE_STRUCT_ERA_ENTRY
+ struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
+ if (era)
+ {
+# ifdef COMPILE_WIDE
+ size_t len = __wcslen (era->era_wname);
+ cpy (len, era->era_wname);
+# else
+ size_t len = strlen (era->era_name);
+ cpy (len, era->era_name);
+# endif
+ break;
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+
+ {
+ int year = tp->tm_year + TM_YEAR_BASE;
+ DO_NUMBER (1, year / 100 - (year % 100 < 0));
+ }
+
+ case L_('x'):
+ if (modifier == L_('O'))
+ goto bad_format;
+#ifdef _NL_CURRENT
+ if (! (modifier == L_('E')
+ && (*(subfmt =
+ (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
+ != L_('\0'))))
+ subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
+ goto subformat;
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# else
+ /* Fall through. */
+# endif
+#endif
+ case L_('D'):
+ if (modifier != 0)
+ goto bad_format;
+ subfmt = L_("%m/%d/%y");
+ goto subformat;
+
+ case L_('d'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_mday);
+
+ case L_('e'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER_SPACEPAD (2, tp->tm_mday);
+
+ /* All numeric formats set DIGITS and NUMBER_VALUE and then
+ jump to one of these two labels. */
+
+ do_number_spacepad:
+ /* Force `_' flag unless overwritten by `0' or '-' flag. */
+ if (pad != L_('0') && pad != L_('-'))
+ pad = L_('_');
+
+ do_number:
+ /* Format the number according to the MODIFIER flag. */
+
+ if (modifier == L_('O') && 0 <= number_value)
+ {
+#ifdef _NL_CURRENT
+ /* Get the locale specific alternate representation of
+ the number NUMBER_VALUE. If none exist NULL is returned. */
+ const CHAR_T *cp = nl_get_alt_digit (number_value
+ HELPER_LOCALE_ARG);
+
+ if (cp != NULL)
+ {
+ size_t digitlen = STRLEN (cp);
+ if (digitlen != 0)
+ {
+ cpy (digitlen, cp);
+ break;
+ }
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+ {
+ unsigned int u = number_value;
+
+ bufp = buf + sizeof (buf) / sizeof (buf[0]);
+ negative_number = number_value < 0;
+
+ if (negative_number)
+ u = -u;
+
+ do
+ *--bufp = u % 10 + L_('0');
+ while ((u /= 10) != 0);
+ }
+
+ do_number_sign_and_padding:
+ if (negative_number)
+ *--bufp = L_('-');
+
+ if (pad != L_('-'))
+ {
+ int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
+ - bufp);
+
+ if (padding > 0)
+ {
+ if (pad == L_('_'))
+ {
+ if ((size_t) padding >= maxsize - i)
+ return 0;
+
+ if (p)
+ memset_space (p, padding);
+ i += padding;
+ width = width > padding ? width - padding : 0;
+ }
+ else
+ {
+ if ((size_t) digits >= maxsize - i)
+ return 0;
+
+ if (negative_number)
+ {
+ ++bufp;
+
+ if (p)
+ *p++ = L_('-');
+ ++i;
+ }
+
+ if (p)
+ memset_zero (p, padding);
+ i += padding;
+ width = 0;
+ }
+ }
+ }
+
+ cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
+ break;
+
+ case L_('F'):
+ if (modifier != 0)
+ goto bad_format;
+ subfmt = L_("%Y-%m-%d");
+ goto subformat;
+
+ case L_('H'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_hour);
+
+ case L_('I'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, hour12);
+
+ case L_('k'): /* GNU extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER_SPACEPAD (2, tp->tm_hour);
+
+ case L_('l'): /* GNU extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER_SPACEPAD (2, hour12);
+
+ case L_('j'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (3, 1 + tp->tm_yday);
+
+ case L_('M'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_min);
+
+ case L_('m'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_mon + 1);
+
+ case L_('n'):
+ add (1, *p = L_('\n'));
+ break;
+
+ case L_('P'):
+ to_lowcase = 1;
+#if !defined _NL_CURRENT && HAVE_STRFTIME
+ format_char = L_('p');
+#endif
+ /* FALLTHROUGH */
+
+ case L_('p'):
+ if (change_case)
+ {
+ to_uppcase = 0;
+ to_lowcase = 1;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (ap_len, ampm);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('R'):
+ subfmt = L_("%H:%M");
+ goto subformat;
+
+ case L_('r'):
+#if !defined _NL_CURRENT && HAVE_STRFTIME
+ goto underlying_strftime;
+#else
+# ifdef _NL_CURRENT
+ if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
+ NLW(T_FMT_AMPM)))
+ == L_('\0'))
+# endif
+ subfmt = L_("%I:%M:%S %p");
+ goto subformat;
+#endif
+
+ case L_('S'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_sec);
+
+ case L_('s'): /* GNU extension. */
+ {
+ struct tm ltm;
+ time_t t;
+
+ ltm = *tp;
+ t = mktime (&ltm);
+
+ /* Generate string value for T using time_t arithmetic;
+ this works even if sizeof (long) < sizeof (time_t). */
+
+ bufp = buf + sizeof (buf) / sizeof (buf[0]);
+ negative_number = t < 0;
+
+ do
+ {
+ int d = t % 10;
+ t /= 10;
+
+ if (negative_number)
+ {
+ d = -d;
+
+ /* Adjust if division truncates to minus infinity. */
+ if (0 < -1 % 10 && d < 0)
+ {
+ t++;
+ d += 10;
+ }
+ }
+
+ *--bufp = d + L_('0');
+ }
+ while (t != 0);
+
+ digits = 1;
+ goto do_number_sign_and_padding;
+ }
+
+ case L_('X'):
+ if (modifier == L_('O'))
+ goto bad_format;
+#ifdef _NL_CURRENT
+ if (! (modifier == L_('E')
+ && (*(subfmt =
+ (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
+ != L_('\0'))))
+ subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
+ goto subformat;
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# else
+ /* Fall through. */
+# endif
+#endif
+ case L_('T'):
+ subfmt = L_("%H:%M:%S");
+ goto subformat;
+
+ case L_('t'):
+ add (1, *p = L_('\t'));
+ break;
+
+ case L_('u'):
+ DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
+
+ case L_('U'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
+
+ case L_('V'):
+ case L_('g'):
+ case L_('G'):
+ if (modifier == L_('E'))
+ goto bad_format;
+ {
+ int year = tp->tm_year + TM_YEAR_BASE;
+ int days = iso_week_days (tp->tm_yday, tp->tm_wday);
+
+ if (days < 0)
+ {
+ /* This ISO week belongs to the previous year. */
+ year--;
+ days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
+ tp->tm_wday);
+ }
+ else
+ {
+ int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
+ tp->tm_wday);
+ if (0 <= d)
+ {
+ /* This ISO week belongs to the next year. */
+ year++;
+ days = d;
+ }
+ }
+
+ switch (*f)
+ {
+ case L_('g'):
+ DO_NUMBER (2, (year % 100 + 100) % 100);
+
+ case L_('G'):
+ DO_NUMBER (1, year);
+
+ default:
+ DO_NUMBER (2, days / 7 + 1);
+ }
+ }
+
+ case L_('W'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
+
+ case L_('w'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (1, tp->tm_wday);
+
+ case L_('Y'):
+ if (modifier == 'E')
+ {
+#if HAVE_STRUCT_ERA_ENTRY
+ struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
+ if (era)
+ {
+# ifdef COMPILE_WIDE
+ subfmt = era->era_wformat;
+# else
+ subfmt = era->era_format;
+# endif
+ goto subformat;
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+ if (modifier == L_('O'))
+ goto bad_format;
+ else
+ DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
+
+ case L_('y'):
+ if (modifier == L_('E'))
+ {
+#if HAVE_STRUCT_ERA_ENTRY
+ struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
+ if (era)
+ {
+ int delta = tp->tm_year - era->start_date[0];
+ DO_NUMBER (1, (era->offset
+ + delta * era->absolute_direction));
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+ DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
+
+ case L_('Z'):
+ if (change_case)
+ {
+ to_uppcase = 0;
+ to_lowcase = 1;
+ }
+
+#if HAVE_TZNAME
+ /* The tzset() call might have changed the value. */
+ if (!(zone && *zone) && tp->tm_isdst >= 0)
+ {
+ /* POSIX.1 requires that local time zone information is used as
+ though strftime called tzset. */
+# if HAVE_TZSET
+ if (!*tzset_called)
+ {
+ tzset ();
+ *tzset_called = true;
+ }
+# endif
+ zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?";
+ }
+#endif
+ if (! zone)
+ zone = "";
+
+#ifdef COMPILE_WIDE
+ {
+ /* The zone string is always given in multibyte form. We have
+ to transform it first. */
+ wchar_t *wczone;
+ size_t len;
+ widen (zone, wczone, len);
+ cpy (len, wczone);
+ }
+#else
+ cpy (strlen (zone), zone);
+#endif
+ break;
+
+ case L_('z'):
+ if (tp->tm_isdst < 0)
+ break;
+
+ {
+ int diff;
+#if HAVE_TM_GMTOFF
+ diff = tp->tm_gmtoff;
+#else
+ if (ut)
+ diff = 0;
+ else
+ {
+ struct tm gtm;
+ struct tm ltm;
+ time_t lt;
+
+ /* POSIX.1 requires that local time zone information is used as
+ though strftime called tzset. */
+# if HAVE_TZSET
+ if (!*tzset_called)
+ {
+ tzset ();
+ *tzset_called = true;
+ }
+# endif
+
+ ltm = *tp;
+ lt = mktime (&ltm);
+
+ if (lt == (time_t) -1)
+ {
+ /* mktime returns -1 for errors, but -1 is also a
+ valid time_t value. Check whether an error really
+ occurred. */
+ struct tm tm;
+
+ if (! __localtime_r (&lt, &tm)
+ || ((ltm.tm_sec ^ tm.tm_sec)
+ | (ltm.tm_min ^ tm.tm_min)
+ | (ltm.tm_hour ^ tm.tm_hour)
+ | (ltm.tm_mday ^ tm.tm_mday)
+ | (ltm.tm_mon ^ tm.tm_mon)
+ | (ltm.tm_year ^ tm.tm_year)))
+ break;
+ }
+
+ if (! __gmtime_r (&lt, &gtm))
+ break;
+
+ diff = tm_diff (&ltm, &gtm);
+ }
+#endif
+
+ if (diff < 0)
+ {
+ add (1, *p = L_('-'));
+ diff = -diff;
+ }
+ else
+ add (1, *p = L_('+'));
+
+ diff /= 60;
+ DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
+ }
+
+ case L_('\0'): /* GNU extension: % at end of format. */
+ --f;
+ /* Fall through. */
+ default:
+ /* Unknown format; output the format, including the '%',
+ since this is most likely the right thing to do if a
+ multibyte string has been misparsed. */
+ bad_format:
+ {
+ int flen;
+ for (flen = 1; f[1 - flen] != L_('%'); flen++)
+ continue;
+ cpy (flen, &f[1 - flen]);
+ }
+ break;
+ }
+ }
+
+ if (p && maxsize != 0)
+ *p = L_('\0');
+ return i;
+}
+
+
+#ifdef emacs
+/* For Emacs we have a separate interface which corresponds to the normal
+ strftime function and does not have the extra information whether the
+ TP arguments comes from a `gmtime' call or not. */
+size_t
+emacs_strftime (char *s, size_t maxsize, const char *format,
+ const struct tm *tp)
+{
+ return my_strftime (s, maxsize, format, tp, 0);
+}
+#endif
+
+#if defined _LIBC && !defined COMPILE_WIDE
+weak_alias (__strftime_l, strftime_l)
+#endif
diff --git a/REORG.TODO/time/strptime.c b/REORG.TODO/time/strptime.c
new file mode 100644
index 0000000000..06463b364c
--- /dev/null
+++ b/REORG.TODO/time/strptime.c
@@ -0,0 +1,34 @@
+/* Convert a string representation of time to a time value.
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* XXX This version of the implementation is not really complete.
+ Some of the fields cannot add information alone. But if seeing
+ some of them in the same format (such as year, week and weekday)
+ this is enough information for determining the date. */
+
+#include <time.h>
+#include <locale/localeinfo.h>
+
+
+char *
+strptime (const char *buf, const char *format, struct tm *tm)
+{
+ return __strptime_internal (buf, format, tm, NULL, _NL_CURRENT_LOCALE);
+}
+libc_hidden_def (strptime)
diff --git a/REORG.TODO/time/strptime_l.c b/REORG.TODO/time/strptime_l.c
new file mode 100644
index 0000000000..dbf4606982
--- /dev/null
+++ b/REORG.TODO/time/strptime_l.c
@@ -0,0 +1,1211 @@
+/* Copyright (C) 2002-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <string.h>
+#include <time.h>
+#include <stdbool.h>
+
+#ifdef _LIBC
+# define HAVE_LOCALTIME_R 0
+# include "../locale/localeinfo.h"
+#endif
+
+
+#if ! HAVE_LOCALTIME_R && ! defined localtime_r
+# ifdef _LIBC
+# define localtime_r __localtime_r
+# else
+/* Approximate localtime_r as best we can in its absence. */
+# define localtime_r my_localtime_r
+static struct tm *localtime_r (const time_t *, struct tm *);
+static struct tm *
+localtime_r (const time_t *t, struct tm *tp)
+{
+ struct tm *l = localtime (t);
+ if (! l)
+ return 0;
+ *tp = *l;
+ return tp;
+}
+# endif /* ! _LIBC */
+#endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
+
+
+#define match_char(ch1, ch2) if (ch1 != ch2) return NULL
+#if defined __GNUC__ && __GNUC__ >= 2
+# define match_string(cs1, s2) \
+ ({ size_t len = strlen (cs1); \
+ int result = __strncasecmp_l ((cs1), (s2), len, locale) == 0; \
+ if (result) (s2) += len; \
+ result; })
+#else
+/* Oh come on. Get a reasonable compiler. */
+# define match_string(cs1, s2) \
+ (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
+#endif
+/* We intentionally do not use isdigit() for testing because this will
+ lead to problems with the wide character version. */
+#define get_number(from, to, n) \
+ do { \
+ int __n = n; \
+ val = 0; \
+ while (ISSPACE (*rp)) \
+ ++rp; \
+ if (*rp < '0' || *rp > '9') \
+ return NULL; \
+ do { \
+ val *= 10; \
+ val += *rp++ - '0'; \
+ } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \
+ if (val < from || val > to) \
+ return NULL; \
+ } while (0)
+#ifdef _NL_CURRENT
+# define get_alt_number(from, to, n) \
+ ({ \
+ __label__ do_normal; \
+ \
+ if (s.decided != raw) \
+ { \
+ val = _nl_parse_alt_digit (&rp HELPER_LOCALE_ARG); \
+ if (val == -1 && s.decided != loc) \
+ { \
+ s.decided = loc; \
+ goto do_normal; \
+ } \
+ if (val < from || val > to) \
+ return NULL; \
+ } \
+ else \
+ { \
+ do_normal: \
+ get_number (from, to, n); \
+ } \
+ 0; \
+ })
+#else
+# define get_alt_number(from, to, n) \
+ /* We don't have the alternate representation. */ \
+ get_number(from, to, n)
+#endif
+#define recursive(new_fmt) \
+ (*(new_fmt) != '\0' \
+ && (rp = __strptime_internal (rp, (new_fmt), tm, &s LOCALE_ARG)) != NULL)
+
+
+#ifdef _LIBC
+/* This is defined in locale/C-time.c in the GNU libc. */
+extern const struct __locale_data _nl_C_LC_TIME attribute_hidden;
+
+# define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
+# define ab_weekday_name \
+ (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
+# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
+# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
+# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
+# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
+# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
+# define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
+# define HERE_T_FMT_AMPM \
+ (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
+# define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
+
+# define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
+#else
+static char const weekday_name[][10] =
+ {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"
+ };
+static char const ab_weekday_name[][4] =
+ {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ };
+static char const month_name[][10] =
+ {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+ };
+static char const ab_month_name[][4] =
+ {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
+# define HERE_D_FMT "%m/%d/%y"
+# define HERE_AM_STR "AM"
+# define HERE_PM_STR "PM"
+# define HERE_T_FMT_AMPM "%I:%M:%S %p"
+# define HERE_T_FMT "%H:%M:%S"
+
+static const unsigned short int __mon_yday[2][13] =
+ {
+ /* Normal years. */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ /* Leap years. */
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+ };
+#endif
+
+#if defined _LIBC
+/* We use this code also for the extended locale handling where the
+ function gets as an additional argument the locale which has to be
+ used. To access the values we have to redefine the _NL_CURRENT
+ macro. */
+# define strptime __strptime_l
+# undef _NL_CURRENT
+# define _NL_CURRENT(category, item) \
+ (current->values[_NL_ITEM_INDEX (item)].string)
+# undef _NL_CURRENT_WORD
+# define _NL_CURRENT_WORD(category, item) \
+ (current->values[_NL_ITEM_INDEX (item)].word)
+# define LOCALE_PARAM , __locale_t locale
+# define LOCALE_ARG , locale
+# define HELPER_LOCALE_ARG , current
+# define ISSPACE(Ch) __isspace_l (Ch, locale)
+#else
+# define LOCALE_PARAM
+# define LOCALE_ARG
+# define HELPER_LOCALE_ARG
+# define ISSPACE(Ch) isspace (Ch)
+#endif
+
+
+
+
+#ifndef __isleap
+/* Nonzero if YEAR is a leap year (every 4 years,
+ except every 100th isn't, and every 400th is). */
+# define __isleap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+#endif
+
+/* Compute the day of the week. */
+static void
+day_of_the_week (struct tm *tm)
+{
+ /* We know that January 1st 1970 was a Thursday (= 4). Compute the
+ difference between this data in the one on TM and so determine
+ the weekday. */
+ int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
+ int wday = (-473
+ + (365 * (tm->tm_year - 70))
+ + (corr_year / 4)
+ - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
+ + (((corr_year / 4) / 25) / 4)
+ + __mon_yday[0][tm->tm_mon]
+ + tm->tm_mday - 1);
+ tm->tm_wday = ((wday % 7) + 7) % 7;
+}
+
+/* Compute the day of the year. */
+static void
+day_of_the_year (struct tm *tm)
+{
+ tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
+ + (tm->tm_mday - 1));
+}
+
+
+#ifdef _LIBC
+char *
+internal_function
+#else
+static char *
+#endif
+__strptime_internal (const char *rp, const char *fmt, struct tm *tmp,
+ void *statep LOCALE_PARAM)
+{
+#ifdef _LIBC
+ struct __locale_data *const current = locale->__locales[LC_TIME];
+#endif
+
+ const char *rp_backup;
+ const char *rp_longest;
+ int cnt;
+ int cnt_longest;
+ size_t val;
+ size_t num_eras;
+ struct era_entry *era = NULL;
+ enum ptime_locale_status { not, loc, raw } decided_longest;
+ struct __strptime_state
+ {
+ unsigned int have_I : 1;
+ unsigned int have_wday : 1;
+ unsigned int have_yday : 1;
+ unsigned int have_mon : 1;
+ unsigned int have_mday : 1;
+ unsigned int have_uweek : 1;
+ unsigned int have_wweek : 1;
+ unsigned int is_pm : 1;
+ unsigned int want_century : 1;
+ unsigned int want_era : 1;
+ unsigned int want_xday : 1;
+ enum ptime_locale_status decided : 2;
+ signed char week_no;
+ signed char century;
+ int era_cnt;
+ } s;
+ struct tm tmb;
+ struct tm *tm;
+
+ if (statep == NULL)
+ {
+ memset (&s, 0, sizeof (s));
+ s.century = -1;
+ s.era_cnt = -1;
+#ifdef _NL_CURRENT
+ s.decided = not;
+#else
+ s.decided = raw;
+#endif
+ tm = tmp;
+ }
+ else
+ {
+ s = *(struct __strptime_state *) statep;
+ tmb = *tmp;
+ tm = &tmb;
+ }
+
+ while (*fmt != '\0')
+ {
+ /* A white space in the format string matches 0 more or white
+ space in the input string. */
+ if (ISSPACE (*fmt))
+ {
+ while (ISSPACE (*rp))
+ ++rp;
+ ++fmt;
+ continue;
+ }
+
+ /* Any character but `%' must be matched by the same character
+ in the iput string. */
+ if (*fmt != '%')
+ {
+ match_char (*fmt++, *rp++);
+ continue;
+ }
+
+ ++fmt;
+ /* We discard strftime modifiers. */
+ while (*fmt == '-' || *fmt == '_' || *fmt == '0'
+ || *fmt == '^' || *fmt == '#')
+ ++fmt;
+
+ /* And field width. */
+ while (*fmt >= '0' && *fmt <= '9')
+ ++fmt;
+
+#ifndef _NL_CURRENT
+ /* We need this for handling the `E' modifier. */
+ start_over:
+#endif
+
+ /* Make back up of current processing pointer. */
+ rp_backup = rp;
+
+ switch (*fmt++)
+ {
+ case '%':
+ /* Match the `%' character itself. */
+ match_char ('%', *rp++);
+ break;
+ case 'a':
+ case 'A':
+ /* Match day of week. */
+ rp_longest = NULL;
+ decided_longest = s.decided;
+ cnt_longest = -1;
+ for (cnt = 0; cnt < 7; ++cnt)
+ {
+ const char *trp;
+#ifdef _NL_CURRENT
+ if (s.decided !=raw)
+ {
+ trp = rp;
+ if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), trp)
+ && trp > rp_longest)
+ {
+ rp_longest = trp;
+ cnt_longest = cnt;
+ if (s.decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
+ weekday_name[cnt]))
+ decided_longest = loc;
+ }
+ trp = rp;
+ if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), trp)
+ && trp > rp_longest)
+ {
+ rp_longest = trp;
+ cnt_longest = cnt;
+ if (s.decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
+ ab_weekday_name[cnt]))
+ decided_longest = loc;
+ }
+ }
+#endif
+ if (s.decided != loc
+ && (((trp = rp, match_string (weekday_name[cnt], trp))
+ && trp > rp_longest)
+ || ((trp = rp, match_string (ab_weekday_name[cnt], rp))
+ && trp > rp_longest)))
+ {
+ rp_longest = trp;
+ cnt_longest = cnt;
+ decided_longest = raw;
+ }
+ }
+ if (rp_longest == NULL)
+ /* Does not match a weekday name. */
+ return NULL;
+ rp = rp_longest;
+ s.decided = decided_longest;
+ tm->tm_wday = cnt_longest;
+ s.have_wday = 1;
+ break;
+ case 'b':
+ case 'B':
+ case 'h':
+ /* Match month name. */
+ rp_longest = NULL;
+ decided_longest = s.decided;
+ cnt_longest = -1;
+ for (cnt = 0; cnt < 12; ++cnt)
+ {
+ const char *trp;
+#ifdef _NL_CURRENT
+ if (s.decided !=raw)
+ {
+ trp = rp;
+ if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), trp)
+ && trp > rp_longest)
+ {
+ rp_longest = trp;
+ cnt_longest = cnt;
+ if (s.decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
+ month_name[cnt]))
+ decided_longest = loc;
+ }
+ trp = rp;
+ if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), trp)
+ && trp > rp_longest)
+ {
+ rp_longest = trp;
+ cnt_longest = cnt;
+ if (s.decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
+ ab_month_name[cnt]))
+ decided_longest = loc;
+ }
+ }
+#endif
+ if (s.decided != loc
+ && (((trp = rp, match_string (month_name[cnt], trp))
+ && trp > rp_longest)
+ || ((trp = rp, match_string (ab_month_name[cnt], trp))
+ && trp > rp_longest)))
+ {
+ rp_longest = trp;
+ cnt_longest = cnt;
+ decided_longest = raw;
+ }
+ }
+ if (rp_longest == NULL)
+ /* Does not match a month name. */
+ return NULL;
+ rp = rp_longest;
+ s.decided = decided_longest;
+ tm->tm_mon = cnt_longest;
+ s.have_mon = 1;
+ s.want_xday = 1;
+ break;
+ case 'c':
+ /* Match locale's date and time format. */
+#ifdef _NL_CURRENT
+ if (s.decided != raw)
+ {
+ if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
+ {
+ if (s.decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (s.decided == not &&
+ strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
+ s.decided = loc;
+ s.want_xday = 1;
+ break;
+ }
+ s.decided = raw;
+ }
+#endif
+ if (!recursive (HERE_D_T_FMT))
+ return NULL;
+ s.want_xday = 1;
+ break;
+ case 'C':
+ /* Match century number. */
+ match_century:
+ get_number (0, 99, 2);
+ s.century = val;
+ s.want_xday = 1;
+ break;
+ case 'd':
+ case 'e':
+ /* Match day of month. */
+ get_number (1, 31, 2);
+ tm->tm_mday = val;
+ s.have_mday = 1;
+ s.want_xday = 1;
+ break;
+ case 'F':
+ if (!recursive ("%Y-%m-%d"))
+ return NULL;
+ s.want_xday = 1;
+ break;
+ case 'x':
+#ifdef _NL_CURRENT
+ if (s.decided != raw)
+ {
+ if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
+ {
+ if (s.decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (s.decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
+ s.decided = loc;
+ s.want_xday = 1;
+ break;
+ }
+ s.decided = raw;
+ }
+#endif
+ /* Fall through. */
+ case 'D':
+ /* Match standard day format. */
+ if (!recursive (HERE_D_FMT))
+ return NULL;
+ s.want_xday = 1;
+ break;
+ case 'k':
+ case 'H':
+ /* Match hour in 24-hour clock. */
+ get_number (0, 23, 2);
+ tm->tm_hour = val;
+ s.have_I = 0;
+ break;
+ case 'l':
+ /* Match hour in 12-hour clock. GNU extension. */
+ case 'I':
+ /* Match hour in 12-hour clock. */
+ get_number (1, 12, 2);
+ tm->tm_hour = val % 12;
+ s.have_I = 1;
+ break;
+ case 'j':
+ /* Match day number of year. */
+ get_number (1, 366, 3);
+ tm->tm_yday = val - 1;
+ s.have_yday = 1;
+ break;
+ case 'm':
+ /* Match number of month. */
+ get_number (1, 12, 2);
+ tm->tm_mon = val - 1;
+ s.have_mon = 1;
+ s.want_xday = 1;
+ break;
+ case 'M':
+ /* Match minute. */
+ get_number (0, 59, 2);
+ tm->tm_min = val;
+ break;
+ case 'n':
+ case 't':
+ /* Match any white space. */
+ while (ISSPACE (*rp))
+ ++rp;
+ break;
+ case 'p':
+ /* Match locale's equivalent of AM/PM. */
+#ifdef _NL_CURRENT
+ if (s.decided != raw)
+ {
+ if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
+ {
+ if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
+ s.decided = loc;
+ s.is_pm = 0;
+ break;
+ }
+ if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
+ {
+ if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
+ s.decided = loc;
+ s.is_pm = 1;
+ break;
+ }
+ s.decided = raw;
+ }
+#endif
+ if (!match_string (HERE_AM_STR, rp))
+ {
+ if (match_string (HERE_PM_STR, rp))
+ s.is_pm = 1;
+ else
+ return NULL;
+ }
+ else
+ s.is_pm = 0;
+ break;
+ case 'r':
+#ifdef _NL_CURRENT
+ if (s.decided != raw)
+ {
+ if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
+ {
+ if (s.decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (s.decided == not &&
+ strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
+ HERE_T_FMT_AMPM))
+ s.decided = loc;
+ break;
+ }
+ s.decided = raw;
+ }
+#endif
+ if (!recursive (HERE_T_FMT_AMPM))
+ return NULL;
+ break;
+ case 'R':
+ if (!recursive ("%H:%M"))
+ return NULL;
+ break;
+ case 's':
+ {
+ /* The number of seconds may be very high so we cannot use
+ the `get_number' macro. Instead read the number
+ character for character and construct the result while
+ doing this. */
+ time_t secs = 0;
+ if (*rp < '0' || *rp > '9')
+ /* We need at least one digit. */
+ return NULL;
+
+ do
+ {
+ secs *= 10;
+ secs += *rp++ - '0';
+ }
+ while (*rp >= '0' && *rp <= '9');
+
+ if (localtime_r (&secs, tm) == NULL)
+ /* Error in function. */
+ return NULL;
+ }
+ break;
+ case 'S':
+ get_number (0, 61, 2);
+ tm->tm_sec = val;
+ break;
+ case 'X':
+#ifdef _NL_CURRENT
+ if (s.decided != raw)
+ {
+ if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
+ {
+ if (s.decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
+ s.decided = loc;
+ break;
+ }
+ s.decided = raw;
+ }
+#endif
+ /* Fall through. */
+ case 'T':
+ if (!recursive (HERE_T_FMT))
+ return NULL;
+ break;
+ case 'u':
+ get_number (1, 7, 1);
+ tm->tm_wday = val % 7;
+ s.have_wday = 1;
+ break;
+ case 'g':
+ get_number (0, 99, 2);
+ /* XXX This cannot determine any field in TM. */
+ break;
+ case 'G':
+ if (*rp < '0' || *rp > '9')
+ return NULL;
+ /* XXX Ignore the number since we would need some more
+ information to compute a real date. */
+ do
+ ++rp;
+ while (*rp >= '0' && *rp <= '9');
+ break;
+ case 'U':
+ get_number (0, 53, 2);
+ s.week_no = val;
+ s.have_uweek = 1;
+ break;
+ case 'W':
+ get_number (0, 53, 2);
+ s.week_no = val;
+ s.have_wweek = 1;
+ break;
+ case 'V':
+ get_number (0, 53, 2);
+ /* XXX This cannot determine any field in TM without some
+ information. */
+ break;
+ case 'w':
+ /* Match number of weekday. */
+ get_number (0, 6, 1);
+ tm->tm_wday = val;
+ s.have_wday = 1;
+ break;
+ case 'y':
+ match_year_in_century:
+ /* Match year within century. */
+ get_number (0, 99, 2);
+ /* The "Year 2000: The Millennium Rollover" paper suggests that
+ values in the range 69-99 refer to the twentieth century. */
+ tm->tm_year = val >= 69 ? val : val + 100;
+ /* Indicate that we want to use the century, if specified. */
+ s.want_century = 1;
+ s.want_xday = 1;
+ break;
+ case 'Y':
+ /* Match year including century number. */
+ get_number (0, 9999, 4);
+ tm->tm_year = val - 1900;
+ s.want_century = 0;
+ s.want_xday = 1;
+ break;
+ case 'Z':
+ /* Read timezone but perform no conversion. */
+ while (ISSPACE (*rp))
+ rp++;
+ while (!ISSPACE (*rp) && *rp != '\0')
+ rp++;
+ break;
+ case 'z':
+ /* We recognize four formats:
+ 1. Two digits specify hours.
+ 2. Four digits specify hours and minutes.
+ 3. Two digits, ':', and two digits specify hours and minutes.
+ 4. 'Z' is equivalent to +0000. */
+ {
+ val = 0;
+ while (ISSPACE (*rp))
+ ++rp;
+ if (*rp == 'Z')
+ {
+ ++rp;
+ tm->tm_gmtoff = 0;
+ break;
+ }
+ if (*rp != '+' && *rp != '-')
+ return NULL;
+ bool neg = *rp++ == '-';
+ int n = 0;
+ while (n < 4 && *rp >= '0' && *rp <= '9')
+ {
+ val = val * 10 + *rp++ - '0';
+ ++n;
+ if (*rp == ':' && n == 2 && isdigit (*(rp + 1)))
+ ++rp;
+ }
+ if (n == 2)
+ val *= 100;
+ else if (n != 4)
+ /* Only two or four digits recognized. */
+ return NULL;
+ else if (val % 100 >= 60)
+ /* Minutes valid range is 0 through 59. */
+ return NULL;
+ tm->tm_gmtoff = (val / 100) * 3600 + (val % 100) * 60;
+ if (neg)
+ tm->tm_gmtoff = -tm->tm_gmtoff;
+ }
+ break;
+ case 'E':
+#ifdef _NL_CURRENT
+ switch (*fmt++)
+ {
+ case 'c':
+ /* Match locale's alternate date and time format. */
+ if (s.decided != raw)
+ {
+ const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
+
+ if (*fmt == '\0')
+ fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
+
+ if (!recursive (fmt))
+ {
+ if (s.decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (strcmp (fmt, HERE_D_T_FMT))
+ s.decided = loc;
+ s.want_xday = 1;
+ break;
+ }
+ s.decided = raw;
+ }
+ /* The C locale has no era information, so use the
+ normal representation. */
+ if (!recursive (HERE_D_T_FMT))
+ return NULL;
+ s.want_xday = 1;
+ break;
+ case 'C':
+ if (s.decided != raw)
+ {
+ if (s.era_cnt >= 0)
+ {
+ era = _nl_select_era_entry (s.era_cnt HELPER_LOCALE_ARG);
+ if (era != NULL && match_string (era->era_name, rp))
+ {
+ s.decided = loc;
+ break;
+ }
+ else
+ return NULL;
+ }
+
+ num_eras = _NL_CURRENT_WORD (LC_TIME,
+ _NL_TIME_ERA_NUM_ENTRIES);
+ for (s.era_cnt = 0; s.era_cnt < (int) num_eras;
+ ++s.era_cnt, rp = rp_backup)
+ {
+ era = _nl_select_era_entry (s.era_cnt
+ HELPER_LOCALE_ARG);
+ if (era != NULL && match_string (era->era_name, rp))
+ {
+ s.decided = loc;
+ break;
+ }
+ }
+ if (s.era_cnt != (int) num_eras)
+ break;
+
+ s.era_cnt = -1;
+ if (s.decided == loc)
+ return NULL;
+
+ s.decided = raw;
+ }
+ /* The C locale has no era information, so use the
+ normal representation. */
+ goto match_century;
+ case 'y':
+ if (s.decided != raw)
+ {
+ get_number(0, 9999, 4);
+ tm->tm_year = val;
+ s.want_era = 1;
+ s.want_xday = 1;
+ s.want_century = 1;
+
+ if (s.era_cnt >= 0)
+ {
+ assert (s.decided == loc);
+
+ era = _nl_select_era_entry (s.era_cnt HELPER_LOCALE_ARG);
+ bool match = false;
+ if (era != NULL)
+ {
+ int delta = ((tm->tm_year - era->offset)
+ * era->absolute_direction);
+ match = (delta >= 0
+ && delta < (((int64_t) era->stop_date[0]
+ - (int64_t) era->start_date[0])
+ * era->absolute_direction));
+ }
+ if (! match)
+ return NULL;
+
+ break;
+ }
+
+ num_eras = _NL_CURRENT_WORD (LC_TIME,
+ _NL_TIME_ERA_NUM_ENTRIES);
+ for (s.era_cnt = 0; s.era_cnt < (int) num_eras; ++s.era_cnt)
+ {
+ era = _nl_select_era_entry (s.era_cnt
+ HELPER_LOCALE_ARG);
+ if (era != NULL)
+ {
+ int delta = ((tm->tm_year - era->offset)
+ * era->absolute_direction);
+ if (delta >= 0
+ && delta < (((int64_t) era->stop_date[0]
+ - (int64_t) era->start_date[0])
+ * era->absolute_direction))
+ {
+ s.decided = loc;
+ break;
+ }
+ }
+ }
+ if (s.era_cnt != (int) num_eras)
+ break;
+
+ s.era_cnt = -1;
+ if (s.decided == loc)
+ return NULL;
+
+ s.decided = raw;
+ }
+
+ goto match_year_in_century;
+ case 'Y':
+ if (s.decided != raw)
+ {
+ num_eras = _NL_CURRENT_WORD (LC_TIME,
+ _NL_TIME_ERA_NUM_ENTRIES);
+ for (s.era_cnt = 0; s.era_cnt < (int) num_eras;
+ ++s.era_cnt, rp = rp_backup)
+ {
+ era = _nl_select_era_entry (s.era_cnt HELPER_LOCALE_ARG);
+ if (era != NULL && recursive (era->era_format))
+ break;
+ }
+ if (s.era_cnt == (int) num_eras)
+ {
+ s.era_cnt = -1;
+ if (s.decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ s.decided = loc;
+ break;
+ }
+
+ s.decided = raw;
+ }
+ get_number (0, 9999, 4);
+ tm->tm_year = val - 1900;
+ s.want_century = 0;
+ s.want_xday = 1;
+ break;
+ case 'x':
+ if (s.decided != raw)
+ {
+ const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
+
+ if (*fmt == '\0')
+ fmt = _NL_CURRENT (LC_TIME, D_FMT);
+
+ if (!recursive (fmt))
+ {
+ if (s.decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (strcmp (fmt, HERE_D_FMT))
+ s.decided = loc;
+ break;
+ }
+ s.decided = raw;
+ }
+ if (!recursive (HERE_D_FMT))
+ return NULL;
+ break;
+ case 'X':
+ if (s.decided != raw)
+ {
+ const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
+
+ if (*fmt == '\0')
+ fmt = _NL_CURRENT (LC_TIME, T_FMT);
+
+ if (!recursive (fmt))
+ {
+ if (s.decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (strcmp (fmt, HERE_T_FMT))
+ s.decided = loc;
+ break;
+ }
+ s.decided = raw;
+ }
+ if (!recursive (HERE_T_FMT))
+ return NULL;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+#else
+ /* We have no information about the era format. Just use
+ the normal format. */
+ if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
+ && *fmt != 'x' && *fmt != 'X')
+ /* This is an illegal format. */
+ return NULL;
+
+ goto start_over;
+#endif
+ case 'O':
+ switch (*fmt++)
+ {
+ case 'd':
+ case 'e':
+ /* Match day of month using alternate numeric symbols. */
+ get_alt_number (1, 31, 2);
+ tm->tm_mday = val;
+ s.have_mday = 1;
+ s.want_xday = 1;
+ break;
+ case 'H':
+ /* Match hour in 24-hour clock using alternate numeric
+ symbols. */
+ get_alt_number (0, 23, 2);
+ tm->tm_hour = val;
+ s.have_I = 0;
+ break;
+ case 'I':
+ /* Match hour in 12-hour clock using alternate numeric
+ symbols. */
+ get_alt_number (1, 12, 2);
+ tm->tm_hour = val % 12;
+ s.have_I = 1;
+ break;
+ case 'm':
+ /* Match month using alternate numeric symbols. */
+ get_alt_number (1, 12, 2);
+ tm->tm_mon = val - 1;
+ s.have_mon = 1;
+ s.want_xday = 1;
+ break;
+ case 'M':
+ /* Match minutes using alternate numeric symbols. */
+ get_alt_number (0, 59, 2);
+ tm->tm_min = val;
+ break;
+ case 'S':
+ /* Match seconds using alternate numeric symbols. */
+ get_alt_number (0, 61, 2);
+ tm->tm_sec = val;
+ break;
+ case 'U':
+ get_alt_number (0, 53, 2);
+ s.week_no = val;
+ s.have_uweek = 1;
+ break;
+ case 'W':
+ get_alt_number (0, 53, 2);
+ s.week_no = val;
+ s.have_wweek = 1;
+ break;
+ case 'V':
+ get_alt_number (0, 53, 2);
+ /* XXX This cannot determine any field in TM without
+ further information. */
+ break;
+ case 'w':
+ /* Match number of weekday using alternate numeric symbols. */
+ get_alt_number (0, 6, 1);
+ tm->tm_wday = val;
+ s.have_wday = 1;
+ break;
+ case 'y':
+ /* Match year within century using alternate numeric symbols. */
+ get_alt_number (0, 99, 2);
+ tm->tm_year = val >= 69 ? val : val + 100;
+ s.want_xday = 1;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ default:
+ return NULL;
+ }
+ }
+
+ if (statep != NULL)
+ {
+ /* Recursive invocation, returning success, so
+ update parent's struct tm and state. */
+ *(struct __strptime_state *) statep = s;
+ *tmp = tmb;
+ return (char *) rp;
+ }
+
+ if (s.have_I && s.is_pm)
+ tm->tm_hour += 12;
+
+ if (s.century != -1)
+ {
+ if (s.want_century)
+ tm->tm_year = tm->tm_year % 100 + (s.century - 19) * 100;
+ else
+ /* Only the century, but not the year. Strange, but so be it. */
+ tm->tm_year = (s.century - 19) * 100;
+ }
+
+ if (s.era_cnt != -1)
+ {
+ era = _nl_select_era_entry (s.era_cnt HELPER_LOCALE_ARG);
+ if (era == NULL)
+ return NULL;
+ if (s.want_era)
+ tm->tm_year = (era->start_date[0]
+ + ((tm->tm_year - era->offset)
+ * era->absolute_direction));
+ else
+ /* Era start year assumed. */
+ tm->tm_year = era->start_date[0];
+ }
+ else
+ if (s.want_era)
+ {
+ /* No era found but we have seen an E modifier. Rectify some
+ values. */
+ if (s.want_century && s.century == -1 && tm->tm_year < 69)
+ tm->tm_year += 100;
+ }
+
+ if (s.want_xday && !s.have_wday)
+ {
+ if ( !(s.have_mon && s.have_mday) && s.have_yday)
+ {
+ /* We don't have tm_mon and/or tm_mday, compute them. */
+ int t_mon = 0;
+ while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
+ t_mon++;
+ if (!s.have_mon)
+ tm->tm_mon = t_mon - 1;
+ if (!s.have_mday)
+ tm->tm_mday =
+ (tm->tm_yday
+ - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
+ s.have_mon = 1;
+ s.have_mday = 1;
+ }
+ /* Don't crash in day_of_the_week if tm_mon is uninitialized. */
+ if (s.have_mon || (unsigned) tm->tm_mon <= 11)
+ day_of_the_week (tm);
+ }
+
+ if (s.want_xday && !s.have_yday && (s.have_mon || (unsigned) tm->tm_mon <= 11))
+ day_of_the_year (tm);
+
+ if ((s.have_uweek || s.have_wweek) && s.have_wday)
+ {
+ int save_wday = tm->tm_wday;
+ int save_mday = tm->tm_mday;
+ int save_mon = tm->tm_mon;
+ int w_offset = s.have_uweek ? 0 : 1;
+
+ tm->tm_mday = 1;
+ tm->tm_mon = 0;
+ day_of_the_week (tm);
+ if (s.have_mday)
+ tm->tm_mday = save_mday;
+ if (s.have_mon)
+ tm->tm_mon = save_mon;
+
+ if (!s.have_yday)
+ tm->tm_yday = ((7 - (tm->tm_wday - w_offset)) % 7
+ + (s.week_no - 1) * 7
+ + (save_wday - w_offset + 7) % 7);
+
+ if (!s.have_mday || !s.have_mon)
+ {
+ int t_mon = 0;
+ while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon]
+ <= tm->tm_yday)
+ t_mon++;
+ if (!s.have_mon)
+ tm->tm_mon = t_mon - 1;
+ if (!s.have_mday)
+ tm->tm_mday =
+ (tm->tm_yday
+ - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
+ }
+
+ tm->tm_wday = save_wday;
+ }
+
+ return (char *) rp;
+}
+
+
+char *
+strptime (const char *buf, const char *format, struct tm *tm LOCALE_PARAM)
+{
+ return __strptime_internal (buf, format, tm, NULL LOCALE_ARG);
+}
+
+#ifdef _LIBC
+weak_alias (__strptime_l, strptime_l)
+#endif
diff --git a/REORG.TODO/time/sys/time.h b/REORG.TODO/time/sys/time.h
new file mode 100644
index 0000000000..165296ac59
--- /dev/null
+++ b/REORG.TODO/time/sys/time.h
@@ -0,0 +1,188 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_TIME_H
+#define _SYS_TIME_H 1
+
+#include <features.h>
+
+#include <bits/types.h>
+#include <bits/types/time_t.h>
+#include <bits/types/struct_timeval.h>
+
+#ifndef __suseconds_t_defined
+typedef __suseconds_t suseconds_t;
+# define __suseconds_t_defined
+#endif
+
+#include <sys/select.h>
+
+__BEGIN_DECLS
+
+#ifdef __USE_GNU
+/* Macros for converting between `struct timeval' and `struct timespec'. */
+# define TIMEVAL_TO_TIMESPEC(tv, ts) { \
+ (ts)->tv_sec = (tv)->tv_sec; \
+ (ts)->tv_nsec = (tv)->tv_usec * 1000; \
+}
+# define TIMESPEC_TO_TIMEVAL(tv, ts) { \
+ (tv)->tv_sec = (ts)->tv_sec; \
+ (tv)->tv_usec = (ts)->tv_nsec / 1000; \
+}
+#endif
+
+
+#ifdef __USE_MISC
+/* Structure crudely representing a timezone.
+ This is obsolete and should never be used. */
+struct timezone
+ {
+ int tz_minuteswest; /* Minutes west of GMT. */
+ int tz_dsttime; /* Nonzero if DST is ever in effect. */
+ };
+
+typedef struct timezone *__restrict __timezone_ptr_t;
+#else
+typedef void *__restrict __timezone_ptr_t;
+#endif
+
+/* Get the current time of day and timezone information,
+ putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled.
+ Returns 0 on success, -1 on errors.
+ NOTE: This form of timezone information is obsolete.
+ Use the functions and variables declared in <time.h> instead. */
+extern int gettimeofday (struct timeval *__restrict __tv,
+ __timezone_ptr_t __tz) __THROW __nonnull ((1));
+
+#ifdef __USE_MISC
+/* Set the current time of day and timezone information.
+ This call is restricted to the super-user. */
+extern int settimeofday (const struct timeval *__tv,
+ const struct timezone *__tz)
+ __THROW;
+
+/* Adjust the current time of day by the amount in DELTA.
+ If OLDDELTA is not NULL, it is filled in with the amount
+ of time adjustment remaining to be done from the last `adjtime' call.
+ This call is restricted to the super-user. */
+extern int adjtime (const struct timeval *__delta,
+ struct timeval *__olddelta) __THROW;
+#endif
+
+
+/* Values for the first argument to `getitimer' and `setitimer'. */
+enum __itimer_which
+ {
+ /* Timers run in real time. */
+ ITIMER_REAL = 0,
+#define ITIMER_REAL ITIMER_REAL
+ /* Timers run only when the process is executing. */
+ ITIMER_VIRTUAL = 1,
+#define ITIMER_VIRTUAL ITIMER_VIRTUAL
+ /* Timers run when the process is executing and when
+ the system is executing on behalf of the process. */
+ ITIMER_PROF = 2
+#define ITIMER_PROF ITIMER_PROF
+ };
+
+/* Type of the second argument to `getitimer' and
+ the second and third arguments `setitimer'. */
+struct itimerval
+ {
+ /* Value to put into `it_value' when the timer expires. */
+ struct timeval it_interval;
+ /* Time to the next timer expiration. */
+ struct timeval it_value;
+ };
+
+#if defined __USE_GNU && !defined __cplusplus
+/* Use the nicer parameter type only in GNU mode and not for C++ since the
+ strict C++ rules prevent the automatic promotion. */
+typedef enum __itimer_which __itimer_which_t;
+#else
+typedef int __itimer_which_t;
+#endif
+
+/* Set *VALUE to the current setting of timer WHICH.
+ Return 0 on success, -1 on errors. */
+extern int getitimer (__itimer_which_t __which,
+ struct itimerval *__value) __THROW;
+
+/* Set the timer WHICH to *NEW. If OLD is not NULL,
+ set *OLD to the old value of timer WHICH.
+ Returns 0 on success, -1 on errors. */
+extern int setitimer (__itimer_which_t __which,
+ const struct itimerval *__restrict __new,
+ struct itimerval *__restrict __old) __THROW;
+
+/* Change the access time of FILE to TVP[0] and the modification time of
+ FILE to TVP[1]. If TVP is a null pointer, use the current time instead.
+ Returns 0 on success, -1 on errors. */
+extern int utimes (const char *__file, const struct timeval __tvp[2])
+ __THROW __nonnull ((1));
+
+#ifdef __USE_MISC
+/* Same as `utimes', but does not follow symbolic links. */
+extern int lutimes (const char *__file, const struct timeval __tvp[2])
+ __THROW __nonnull ((1));
+
+/* Same as `utimes', but takes an open file descriptor instead of a name. */
+extern int futimes (int __fd, const struct timeval __tvp[2]) __THROW;
+#endif
+
+#ifdef __USE_GNU
+/* Change the access time of FILE relative to FD to TVP[0] and the
+ modification time of FILE to TVP[1]. If TVP is a null pointer, use
+ the current time instead. Returns 0 on success, -1 on errors. */
+extern int futimesat (int __fd, const char *__file,
+ const struct timeval __tvp[2]) __THROW;
+#endif
+
+
+#ifdef __USE_MISC
+/* Convenience macros for operations on timevals.
+ NOTE: `timercmp' does not work for >= or <=. */
+# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
+# define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
+# define timercmp(a, b, CMP) \
+ (((a)->tv_sec == (b)->tv_sec) ? \
+ ((a)->tv_usec CMP (b)->tv_usec) : \
+ ((a)->tv_sec CMP (b)->tv_sec))
+# define timeradd(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
+ if ((result)->tv_usec >= 1000000) \
+ { \
+ ++(result)->tv_sec; \
+ (result)->tv_usec -= 1000000; \
+ } \
+ } while (0)
+# define timersub(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) { \
+ --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif /* Misc. */
+
+__END_DECLS
+
+#endif /* sys/time.h */
diff --git a/REORG.TODO/time/sys/timeb.h b/REORG.TODO/time/sys/timeb.h
new file mode 100644
index 0000000000..351aeaf619
--- /dev/null
+++ b/REORG.TODO/time/sys/timeb.h
@@ -0,0 +1,43 @@
+/* Copyright (C) 1994-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_TIMEB_H
+#define _SYS_TIMEB_H 1
+
+#include <features.h>
+
+#include <bits/types/time_t.h>
+
+__BEGIN_DECLS
+
+/* Structure returned by the `ftime' function. */
+
+struct timeb
+ {
+ time_t time; /* Seconds since epoch, as from `time'. */
+ unsigned short int millitm; /* Additional milliseconds. */
+ short int timezone; /* Minutes west of GMT. */
+ short int dstflag; /* Nonzero if Daylight Savings Time used. */
+ };
+
+/* Fill in TIMEBUF with information about the current time. */
+
+extern int ftime (struct timeb *__timebuf);
+
+__END_DECLS
+
+#endif /* sys/timeb.h */
diff --git a/REORG.TODO/time/test_time.c b/REORG.TODO/time/test_time.c
new file mode 100644
index 0000000000..745acdd458
--- /dev/null
+++ b/REORG.TODO/time/test_time.c
@@ -0,0 +1,115 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+int
+main (int argc, char **argv)
+{
+ time_t t;
+ struct tm *tp;
+ struct tm tbuf;
+ int lose = 0;
+
+ --argc;
+ ++argv;
+
+ do
+ {
+ char buf[BUFSIZ];
+ if (argc > 0)
+ {
+ static char buf[BUFSIZ];
+ sprintf(buf, "TZ=%s", *argv);
+ if (putenv(buf))
+ {
+ puts("putenv failed.");
+ lose = 1;
+ }
+ else
+ puts (buf);
+ }
+ tzset();
+ tbuf.tm_year = 72;
+ tbuf.tm_mon = 0;
+ tbuf.tm_mday = 31;
+ tbuf.tm_hour = 6;
+ tbuf.tm_min = 14;
+ tbuf.tm_sec = 50;
+ tbuf.tm_isdst = -1;
+ doit:;
+ t = mktime(&tbuf);
+ if (t == (time_t) -1)
+ {
+ puts("mktime() failed?");
+ lose = 1;
+ }
+ tp = localtime(&t);
+ if (tp == NULL)
+ {
+ puts("localtime() failed.");
+ lose = 1;
+ }
+ else if (strftime(buf, sizeof(buf), "%a %b %d %X %Z %Y", tp) == 0)
+ {
+ puts("strftime() failed.");
+ lose = 1;
+ }
+ else
+ puts(buf);
+ if (tbuf.tm_year == 101)
+ {
+ tbuf.tm_year = 97;
+ tbuf.tm_mon = 0;
+ goto doit;
+ }
+ ++argv;
+ } while (--argc > 0);
+
+ {
+#define SIZE 256
+ char buffer[SIZE];
+ time_t curtime;
+ struct tm *loctime;
+
+ curtime = time (NULL);
+
+ loctime = localtime (&curtime);
+
+ fputs (asctime (loctime), stdout);
+
+ strftime (buffer, SIZE, "Today is %A, %B %d.\n", loctime);
+ fputs (buffer, stdout);
+ strftime (buffer, SIZE, "The time is %I:%M %p.\n", loctime);
+ fputs (buffer, stdout);
+
+ loctime->tm_year = 72;
+ loctime->tm_mon = 8;
+ loctime->tm_mday = 12;
+ loctime->tm_hour = 20;
+ loctime->tm_min = 49;
+ loctime->tm_sec = 05;
+ curtime = mktime (loctime);
+ strftime (buffer, SIZE, "%D %T was %w the %jth.\n", loctime);
+ fputs (buffer, stdout);
+ }
+
+ return (lose ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/REORG.TODO/time/time.c b/REORG.TODO/time/time.c
new file mode 100644
index 0000000000..e375035265
--- /dev/null
+++ b/REORG.TODO/time/time.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <time.h>
+
+/* Return the time now, and store it in *TIMER if not NULL. */
+time_t
+time (time_t *timer)
+{
+ __set_errno (ENOSYS);
+
+ if (timer != NULL)
+ *timer = (time_t) -1;
+ return (time_t) -1;
+}
+libc_hidden_def (time)
+
+stub_warning (time)
diff --git a/REORG.TODO/time/time.h b/REORG.TODO/time/time.h
new file mode 100644
index 0000000000..bb4994feee
--- /dev/null
+++ b/REORG.TODO/time/time.h
@@ -0,0 +1,309 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * ISO C99 Standard: 7.23 Date and time <time.h>
+ */
+
+#ifndef _TIME_H
+#define _TIME_H 1
+
+#include <features.h>
+
+#define __need_size_t
+#define __need_NULL
+#include <stddef.h>
+
+/* This defines CLOCKS_PER_SEC, which is the number of processor clock
+ ticks per second, and possibly a number of other constants. */
+#include <bits/time.h>
+
+/* Many of the typedefs and structs whose official home is this header
+ may also need to be defined by other headers. */
+#include <bits/types/clock_t.h>
+#include <bits/types/time_t.h>
+#include <bits/types/struct_tm.h>
+
+#if defined __USE_POSIX199309 || defined __USE_ISOC11
+# include <bits/types/struct_timespec.h>
+#endif
+
+#ifdef __USE_POSIX199309
+# include <bits/types/clockid_t.h>
+# include <bits/types/timer_t.h>
+# include <bits/types/struct_itimerspec.h>
+struct sigevent;
+#endif
+
+#ifdef __USE_XOPEN2K
+# ifndef __pid_t_defined
+typedef __pid_t pid_t;
+# define __pid_t_defined
+# endif
+#endif
+
+#ifdef __USE_XOPEN2K8
+# include <xlocale.h>
+#endif
+
+#ifdef __USE_ISOC11
+/* Time base values for timespec_get. */
+# define TIME_UTC 1
+#endif
+
+__BEGIN_DECLS
+
+/* Time used by the program so far (user time + system time).
+ The result / CLOCKS_PER_SECOND is program time in seconds. */
+extern clock_t clock (void) __THROW;
+
+/* Return the current time and put it in *TIMER if TIMER is not NULL. */
+extern time_t time (time_t *__timer) __THROW;
+
+/* Return the difference between TIME1 and TIME0. */
+extern double difftime (time_t __time1, time_t __time0)
+ __THROW __attribute__ ((__const__));
+
+/* Return the `time_t' representation of TP and normalize TP. */
+extern time_t mktime (struct tm *__tp) __THROW;
+
+
+/* Format TP into S according to FORMAT.
+ Write no more than MAXSIZE characters and return the number
+ of characters written, or 0 if it would exceed MAXSIZE. */
+extern size_t strftime (char *__restrict __s, size_t __maxsize,
+ const char *__restrict __format,
+ const struct tm *__restrict __tp) __THROW;
+
+#ifdef __USE_XOPEN
+/* Parse S according to FORMAT and store binary time information in TP.
+ The return value is a pointer to the first unparsed character in S. */
+extern char *strptime (const char *__restrict __s,
+ const char *__restrict __fmt, struct tm *__tp)
+ __THROW;
+#endif
+
+#ifdef __USE_XOPEN2K8
+/* Similar to the two functions above but take the information from
+ the provided locale and not the global locale. */
+
+extern size_t strftime_l (char *__restrict __s, size_t __maxsize,
+ const char *__restrict __format,
+ const struct tm *__restrict __tp,
+ __locale_t __loc) __THROW;
+#endif
+
+#ifdef __USE_GNU
+extern char *strptime_l (const char *__restrict __s,
+ const char *__restrict __fmt, struct tm *__tp,
+ __locale_t __loc) __THROW;
+#endif
+
+
+/* Return the `struct tm' representation of *TIMER
+ in Universal Coordinated Time (aka Greenwich Mean Time). */
+extern struct tm *gmtime (const time_t *__timer) __THROW;
+
+/* Return the `struct tm' representation
+ of *TIMER in the local timezone. */
+extern struct tm *localtime (const time_t *__timer) __THROW;
+
+#ifdef __USE_POSIX
+/* Return the `struct tm' representation of *TIMER in UTC,
+ using *TP to store the result. */
+extern struct tm *gmtime_r (const time_t *__restrict __timer,
+ struct tm *__restrict __tp) __THROW;
+
+/* Return the `struct tm' representation of *TIMER in local time,
+ using *TP to store the result. */
+extern struct tm *localtime_r (const time_t *__restrict __timer,
+ struct tm *__restrict __tp) __THROW;
+#endif /* POSIX */
+
+/* Return a string of the form "Day Mon dd hh:mm:ss yyyy\n"
+ that is the representation of TP in this format. */
+extern char *asctime (const struct tm *__tp) __THROW;
+
+/* Equivalent to `asctime (localtime (timer))'. */
+extern char *ctime (const time_t *__timer) __THROW;
+
+#ifdef __USE_POSIX
+/* Reentrant versions of the above functions. */
+
+/* Return in BUF a string of the form "Day Mon dd hh:mm:ss yyyy\n"
+ that is the representation of TP in this format. */
+extern char *asctime_r (const struct tm *__restrict __tp,
+ char *__restrict __buf) __THROW;
+
+/* Equivalent to `asctime_r (localtime_r (timer, *TMP*), buf)'. */
+extern char *ctime_r (const time_t *__restrict __timer,
+ char *__restrict __buf) __THROW;
+#endif /* POSIX */
+
+
+/* Defined in localtime.c. */
+extern char *__tzname[2]; /* Current timezone names. */
+extern int __daylight; /* If daylight-saving time is ever in use. */
+extern long int __timezone; /* Seconds west of UTC. */
+
+
+#ifdef __USE_POSIX
+/* Same as above. */
+extern char *tzname[2];
+
+/* Set time conversion information from the TZ environment variable.
+ If TZ is not defined, a locale-dependent default is used. */
+extern void tzset (void) __THROW;
+#endif
+
+#if defined __USE_MISC || defined __USE_XOPEN
+extern int daylight;
+extern long int timezone;
+#endif
+
+#ifdef __USE_MISC
+/* Set the system time to *WHEN.
+ This call is restricted to the superuser. */
+extern int stime (const time_t *__when) __THROW;
+#endif
+
+
+/* Nonzero if YEAR is a leap year (every 4 years,
+ except every 100th isn't, and every 400th is). */
+#define __isleap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+
+#ifdef __USE_MISC
+/* Miscellaneous functions many Unices inherited from the public domain
+ localtime package. These are included only for compatibility. */
+
+/* Like `mktime', but for TP represents Universal Time, not local time. */
+extern time_t timegm (struct tm *__tp) __THROW;
+
+/* Another name for `mktime'. */
+extern time_t timelocal (struct tm *__tp) __THROW;
+
+/* Return the number of days in YEAR. */
+extern int dysize (int __year) __THROW __attribute__ ((__const__));
+#endif
+
+
+#ifdef __USE_POSIX199309
+/* Pause execution for a number of nanoseconds.
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern int nanosleep (const struct timespec *__requested_time,
+ struct timespec *__remaining);
+
+
+/* Get resolution of clock CLOCK_ID. */
+extern int clock_getres (clockid_t __clock_id, struct timespec *__res) __THROW;
+
+/* Get current value of clock CLOCK_ID and store it in TP. */
+extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;
+
+/* Set clock CLOCK_ID to value TP. */
+extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp)
+ __THROW;
+
+# ifdef __USE_XOPEN2K
+/* High-resolution sleep with the specified clock.
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern int clock_nanosleep (clockid_t __clock_id, int __flags,
+ const struct timespec *__req,
+ struct timespec *__rem);
+
+/* Return clock ID for CPU-time clock. */
+extern int clock_getcpuclockid (pid_t __pid, clockid_t *__clock_id) __THROW;
+# endif
+
+
+/* Create new per-process timer using CLOCK_ID. */
+extern int timer_create (clockid_t __clock_id,
+ struct sigevent *__restrict __evp,
+ timer_t *__restrict __timerid) __THROW;
+
+/* Delete timer TIMERID. */
+extern int timer_delete (timer_t __timerid) __THROW;
+
+/* Set timer TIMERID to VALUE, returning old value in OVALUE. */
+extern int timer_settime (timer_t __timerid, int __flags,
+ const struct itimerspec *__restrict __value,
+ struct itimerspec *__restrict __ovalue) __THROW;
+
+/* Get current value of timer TIMERID and store it in VALUE. */
+extern int timer_gettime (timer_t __timerid, struct itimerspec *__value)
+ __THROW;
+
+/* Get expiration overrun for timer TIMERID. */
+extern int timer_getoverrun (timer_t __timerid) __THROW;
+#endif
+
+
+#ifdef __USE_ISOC11
+/* Set TS to calendar time based in time base BASE. */
+extern int timespec_get (struct timespec *__ts, int __base)
+ __THROW __nonnull ((1));
+#endif
+
+
+#ifdef __USE_XOPEN_EXTENDED
+/* Set to one of the following values to indicate an error.
+ 1 the DATEMSK environment variable is null or undefined,
+ 2 the template file cannot be opened for reading,
+ 3 failed to get file status information,
+ 4 the template file is not a regular file,
+ 5 an error is encountered while reading the template file,
+ 6 memory allication failed (not enough memory available),
+ 7 there is no line in the template that matches the input,
+ 8 invalid input specification Example: February 31 or a time is
+ specified that can not be represented in a time_t (representing
+ the time in seconds since 00:00:00 UTC, January 1, 1970) */
+extern int getdate_err;
+
+/* Parse the given string as a date specification and return a value
+ representing the value. The templates from the file identified by
+ the environment variable DATEMSK are used. In case of an error
+ `getdate_err' is set.
+
+ This function is a possible cancellation point and therefore not
+ marked with __THROW. */
+extern struct tm *getdate (const char *__string);
+#endif
+
+#ifdef __USE_GNU
+/* Since `getdate' is not reentrant because of the use of `getdate_err'
+ and the static buffer to return the result in, we provide a thread-safe
+ variant. The functionality is the same. The result is returned in
+ the buffer pointed to by RESBUFP and in case of an error the return
+ value is != 0 with the same values as given above for `getdate_err'.
+
+ This function is not part of POSIX and therefore no official
+ cancellation point. But due to similarity with an POSIX interface
+ or due to the implementation it is a cancellation point and
+ therefore not marked with __THROW. */
+extern int getdate_r (const char *__restrict __string,
+ struct tm *__restrict __resbufp);
+#endif
+
+__END_DECLS
+
+#endif /* time.h. */
diff --git a/REORG.TODO/time/timegm.c b/REORG.TODO/time/timegm.c
new file mode 100644
index 0000000000..b0f5d16d16
--- /dev/null
+++ b/REORG.TODO/time/timegm.c
@@ -0,0 +1,47 @@
+/* Convert UTC calendar time to simple time. Like mktime but assumes UTC.
+
+ Copyright (C) 1994-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# include <time.h>
+#else
+# include "timegm.h"
+
+/* Portable standalone applications should supply a "time_r.h" that
+ declares a POSIX-compliant gmtime_r, for the benefit of older
+ implementations that lack gmtime_r or have a nonstandard one.
+ See the gnulib time_r module for one way to implement this. */
+# include <time_r.h>
+# undef __gmtime_r
+# define __gmtime_r gmtime_r
+time_t __mktime_internal (struct tm *,
+ struct tm * (*) (time_t const *, struct tm *),
+ time_t *);
+#endif
+
+time_t
+timegm (struct tm *tmp)
+{
+ static time_t gmtime_offset;
+ tmp->tm_isdst = 0;
+ return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
+}
diff --git a/REORG.TODO/time/timespec_get.c b/REORG.TODO/time/timespec_get.c
new file mode 100644
index 0000000000..125612af14
--- /dev/null
+++ b/REORG.TODO/time/timespec_get.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <time.h>
+
+
+/* Set TS to calendar time based in time base BASE. */
+int
+timespec_get (struct timespec *ts, int base)
+{
+ switch (base)
+ {
+ case TIME_UTC:
+ /* Not supported. */
+ return 0;
+
+ default:
+ return 0;
+ }
+
+ return base;
+}
+stub_warning (timespec_get)
diff --git a/REORG.TODO/time/tst-ftime.c b/REORG.TODO/time/tst-ftime.c
new file mode 100644
index 0000000000..6df20be630
--- /dev/null
+++ b/REORG.TODO/time/tst-ftime.c
@@ -0,0 +1,59 @@
+/* Verify that ftime is sane.
+ Copyright (C) 2014-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/timeb.h>
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+ struct timeb prev, curr = {.time = 0, .millitm = 0};
+ int sec = 0;
+
+ while (sec != 3)
+ {
+ prev = curr;
+
+ if (ftime (&curr))
+ {
+ printf ("ftime returned an error\n");
+ return 1;
+ }
+
+ if (curr.time < prev.time)
+ {
+ printf ("ftime's time flowed backwards\n");
+ return 1;
+ }
+
+ if (curr.time == prev.time
+ && curr.millitm < prev.millitm)
+ {
+ printf ("ftime's millitm flowed backwards\n");
+ return 1;
+ }
+
+ if (curr.time > prev.time)
+ sec ++;
+ }
+ return 0;
+}
+
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-ftime_l.c b/REORG.TODO/time/tst-ftime_l.c
new file mode 100644
index 0000000000..6690efeb9c
--- /dev/null
+++ b/REORG.TODO/time/tst-ftime_l.c
@@ -0,0 +1,129 @@
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <wchar.h>
+
+
+static int
+do_test (void)
+{
+ locale_t l;
+ locale_t old;
+ struct tm tm;
+ char buf[1000];
+ wchar_t wbuf[1000];
+ int result = 0;
+ size_t n;
+
+ l = newlocale (LC_ALL_MASK, "de_DE.ISO-8859-1", NULL);
+ if (l == NULL)
+ {
+ puts ("newlocale failed");
+ exit (1);
+ }
+
+ memset (&tm, '\0', sizeof (tm));
+
+ tm.tm_year = 102;
+ tm.tm_mon = 2;
+ tm.tm_mday = 1;
+
+ if (strftime (buf, sizeof (buf), "%e %^B %Y", &tm) == 0)
+ {
+ puts ("initial strftime failed");
+ exit (1);
+ }
+ if (strcmp (buf, " 1 MARCH 2002") != 0)
+ {
+ printf ("initial strftime: expected \"%s\", got \"%s\"\n",
+ " 1 MARCH 2002", buf);
+ result = 1;
+ }
+ else
+ printf ("got \"%s\"\n", buf);
+
+ /* Now using the extended locale model. */
+ if (strftime_l (buf, sizeof (buf), "%e %^B %Y", &tm, l) == 0)
+ {
+ puts ("strftime_l failed");
+ result = 1;
+ }
+ else if (strcmp (buf, " 1 M\xc4RZ 2002") != 0)
+ {
+ printf ("strftime_l: expected \"%s\", got \"%s\"\n",
+ " 1 M\xc4RZ 2002", buf);
+ result = 1;
+ }
+ else
+ {
+ setlocale (LC_ALL, "de_DE.ISO-8859-1");
+ printf ("got \"%s\"\n", buf);
+ setlocale (LC_ALL, "C");
+ }
+
+ /* And the wide character version. */
+ if (wcsftime_l (wbuf, sizeof (wbuf) / sizeof (wbuf[0]), L"%e %^B %Y", &tm, l)
+ == 0)
+ {
+ puts ("wcsftime_l failed");
+ result = 1;
+ }
+ else if (wcscmp (wbuf, L" 1 M\x00c4RZ 2002") != 0)
+ {
+ printf ("wcsftime_l: expected \"%ls\", got \"%ls\"\n",
+ L" 1 M\x00c4RZ 2002", wbuf);
+ result = 1;
+ }
+ else
+ {
+ setlocale (LC_ALL, "de_DE.ISO-8859-1");
+ printf ("got \"%ls\"\n", wbuf);
+ setlocale (LC_ALL, "C");
+ }
+
+ old = uselocale (l);
+
+ n = strftime (buf, sizeof (buf), "%e %^B %Y", &tm);
+
+ /* Switch back. */
+ (void) uselocale (old);
+
+ if (n == 0)
+ {
+ puts ("strftime after first uselocale failed");
+ result = 1;
+ }
+ else if (strcmp (buf, " 1 M\xc4RZ 2002") != 0)
+ {
+ printf ("strftime in non-C locale: expected \"%s\", got \"%s\"\n",
+ " 1 M\xc4RZ 2002", buf);
+ result = 1;
+ }
+ else
+ {
+ setlocale (LC_ALL, "de_DE.ISO-8859-1");
+ printf ("got \"%s\"\n", buf);
+ setlocale (LC_ALL, "C");
+ }
+
+ if (strftime (buf, sizeof (buf), "%e %^B %Y", &tm) == 0)
+ {
+ puts ("strftime after second uselocale failed");
+ result = 1;
+ }
+ else if (strcmp (buf, " 1 MARCH 2002") != 0)
+ {
+ printf ("initial strftime: expected \"%s\", got \"%s\"\n",
+ " 1 MARCH 2002", buf);
+ result = 1;
+ }
+ else
+ printf ("got \"%s\"\n", buf);
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-getdate.c b/REORG.TODO/time/tst-getdate.c
new file mode 100644
index 0000000000..e4b34b7a5c
--- /dev/null
+++ b/REORG.TODO/time/tst-getdate.c
@@ -0,0 +1,126 @@
+/* Test for getdate.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+static const struct
+{
+ const char *str;
+ const char *tz;
+ int err;
+ struct tm tm;
+} tests [] =
+{
+ {"21:01:10 1999-1-31", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
+ {"21:01:10 1999-1-31", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
+ {" 21:01:10 1999-1-31", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
+ {"21:01:10 1999-1-31 ", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
+ {" 21:01:10 1999-1-31 ", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}},
+ {"21:01:10 1999-2-28", "Universal", 0, {10, 1, 21, 28, 1, 99, 0, 0, 0}},
+ {"16:30:46 2000-2-29", "Universal", 0, {46, 30,16, 29, 1, 100, 0, 0, 0}},
+ {"01-08-2000 05:06:07", "Europe/Berlin", 0, {7, 6, 5, 1, 7, 100, 0, 0, 0}}
+};
+
+static void
+report_date_error (int err)
+{
+ switch(err)
+ {
+ case 1:
+ printf ("The environment variable DATEMSK is not defined or null.\n");
+ break;
+ case 2:
+ printf ("The template file denoted by the DATEMSK environment variable cannot be opened.\n");
+ break;
+ case 3:
+ printf ("Information about the template file cannot retrieved.\n");
+ break;
+ case 4:
+ printf ("The template file is not a regular file.\n");
+ break;
+ case 5:
+ printf ("An I/O error occurred while reading the template file.\n");
+ break;
+ case 6:
+ printf ("Not enough memory available to execute the function.\n");
+ break;
+ case 7:
+ printf ("The template file contains no matching template.\n");
+ break;
+ case 8:
+ printf ("The input date is invalid, but would match a template otherwise.\n");
+ break;
+ default:
+ printf("Unknown error code.\n");
+ break;
+ }
+}
+
+
+static int
+do_test (void)
+{
+ int errors = 0;
+ size_t i;
+ struct tm *tm;
+
+
+ for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+ {
+ setenv ("TZ", tests[i].tz, 1);
+
+ tm = getdate (tests[i].str);
+
+ if (getdate_err != tests[i].err)
+ {
+ printf ("Failure for getdate (\"%s\"):\n", tests[i].str);
+ printf ("getdate_err should be %d but returned: %d which means:\n",
+ tests[i].err, getdate_err);
+ report_date_error (getdate_err);
+ ++errors;
+ }
+ else if (tests[i].tm.tm_mon != tm->tm_mon
+ || tests[i].tm.tm_year != tm->tm_year
+ || tests[i].tm.tm_mday != tm->tm_mday
+ || tests[i].tm.tm_hour != tm->tm_hour
+ || tests[i].tm.tm_min != tm->tm_min
+ || tests[i].tm.tm_sec != tm->tm_sec)
+ {
+ printf ("Failure for getdate (\"%s\"):\n", tests[i].str);
+ printf ("struct tm is: %d-%d-%d %d:%d:%d\n",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ printf ("but should be: %d-%d-%d %d:%d:%d\n",
+ tests[i].tm.tm_year + 1900, tests[i].tm.tm_mon + 1,
+ tests[i].tm.tm_mday,
+ tests[i].tm.tm_hour, tests[i].tm.tm_min, tests[i].tm.tm_sec);
+ ++errors;
+ }
+ }
+
+ if (!errors)
+ printf ("No errors found.\n");
+ return errors != 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-mktime.c b/REORG.TODO/time/tst-mktime.c
new file mode 100644
index 0000000000..c1473600dd
--- /dev/null
+++ b/REORG.TODO/time/tst-mktime.c
@@ -0,0 +1,73 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+static int
+do_test (void)
+{
+ struct tm time_str, *tm;
+ time_t t;
+ char daybuf[20];
+ int result;
+
+ time_str.tm_year = 2001 - 1900;
+ time_str.tm_mon = 7 - 1;
+ time_str.tm_mday = 4;
+ time_str.tm_hour = 0;
+ time_str.tm_min = 0;
+ time_str.tm_sec = 1;
+ time_str.tm_isdst = -1;
+
+ if (mktime (&time_str) == -1)
+ {
+ (void) puts ("-unknown-");
+ result = 1;
+ }
+ else
+ {
+ (void) strftime (daybuf, sizeof (daybuf), "%A", &time_str);
+ (void) puts (daybuf);
+ result = strcmp (daybuf, "Wednesday") != 0;
+ }
+
+ setenv ("TZ", "EST+5", 1);
+#define EVENING69 1 * 60 * 60 + 2 * 60 + 29
+ t = EVENING69;
+ tm = localtime (&t);
+ if (tm == NULL)
+ {
+ (void) puts ("localtime returned NULL");
+ result = 1;
+ }
+ else
+ {
+ time_str = *tm;
+ t = mktime (&time_str);
+ if (t != EVENING69)
+ {
+ printf ("mktime returned %ld, expected %d\n",
+ (long) t, EVENING69);
+ result = 1;
+ }
+ else
+ (void) puts ("Dec 31 1969 EST test passed");
+
+ setenv ("TZ", "CET-1", 1);
+ t = mktime (&time_str);
+#define EVENING69_CET (EVENING69 - (5 - -1) * 60 * 60)
+ if (t != EVENING69_CET)
+ {
+ printf ("mktime returned %ld, expected %ld\n",
+ (long) t, (long) EVENING69_CET);
+ result = 1;
+ }
+ else
+ (void) puts ("Dec 31 1969 CET test passed");
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-mktime2.c b/REORG.TODO/time/tst-mktime2.c
new file mode 100644
index 0000000000..c41db3e3b7
--- /dev/null
+++ b/REORG.TODO/time/tst-mktime2.c
@@ -0,0 +1,158 @@
+/* Test program from Paul Eggert and Tony Leneis. */
+
+#include <limits.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* True if the arithmetic type T is signed. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* The maximum and minimum values for the integer type T. These
+ macros have undefined behavior if T is signed and has padding bits.
+ If this is a problem for you, please let us know how to fix it for
+ your host. */
+#define TYPE_MINIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) 0 \
+ : ~ TYPE_MAXIMUM (t)))
+#define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
+
+#ifndef TIME_T_MIN
+# define TIME_T_MIN TYPE_MINIMUM (time_t)
+#endif
+#ifndef TIME_T_MAX
+# define TIME_T_MAX TYPE_MAXIMUM (time_t)
+#endif
+
+/* Values we'll use to set the TZ environment variable. */
+static const char *tz_strings[] =
+ {
+ (const char *) 0, "GMT0", "JST-9",
+ "EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00"
+ };
+#define N_STRINGS ((int) (sizeof (tz_strings) / sizeof (tz_strings[0])))
+
+/* Fail if mktime fails to convert a date in the spring-forward gap.
+ Based on a problem report from Andreas Jaeger. */
+static void
+spring_forward_gap (void)
+{
+ /* glibc (up to about 1998-10-07) failed this test. */
+ struct tm tm;
+
+ /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0"
+ instead of "TZ=America/Vancouver" in order to detect the bug even
+ on systems that don't support the Olson extension, or don't have the
+ full zoneinfo tables installed. */
+ setenv ("TZ", "PST8PDT,M4.1.0,M10.5.0", 1);
+
+ tm.tm_year = 98;
+ tm.tm_mon = 3;
+ tm.tm_mday = 5;
+ tm.tm_hour = 2;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_isdst = -1;
+ if (mktime (&tm) == (time_t)-1)
+ exit (1);
+}
+
+static void
+mktime_test1 (time_t now)
+{
+ struct tm *lt = localtime (&now);
+ if (lt && mktime (lt) != now)
+ exit (2);
+}
+
+static void
+mktime_test (time_t now)
+{
+ mktime_test1 (now);
+ mktime_test1 ((time_t) (TIME_T_MAX - now));
+ mktime_test1 ((time_t) (TIME_T_MIN + now));
+}
+
+static void
+irix_6_4_bug (void)
+{
+ /* Based on code from Ariel Faigon. */
+ struct tm tm;
+ tm.tm_year = 96;
+ tm.tm_mon = 3;
+ tm.tm_mday = 0;
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_isdst = -1;
+ mktime (&tm);
+ if (tm.tm_mon != 2 || tm.tm_mday != 31)
+ exit (3);
+}
+
+static void
+bigtime_test (int j)
+{
+ struct tm tm;
+ time_t now;
+ tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j;
+ tm.tm_isdst = -1;
+ now = mktime (&tm);
+ if (now != (time_t) -1)
+ {
+ struct tm *lt = localtime (&now);
+ if (! (lt
+ && lt->tm_year == tm.tm_year
+ && lt->tm_mon == tm.tm_mon
+ && lt->tm_mday == tm.tm_mday
+ && lt->tm_hour == tm.tm_hour
+ && lt->tm_min == tm.tm_min
+ && lt->tm_sec == tm.tm_sec
+ && lt->tm_yday == tm.tm_yday
+ && lt->tm_wday == tm.tm_wday
+ && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst)
+ == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst))))
+ exit (4);
+ }
+}
+
+static int
+do_test (void)
+{
+ time_t t, delta;
+ int i;
+ unsigned int j;
+
+ setenv ("TZ", "America/Sao_Paulo", 1);
+ /* This test makes some buggy mktime implementations loop.
+ Give up after 60 seconds; a mktime slower than that
+ isn't worth using anyway. */
+ alarm (60);
+
+ delta = TIME_T_MAX / 997; /* a suitable prime number */
+ for (i = 0; i < N_STRINGS; i++)
+ {
+ if (tz_strings[i])
+ setenv ("TZ", tz_strings[i], 1);
+
+ for (t = 0; t <= TIME_T_MAX - delta; t += delta)
+ mktime_test (t);
+ mktime_test ((time_t) 1);
+ mktime_test ((time_t) (60 * 60));
+ mktime_test ((time_t) (60 * 60 * 24));
+
+ for (j = 1; j <= INT_MAX; j *= 2)
+ bigtime_test (j);
+ bigtime_test (j - 1);
+ }
+ irix_6_4_bug ();
+ spring_forward_gap ();
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-mktime3.c b/REORG.TODO/time/tst-mktime3.c
new file mode 100644
index 0000000000..c738e5384a
--- /dev/null
+++ b/REORG.TODO/time/tst-mktime3.c
@@ -0,0 +1,53 @@
+/* Test program for mktime bugs with out-of-range tm_sec values. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+struct tm tests[] =
+{
+ { .tm_sec = -1, .tm_mday = 1, .tm_year = 104 },
+ { .tm_sec = 65, .tm_min = 59, .tm_hour = 23, .tm_mday = 31,
+ .tm_mon = 11, .tm_year = 101 }
+};
+struct tm expected[] =
+{
+ { .tm_sec = 59, .tm_min = 59, .tm_hour = 23, .tm_mday = 31,
+ .tm_mon = 11, .tm_year = 103, .tm_wday = 3, .tm_yday = 364 },
+ { .tm_sec = 5, .tm_mday = 1, .tm_year = 102, .tm_wday = 2 }
+};
+
+static int
+do_test (void)
+{
+ setenv ("TZ", "UTC", 1);
+ int i;
+ for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+ {
+ if (mktime (&tests[i]) < 0)
+ {
+ printf ("mktime %d failed\n", i);
+ return 1;
+ }
+#define CHECK(name) \
+ if (tests[i].name != expected[i].name) \
+ { \
+ printf ("test %d " #name " got %d expected %d\n", \
+ i, tests[i].name, expected[i].name); \
+ return 1; \
+ }
+ CHECK (tm_sec)
+ CHECK (tm_min)
+ CHECK (tm_hour)
+ CHECK (tm_mday)
+ CHECK (tm_mon)
+ CHECK (tm_year)
+ CHECK (tm_wday)
+ CHECK (tm_yday)
+ CHECK (tm_isdst)
+ }
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-posixtz.c b/REORG.TODO/time/tst-posixtz.c
new file mode 100644
index 0000000000..9bec7ae4bb
--- /dev/null
+++ b/REORG.TODO/time/tst-posixtz.c
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdint.h>
+
+struct
+{
+ time_t when;
+ const char *tz;
+ const char *result;
+} tests[] =
+{
+ { 909312849L, "AEST-10AEDST-11,M10.5.0,M3.5.0",
+ "1998/10/25 21:54:09 dst=1 zone=AEDST" },
+ { 924864849L, "AEST-10AEDST-11,M10.5.0,M3.5.0",
+ "1999/04/23 20:54:09 dst=0 zone=AEST" },
+ { 919973892L, "AEST-10AEDST-11,M10.5.0,M3.5.0",
+ "1999/02/26 07:18:12 dst=1 zone=AEDST" },
+ { 909312849L, "EST+5EDT,M4.1.0/2,M10.5.0/2",
+ "1998/10/25 05:54:09 dst=0 zone=EST" },
+ { 909312849L, "EST5EDT,M4.1.0/2,M10.5.0/2",
+ "1998/10/25 05:54:09 dst=0 zone=EST" },
+ { 909312849L, "<EST5>5EDT,M4.1.0/2,M10.5.0/2",
+ "1998/10/25 05:54:09 dst=0 zone=EST5" },
+ { 924864849L, "EST+5EDT,M4.1.0/2,M10.5.0/2",
+ "1999/04/23 06:54:09 dst=1 zone=EDT" },
+ { 919973892L, "EST+5EDT,M4.1.0/2,M10.5.0/2",
+ "1999/02/25 15:18:12 dst=0 zone=EST" },
+};
+
+static int
+do_test (void)
+{
+ int result = 0;
+ size_t cnt;
+
+ for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt)
+ {
+ char buf[100];
+ struct tm *tmp;
+
+ printf ("TZ = \"%s\", time = %jd => ", tests[cnt].tz,
+ (intmax_t) tests[cnt].when);
+ fflush (stdout);
+
+ setenv ("TZ", tests[cnt].tz, 1);
+
+ tmp = localtime (&tests[cnt].when);
+
+ snprintf (buf, sizeof (buf),
+ "%04d/%02d/%02d %02d:%02d:%02d dst=%d zone=%s",
+ tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tmp->tm_isdst,
+ tzname[tmp->tm_isdst ? 1 : 0]);
+
+ fputs (buf, stdout);
+
+ if (strcmp (buf, tests[cnt].result) == 0)
+ puts (", OK");
+ else
+ {
+ result = 1;
+ puts (", FAIL");
+ }
+ }
+
+ setenv ("TZ", "Universal", 1);
+ localtime (&tests[0].when);
+ printf ("TZ = \"Universal\" daylight %d tzname = { \"%s\", \"%s\" }",
+ daylight, tzname[0], tzname[1]);
+ if (! daylight)
+ puts (", OK");
+ else
+ {
+ result = 1;
+ puts (", FAIL");
+ }
+
+ setenv ("TZ", "AEST-10AEDST-11,M10.5.0,M3.5.0", 1);
+ tzset ();
+ printf ("TZ = \"AEST-10AEDST-11,M10.5.0,M3.5.0\" daylight %d"
+ " tzname = { \"%s\", \"%s\" }", daylight, tzname[0], tzname[1]);
+ if (daylight
+ && strcmp (tzname[0], "AEST") == 0 && strcmp (tzname[1], "AEDST") == 0)
+ puts (", OK");
+ else
+ {
+ result = 1;
+ puts (", FAIL");
+ }
+
+ setenv ("TZ", "<AB1>-10<AB2>-11,M10.5.0,M3.5.0", 1);
+ tzset ();
+ printf ("TZ = \"<AB1>-10<AB2>-11,M10.5.0,M3.5.0\" daylight %d"
+ " tzname = { \"%s\", \"%s\" }", daylight, tzname[0], tzname[1]);
+ if (daylight
+ && strcmp (tzname[0], "AB1") == 0 && strcmp (tzname[1], "AB2") == 0)
+ puts (", OK");
+ else
+ {
+ result = 1;
+ puts (", FAIL");
+ }
+
+ setenv ("TZ", "<BB1>-10", 1);
+ tzset ();
+ printf ("TZ = \"<BB1>-10\" daylight %d"
+ " tzname = { \"%s\", \"%s\" }", daylight, tzname[0], tzname[1]);
+ if (daylight == 0
+ && strcmp (tzname[0], "BB1") == 0 && strcmp (tzname[1], "BB1") == 0)
+ puts (", OK");
+ else
+ {
+ result = 1;
+ puts (", FAIL");
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-strftime.c b/REORG.TODO/time/tst-strftime.c
new file mode 100644
index 0000000000..af3ff72faf
--- /dev/null
+++ b/REORG.TODO/time/tst-strftime.c
@@ -0,0 +1,161 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+
+static int
+do_bz18985 (void)
+{
+ char buf[1000];
+ struct tm ttm;
+ int rc, ret = 0;
+
+ memset (&ttm, 1, sizeof (ttm));
+ ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */
+ rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
+
+ if (rc == 66)
+ {
+ const char expected[]
+ = "? ? ? ? ? ? 16843009 16843009:16843009:16843009 16844909 +467836 ?";
+ if (0 != strcmp (buf, expected))
+ {
+ printf ("expected:\n %s\ngot:\n %s\n", expected, buf);
+ ret += 1;
+ }
+ }
+ else
+ {
+ printf ("expected 66, got %d\n", rc);
+ ret += 1;
+ }
+
+ /* Check negative values as well. */
+ memset (&ttm, 0xFF, sizeof (ttm));
+ ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */
+ rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
+
+ if (rc == 30)
+ {
+ const char expected[] = "? ? ? ? ? ? -1 -1:-1:-1 1899 ";
+ if (0 != strcmp (buf, expected))
+ {
+ printf ("expected:\n %s\ngot:\n %s\n", expected, buf);
+ ret += 1;
+ }
+ }
+ else
+ {
+ printf ("expected 30, got %d\n", rc);
+ ret += 1;
+ }
+
+ return ret;
+}
+
+static struct
+{
+ const char *fmt;
+ size_t min;
+ size_t max;
+} tests[] =
+ {
+ { "%2000Y", 2000, 4000 },
+ { "%02000Y", 2000, 4000 },
+ { "%_2000Y", 2000, 4000 },
+ { "%-2000Y", 2000, 4000 },
+ };
+#define ntests (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+ size_t cnt;
+ int result = 0;
+
+ time_t tnow = time (NULL);
+ struct tm *now = localtime (&tnow);
+
+ for (cnt = 0; cnt < ntests; ++cnt)
+ {
+ size_t size = 0;
+ int res;
+ char *buf = NULL;
+
+ do
+ {
+ size += 500;
+ buf = (char *) realloc (buf, size);
+ if (buf == NULL)
+ {
+ puts ("out of memory");
+ exit (1);
+ }
+
+ res = strftime (buf, size, tests[cnt].fmt, now);
+ if (res != 0)
+ break;
+ }
+ while (size < tests[cnt].max);
+
+ if (res == 0)
+ {
+ printf ("%Zu: %s: res == 0 despite size == %Zu\n",
+ cnt, tests[cnt].fmt, size);
+ result = 1;
+ }
+ else if (size < tests[cnt].min)
+ {
+ printf ("%Zu: %s: size == %Zu was enough\n",
+ cnt, tests[cnt].fmt, size);
+ result = 1;
+ }
+ else
+ printf ("%Zu: %s: size == %Zu: OK\n", cnt, tests[cnt].fmt, size);
+
+ free (buf);
+ }
+
+ struct tm ttm =
+ {
+ /* Initialize the fields which are needed in the tests. */
+ .tm_mday = 1,
+ .tm_hour = 2
+ };
+ const struct
+ {
+ const char *fmt;
+ const char *exp;
+ size_t n;
+ } ftests[] =
+ {
+ { "%-e", "1", 1 },
+ { "%-k", "2", 1 },
+ { "%-l", "2", 1 },
+ };
+#define nftests (sizeof (ftests) / sizeof (ftests[0]))
+ for (cnt = 0; cnt < nftests; ++cnt)
+ {
+ char buf[100];
+ size_t r = strftime (buf, sizeof (buf), ftests[cnt].fmt, &ttm);
+ if (r != ftests[cnt].n)
+ {
+ printf ("strftime(\"%s\") returned %zu not %zu\n",
+ ftests[cnt].fmt, r, ftests[cnt].n);
+ result = 1;
+ }
+ if (strcmp (buf, ftests[cnt].exp) != 0)
+ {
+ printf ("strftime(\"%s\") produced \"%s\" not \"%s\"\n",
+ ftests[cnt].fmt, buf, ftests[cnt].exp);
+ result = 1;
+ }
+ }
+
+ return result + do_bz18985 ();
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-strptime-whitespace.c b/REORG.TODO/time/tst-strptime-whitespace.c
new file mode 100644
index 0000000000..90d4da80ca
--- /dev/null
+++ b/REORG.TODO/time/tst-strptime-whitespace.c
@@ -0,0 +1,43 @@
+/* Verify that strptime accepts arbitrary whitespace between tokens.
+
+ Copyright (C) 2013-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define _XOPEN_SOURCE
+#include <time.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+do_test (void)
+{
+ struct tm t;
+ const char *in = "Tuesday \t 22 \t July\t1942";
+
+ char *r = strptime (in, "%A%d %b%Y", &t);
+
+ if (r == NULL || r != in + strlen (in))
+ {
+ printf ("strptime failed\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-strptime.c b/REORG.TODO/time/tst-strptime.c
new file mode 100644
index 0000000000..4e9e38c8f3
--- /dev/null
+++ b/REORG.TODO/time/tst-strptime.c
@@ -0,0 +1,199 @@
+/* Test for strptime.
+ Copyright (C) 1998-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+
+static const struct
+{
+ const char *locale;
+ const char *input;
+ const char *format;
+ int wday;
+ int yday;
+ int mon;
+ int mday;
+} day_tests[] =
+{
+ { "C", "2000-01-01", "%Y-%m-%d", 6, 0, 0, 1 },
+ { "C", "03/03/00", "%D", 5, 62, 2, 3 },
+ { "C", "9/9/99", "%x", 4, 251, 8, 9 },
+ { "C", "19990502123412", "%Y%m%d%H%M%S", 0, 121, 4, 2 },
+ { "C", "2001 20 Mon", "%Y %U %a", 1, 140, 4, 21 },
+ { "C", "2001 21 Mon", "%Y %W %a", 1, 140, 4, 21 },
+ { "C", "2001 21 Mon", "%2000Y %W %a", 1, 140, 4, 21 },
+ { "C", "2001 21 Mon", "%^Y %W %a", 1, 140, 4, 21 },
+ { "C", "2001 EST 21 Mon", "%Y %Z %W %a", 1, 140, 4, 21 },
+ { "C", "2012 00 Sun", "%Y %W %a", 0, 0, 0, 1 },
+ { "ja_JP.EUC-JP", "2000-01-01 08:12:21 AM", "%Y-%m-%d %I:%M:%S %p",
+ 6, 0, 0, 1 },
+ { "en_US.ISO-8859-1", "2000-01-01 08:12:21 PM", "%Y-%m-%d %I:%M:%S %p",
+ 6, 0, 0, 1 },
+ { "ja_JP.EUC-JP", "2001 20 \xb7\xee", "%Y %U %a", 1, 140, 4, 21 },
+ { "ja_JP.EUC-JP", "2001 21 \xb7\xee", "%Y %W %a", 1, 140, 4, 21 },
+};
+
+
+static const struct
+{
+ const char *input;
+ const char *format;
+ const char *output;
+ int wday;
+ int yday;
+} tm_tests [] =
+{
+ {"17410105012000", "%H%M%S%d%m%Y", "2000-01-05 17:41:01", 3, 4}
+};
+
+
+
+static int
+test_tm (void)
+{
+ struct tm tm;
+ size_t i;
+ int result = 0;
+ char buf[100];
+
+ for (i = 0; i < sizeof (tm_tests) / sizeof (tm_tests[0]); ++i)
+ {
+ memset (&tm, '\0', sizeof (tm));
+
+ char *ret = strptime (tm_tests[i].input, tm_tests[i].format, &tm);
+ if (ret == NULL)
+ {
+ printf ("strptime returned NULL for `%s'\n", tm_tests[i].input);
+ result = 1;
+ continue;
+ }
+ else if (*ret != '\0')
+ {
+ printf ("not all of `%s' read\n", tm_tests[i].input);
+ result = 1;
+ }
+ strftime (buf, sizeof (buf), "%F %T", &tm);
+ printf ("strptime (\"%s\", \"%s\", ...)\n"
+ "\tshould be: %s, wday = %d, yday = %3d\n"
+ "\t is: %s, wday = %d, yday = %3d\n",
+ tm_tests[i].input, tm_tests[i].format,
+ tm_tests[i].output,
+ tm_tests[i].wday, tm_tests[i].yday,
+ buf, tm.tm_wday, tm.tm_yday);
+
+ if (strcmp (buf, tm_tests[i].output) != 0)
+ {
+ printf ("Time and date are not correct.\n");
+ result = 1;
+ }
+ if (tm.tm_wday != tm_tests[i].wday)
+ {
+ printf ("weekday for `%s' incorrect: %d instead of %d\n",
+ tm_tests[i].input, tm.tm_wday, tm_tests[i].wday);
+ result = 1;
+ }
+ if (tm.tm_yday != tm_tests[i].yday)
+ {
+ printf ("yearday for `%s' incorrect: %d instead of %d\n",
+ tm_tests[i].input, tm.tm_yday, tm_tests[i].yday);
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+
+static int
+do_test (void)
+{
+ struct tm tm;
+ size_t i;
+ int result = 0;
+
+ for (i = 0; i < sizeof (day_tests) / sizeof (day_tests[0]); ++i)
+ {
+ memset (&tm, '\0', sizeof (tm));
+
+ if (setlocale (LC_ALL, day_tests[i].locale) == NULL)
+ {
+ printf ("cannot set locale %s: %m\n", day_tests[i].locale);
+ exit (EXIT_FAILURE);
+ }
+
+ char *ret = strptime (day_tests[i].input, day_tests[i].format, &tm);
+ if (ret == NULL)
+ {
+ printf ("strptime returned NULL for `%s'\n", day_tests[i].input);
+ result = 1;
+ continue;
+ }
+ else if (*ret != '\0')
+ {
+ printf ("not all of `%s' read\n", day_tests[i].input);
+ result = 1;
+ }
+
+ printf ("strptime (\"%s\", \"%s\", ...)\n"
+ "\tshould be: wday = %d, yday = %3d, mon = %2d, mday = %2d\n"
+ "\t is: wday = %d, yday = %3d, mon = %2d, mday = %2d\n",
+ day_tests[i].input, day_tests[i].format,
+ day_tests[i].wday, day_tests[i].yday,
+ day_tests[i].mon, day_tests[i].mday,
+ tm.tm_wday, tm.tm_yday, tm.tm_mon, tm.tm_mday);
+
+ if (tm.tm_wday != day_tests[i].wday)
+ {
+ printf ("weekday for `%s' incorrect: %d instead of %d\n",
+ day_tests[i].input, tm.tm_wday, day_tests[i].wday);
+ result = 1;
+ }
+ if (tm.tm_yday != day_tests[i].yday)
+ {
+ printf ("yearday for `%s' incorrect: %d instead of %d\n",
+ day_tests[i].input, tm.tm_yday, day_tests[i].yday);
+ result = 1;
+ }
+ if (tm.tm_mon != day_tests[i].mon)
+ {
+ printf ("month for `%s' incorrect: %d instead of %d\n",
+ day_tests[i].input, tm.tm_mon, day_tests[i].mon);
+ result = 1;
+ }
+ if (tm.tm_mday != day_tests[i].mday)
+ {
+ printf ("monthday for `%s' incorrect: %d instead of %d\n",
+ day_tests[i].input, tm.tm_mday, day_tests[i].mday);
+ result = 1;
+ }
+ }
+
+ setlocale (LC_ALL, "C");
+
+ result |= test_tm ();
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-strptime2.c b/REORG.TODO/time/tst-strptime2.c
new file mode 100644
index 0000000000..8019e7f5d8
--- /dev/null
+++ b/REORG.TODO/time/tst-strptime2.c
@@ -0,0 +1,235 @@
+/* tst-strptime2 - Test strptime %z timezone offset specifier. */
+
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <time.h>
+#include <libc-diag.h>
+
+/* Dummy string is used to match strptime's %s specifier. */
+
+static const char dummy_string[] = "1113472456";
+
+/* buffer_size contains the maximum test string length, including
+ trailing NUL. */
+
+enum
+{
+ buffer_size = 20,
+};
+
+/* Verbose execution, set with --verbose command line option. */
+
+static bool verbose;
+
+
+/* mkbuf - Write a test string for strptime with the specified time
+ value and number of digits into the supplied buffer, and return
+ the expected strptime test result.
+
+ The test string, buf, is written with the following content:
+ a dummy string matching strptime "%s" format specifier,
+ whitespace matching strptime " " format specifier, and
+ timezone string matching strptime "%z" format specifier.
+
+ Note that a valid timezone string is either "Z" or contains the
+ following fields:
+ Sign field consisting of a '+' or '-' sign,
+ Hours field in two decimal digits, and
+ optional Minutes field in two decimal digits. Optionally,
+ a ':' is used to seperate hours and minutes.
+
+ This function may write test strings with minutes values outside
+ the valid range 00-59. These are invalid strings and useful for
+ testing strptime's rejection of invalid strings.
+
+ The ndigits parameter is used to limit the number of timezone
+ string digits to be written and may range from 0 to 4. Note that
+ only 2 and 4 digit strings are valid input to strptime; strings
+ with 0, 1 or 3 digits are invalid and useful for testing strptime's
+ rejection of invalid strings.
+
+ This function returns the behavior expected of strptime resulting
+ from parsing the the test string. For valid strings, the function
+ returns the expected tm_gmtoff value. For invalid strings,
+ LONG_MAX is returned. LONG_MAX indicates the expectation that
+ strptime will return NULL; for example, if the number of digits
+ are not correct, or minutes part of the time is outside the valid
+ range of 00 to 59. */
+
+static long int
+mkbuf (char *buf, bool neg, bool colon, unsigned int hhmm, size_t ndigits)
+{
+ const int mm_max = 59;
+ char sign = neg ? '-' : '+';
+ int i;
+ unsigned int hh = hhmm / 100;
+ unsigned int mm = hhmm % 100;
+ long int expect = LONG_MAX;
+
+ i = sprintf (buf, "%s %c", dummy_string, sign);
+#if __GNUC_PREREQ (7, 0)
+ /* GCC issues a warning when it thinks the snprintf buffer may be too short.
+ This test is explicitly using short buffers to force snprintf to truncate
+ the output so we ignore the warnings. */
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_NEEDS_COMMENT (7.0, "-Wformat-truncation");
+#endif
+ if (colon)
+ snprintf (buf + i, ndigits + 2, "%02u:%02u", hh, mm);
+ else
+ snprintf (buf + i, ndigits + 1, "%04u", hhmm);
+#if __GNUC_PREREQ (7, 0)
+ DIAG_POP_NEEDS_COMMENT;
+#endif
+
+ if (mm <= mm_max && (ndigits == 2 || ndigits == 4))
+ {
+ long int tm_gmtoff = hh * 3600 + mm * 60;
+
+ expect = neg ? -tm_gmtoff : tm_gmtoff;
+ }
+
+ return expect;
+}
+
+
+/* Write a description of expected or actual test result to stdout. */
+
+static void
+describe (bool string_valid, long int tm_gmtoff)
+{
+ if (string_valid)
+ printf ("valid, tm.tm_gmtoff %ld", tm_gmtoff);
+ else
+ printf ("invalid, return value NULL");
+}
+
+
+/* Using buffer buf, run strptime. Compare results against expect,
+ the expected result. Report failures and verbose results to stdout.
+ Update the result counts. Return 1 if test failed, 0 if passed. */
+
+static int
+compare (const char *buf, long int expect, unsigned int *nresult)
+{
+ struct tm tm;
+ char *p;
+ bool test_string_valid;
+ long int test_result;
+ bool fail;
+ int result;
+
+ p = strptime (buf, "%s %z", &tm);
+ test_string_valid = p != NULL;
+ test_result = test_string_valid ? tm.tm_gmtoff : LONG_MAX;
+ fail = test_result != expect;
+
+ if (fail || verbose)
+ {
+ bool expect_string_valid = expect != LONG_MAX;
+
+ printf ("%s: input \"%s\", expected: ", fail ? "FAIL" : "PASS", buf);
+ describe (expect_string_valid, expect);
+
+ if (fail)
+ {
+ printf (", got: ");
+ describe (test_string_valid, test_result);
+ }
+
+ printf ("\n");
+ }
+
+ result = fail ? 1 : 0;
+ nresult[result]++;
+
+ return result;
+}
+
+
+static int
+do_test (void)
+{
+ char buf[buffer_size];
+ long int expect;
+ int result = 0;
+ /* Number of tests run with passing (index==0) and failing (index==1)
+ results. */
+ unsigned int nresult[2];
+ unsigned int ndigits;
+ unsigned int step;
+ unsigned int hhmm;
+
+ nresult[0] = 0;
+ nresult[1] = 0;
+
+ /* Create and test input string with no sign and four digits input
+ (invalid format). */
+
+ sprintf (buf, "%s 1030", dummy_string);
+ expect = LONG_MAX;
+ result |= compare (buf, expect, nresult);
+
+ /* Create and test input string with "Z" input (valid format).
+ Expect tm_gmtoff of 0. */
+
+ sprintf (buf, "%s Z", dummy_string);
+ expect = 0;
+ result |= compare (buf, expect, nresult);
+
+ /* Create and test input strings with sign and digits:
+ 0 digits (invalid format),
+ 1 digit (invalid format),
+ 2 digits (valid format),
+ 3 digits (invalid format),
+ 4 digits (valid format if and only if minutes is in range 00-59,
+ otherwise invalid).
+ If format is valid, the returned tm_gmtoff is checked. */
+
+ for (ndigits = 0, step = 10000; ndigits <= 4; ndigits++, step /= 10)
+ for (hhmm = 0; hhmm <= 9999; hhmm += step)
+ {
+ /* Test both positive and negative signs. */
+
+ expect = mkbuf (buf, false, false, hhmm, ndigits);
+ result |= compare (buf, expect, nresult);
+
+ expect = mkbuf (buf, true, false, hhmm, ndigits);
+ result |= compare (buf, expect, nresult);
+
+ /* Test with colon as well. */
+
+ if (ndigits >= 3)
+ {
+ expect = mkbuf (buf, false, true, hhmm, ndigits);
+ result |= compare (buf, expect, nresult);
+
+ expect = mkbuf (buf, true, true, hhmm, ndigits);
+ result |= compare (buf, expect, nresult);
+ }
+ }
+
+ if (result > 0 || verbose)
+ printf ("%s: %u input strings: %u fail, %u pass\n",
+ result > 0 ? "FAIL" : "PASS",
+ nresult[1] + nresult[0], nresult[1], nresult[0]);
+
+ return result;
+}
+
+
+/* Add a "--verbose" command line option to test-skeleton.c. */
+
+#define OPT_VERBOSE 10000
+
+#define CMDLINE_OPTIONS \
+ { "verbose", no_argument, NULL, OPT_VERBOSE, },
+
+#define CMDLINE_PROCESS \
+ case OPT_VERBOSE: \
+ verbose = true; \
+ break;
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-strptime3.c b/REORG.TODO/time/tst-strptime3.c
new file mode 100644
index 0000000000..d53f51ee22
--- /dev/null
+++ b/REORG.TODO/time/tst-strptime3.c
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+ struct tm tm;
+
+ memset (&tm, 0xaa, sizeof (tm));
+
+ /* Test we don't crash on uninitialized struct tm.
+ Some fields might contain bogus values until everything
+ needed is initialized, but we shouldn't crash. */
+ if (strptime ("2007", "%Y", &tm) == NULL
+ || strptime ("12", "%d", &tm) == NULL
+ || strptime ("Feb", "%b", &tm) == NULL
+ || strptime ("13", "%M", &tm) == NULL
+ || strptime ("21", "%S", &tm) == NULL
+ || strptime ("16", "%H", &tm) == NULL)
+ {
+ puts ("strptimes failed");
+ result = 1;
+ }
+
+ if (tm.tm_sec != 21 || tm.tm_min != 13 || tm.tm_hour != 16
+ || tm.tm_mday != 12 || tm.tm_mon != 1 || tm.tm_year != 107
+ || tm.tm_wday != 1 || tm.tm_yday != 42)
+ {
+ puts ("unexpected tm content");
+ result = 1;
+ }
+
+ if (strptime ("8", "%d", &tm) == NULL)
+ {
+ puts ("strptime failed");
+ result = 1;
+ }
+
+ if (tm.tm_sec != 21 || tm.tm_min != 13 || tm.tm_hour != 16
+ || tm.tm_mday != 8 || tm.tm_mon != 1 || tm.tm_year != 107
+ || tm.tm_wday != 4 || tm.tm_yday != 38)
+ {
+ puts ("unexpected tm content");
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst-tzname.c b/REORG.TODO/time/tst-tzname.c
new file mode 100644
index 0000000000..f0ce13f835
--- /dev/null
+++ b/REORG.TODO/time/tst-tzname.c
@@ -0,0 +1,50 @@
+/* Test that tzset sets tzname correctly (BZ #19253).
+ Copyright (C) 2015-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+static int
+do_test (void)
+{
+ int result = 0;
+
+ setenv ("TZ", TZDEFRULES, 1);
+ tzset ();
+ const char *stdtz = strdup (tzname[0]);
+ setenv ("TZ", "STD-1DST", 1);
+ tzset ();
+ if (strcmp (tzname[0], "STD") != 0)
+ {
+ printf ("FAIL: TZ=STD-1DST, tzname[0] = %s\n", tzname[0]);
+ result = 1;
+ }
+ setenv ("TZ", TZDEFRULES, 1);
+ tzset ();
+ if (strcmp (tzname[0], stdtz) != 0)
+ {
+ printf ("FAIL: TZ=%s, tzname[0] = %s\n", TZDEFRULES, tzname[0]);
+ result = 1;
+ }
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/time/tst_wcsftime.c b/REORG.TODO/time/tst_wcsftime.c
new file mode 100644
index 0000000000..3f6f0d9f77
--- /dev/null
+++ b/REORG.TODO/time/tst_wcsftime.c
@@ -0,0 +1,28 @@
+#include <time.h>
+#include <wchar.h>
+
+int
+main (int argc, char *argv[])
+{
+ wchar_t buf[200];
+ time_t t;
+ struct tm *tp;
+ int result = 0;
+ size_t n;
+
+ time (&t);
+ tp = gmtime (&t);
+
+ n = wcsftime (buf, sizeof (buf) / sizeof (buf[0]),
+ L"%H:%M:%S %Y-%m-%d\n", tp);
+ if (n != 21)
+ result = 1;
+
+ wprintf (L"It is now %ls", buf);
+
+ wcsftime (buf, sizeof (buf) / sizeof (buf[0]), L"%A\n", tp);
+
+ wprintf (L"The weekday is %ls", buf);
+
+ return result;
+}
diff --git a/REORG.TODO/time/tzfile.c b/REORG.TODO/time/tzfile.c
new file mode 100644
index 0000000000..d41246980b
--- /dev/null
+++ b/REORG.TODO/time/tzfile.c
@@ -0,0 +1,832 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdint.h>
+
+#include <timezone/tzfile.h>
+
+int __use_tzfile;
+static dev_t tzfile_dev;
+static ino64_t tzfile_ino;
+static time_t tzfile_mtime;
+
+struct ttinfo
+ {
+ long int offset; /* Seconds east of GMT. */
+ unsigned char isdst; /* Used to set tm_isdst. */
+ unsigned char idx; /* Index into `zone_names'. */
+ unsigned char isstd; /* Transition times are in standard time. */
+ unsigned char isgmt; /* Transition times are in GMT. */
+ };
+
+struct leap
+ {
+ time_t transition; /* Time the transition takes effect. */
+ long int change; /* Seconds of correction to apply. */
+ };
+
+static size_t num_transitions;
+libc_freeres_ptr (static time_t *transitions);
+static unsigned char *type_idxs;
+static size_t num_types;
+static struct ttinfo *types;
+static char *zone_names;
+static long int rule_stdoff;
+static long int rule_dstoff;
+static size_t num_leaps;
+static struct leap *leaps;
+static char *tzspec;
+
+#include <endian.h>
+#include <byteswap.h>
+
+/* Decode the four bytes at PTR as a signed integer in network byte order. */
+static inline int
+__attribute ((always_inline))
+decode (const void *ptr)
+{
+ if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4)
+ return *(const int *) ptr;
+ if (sizeof (int) == 4)
+ return bswap_32 (*(const int *) ptr);
+
+ const unsigned char *p = ptr;
+ int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
+
+ result = (result << 8) | *p++;
+ result = (result << 8) | *p++;
+ result = (result << 8) | *p++;
+ result = (result << 8) | *p++;
+
+ return result;
+}
+
+
+static inline int64_t
+__attribute ((always_inline))
+decode64 (const void *ptr)
+{
+ if ((BYTE_ORDER == BIG_ENDIAN))
+ return *(const int64_t *) ptr;
+
+ return bswap_64 (*(const int64_t *) ptr);
+}
+
+
+void
+__tzfile_read (const char *file, size_t extra, char **extrap)
+{
+ static const char default_tzdir[] = TZDIR;
+ size_t num_isstd, num_isgmt;
+ FILE *f;
+ struct tzhead tzhead;
+ size_t chars;
+ size_t i;
+ size_t total_size;
+ size_t types_idx;
+ size_t leaps_idx;
+ int was_using_tzfile = __use_tzfile;
+ int trans_width = 4;
+ size_t tzspec_len;
+ char *new = NULL;
+
+ if (sizeof (time_t) != 4 && sizeof (time_t) != 8)
+ abort ();
+
+ __use_tzfile = 0;
+
+ if (file == NULL)
+ /* No user specification; use the site-wide default. */
+ file = TZDEFAULT;
+ else if (*file == '\0')
+ /* User specified the empty string; use UTC with no leap seconds. */
+ goto ret_free_transitions;
+ else
+ {
+ /* We must not allow to read an arbitrary file in a setuid
+ program. So we fail for any file which is not in the
+ directory hierachy starting at TZDIR
+ and which is not the system wide default TZDEFAULT. */
+ if (__libc_enable_secure
+ && ((*file == '/'
+ && memcmp (file, TZDEFAULT, sizeof TZDEFAULT)
+ && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1))
+ || strstr (file, "../") != NULL))
+ /* This test is certainly a bit too restrictive but it should
+ catch all critical cases. */
+ goto ret_free_transitions;
+ }
+
+ if (*file != '/')
+ {
+ const char *tzdir;
+
+ tzdir = getenv ("TZDIR");
+ if (tzdir == NULL || *tzdir == '\0')
+ tzdir = default_tzdir;
+ if (__asprintf (&new, "%s/%s", tzdir, file) == -1)
+ goto ret_free_transitions;
+ file = new;
+ }
+
+ /* If we were already using tzfile, check whether the file changed. */
+ struct stat64 st;
+ if (was_using_tzfile
+ && stat64 (file, &st) == 0
+ && tzfile_ino == st.st_ino && tzfile_dev == st.st_dev
+ && tzfile_mtime == st.st_mtime)
+ goto done; /* Nothing to do. */
+
+ /* Note the file is opened with cancellation in the I/O functions
+ disabled and if available FD_CLOEXEC set. */
+ f = fopen (file, "rce");
+ if (f == NULL)
+ goto ret_free_transitions;
+
+ /* Get information about the file we are actually using. */
+ if (fstat64 (__fileno (f), &st) != 0)
+ {
+ fclose (f);
+ goto ret_free_transitions;
+ }
+
+ free ((void *) transitions);
+ transitions = NULL;
+
+ /* Remember the inode and device number and modification time. */
+ tzfile_dev = st.st_dev;
+ tzfile_ino = st.st_ino;
+ tzfile_mtime = st.st_mtime;
+
+ /* No threads reading this stream. */
+ __fsetlocking (f, FSETLOCKING_BYCALLER);
+
+ read_again:
+ if (__builtin_expect (__fread_unlocked ((void *) &tzhead, sizeof (tzhead),
+ 1, f) != 1, 0)
+ || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)
+ goto lose;
+
+ num_transitions = (size_t) decode (tzhead.tzh_timecnt);
+ num_types = (size_t) decode (tzhead.tzh_typecnt);
+ chars = (size_t) decode (tzhead.tzh_charcnt);
+ num_leaps = (size_t) decode (tzhead.tzh_leapcnt);
+ num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
+ num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
+
+ if (__glibc_unlikely (num_isstd > num_types || num_isgmt > num_types))
+ goto lose;
+
+ /* For platforms with 64-bit time_t we use the new format if available. */
+ if (sizeof (time_t) == 8 && trans_width == 4
+ && tzhead.tzh_version[0] != '\0')
+ {
+ /* We use the 8-byte format. */
+ trans_width = 8;
+
+ /* Position the stream before the second header. */
+ size_t to_skip = (num_transitions * (4 + 1)
+ + num_types * 6
+ + chars
+ + num_leaps * 8
+ + num_isstd
+ + num_isgmt);
+ if (fseek (f, to_skip, SEEK_CUR) != 0)
+ goto lose;
+
+ goto read_again;
+ }
+
+ if (__builtin_expect (num_transitions
+ > ((SIZE_MAX - (__alignof__ (struct ttinfo) - 1))
+ / (sizeof (time_t) + 1)), 0))
+ goto lose;
+ total_size = num_transitions * (sizeof (time_t) + 1);
+ total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
+ & ~(__alignof__ (struct ttinfo) - 1));
+ types_idx = total_size;
+ if (__builtin_expect (num_types
+ > (SIZE_MAX - total_size) / sizeof (struct ttinfo), 0))
+ goto lose;
+ total_size += num_types * sizeof (struct ttinfo);
+ if (__glibc_unlikely (chars > SIZE_MAX - total_size))
+ goto lose;
+ total_size += chars;
+ if (__builtin_expect (__alignof__ (struct leap) - 1
+ > SIZE_MAX - total_size, 0))
+ goto lose;
+ total_size = ((total_size + __alignof__ (struct leap) - 1)
+ & ~(__alignof__ (struct leap) - 1));
+ leaps_idx = total_size;
+ if (__builtin_expect (num_leaps
+ > (SIZE_MAX - total_size) / sizeof (struct leap), 0))
+ goto lose;
+ total_size += num_leaps * sizeof (struct leap);
+ tzspec_len = 0;
+ if (sizeof (time_t) == 8 && trans_width == 8)
+ {
+ off_t rem = st.st_size - __ftello (f);
+ if (__builtin_expect (rem < 0
+ || (size_t) rem < (num_transitions * (8 + 1)
+ + num_types * 6
+ + chars), 0))
+ goto lose;
+ tzspec_len = (size_t) rem - (num_transitions * (8 + 1)
+ + num_types * 6
+ + chars);
+ if (__builtin_expect (num_leaps > SIZE_MAX / 12
+ || tzspec_len < num_leaps * 12, 0))
+ goto lose;
+ tzspec_len -= num_leaps * 12;
+ if (__glibc_unlikely (tzspec_len < num_isstd))
+ goto lose;
+ tzspec_len -= num_isstd;
+ if (__glibc_unlikely (tzspec_len == 0 || tzspec_len - 1 < num_isgmt))
+ goto lose;
+ tzspec_len -= num_isgmt + 1;
+ if (__glibc_unlikely (tzspec_len == 0
+ || SIZE_MAX - total_size < tzspec_len))
+ goto lose;
+ }
+ if (__glibc_unlikely (SIZE_MAX - total_size - tzspec_len < extra))
+ goto lose;
+
+ /* Allocate enough memory including the extra block requested by the
+ caller. */
+ transitions = (time_t *) malloc (total_size + tzspec_len + extra);
+ if (transitions == NULL)
+ goto lose;
+
+ type_idxs = (unsigned char *) transitions + (num_transitions
+ * sizeof (time_t));
+ types = (struct ttinfo *) ((char *) transitions + types_idx);
+ zone_names = (char *) types + num_types * sizeof (struct ttinfo);
+ leaps = (struct leap *) ((char *) transitions + leaps_idx);
+ if (sizeof (time_t) == 8 && trans_width == 8)
+ tzspec = (char *) leaps + num_leaps * sizeof (struct leap) + extra;
+ else
+ tzspec = NULL;
+ if (extra > 0)
+ *extrap = (char *) &leaps[num_leaps];
+
+ if (sizeof (time_t) == 4 || __builtin_expect (trans_width == 8, 1))
+ {
+ if (__builtin_expect (__fread_unlocked (transitions, trans_width + 1,
+ num_transitions, f)
+ != num_transitions, 0))
+ goto lose;
+ }
+ else
+ {
+ if (__builtin_expect (__fread_unlocked (transitions, 4,
+ num_transitions, f)
+ != num_transitions, 0)
+ || __builtin_expect (__fread_unlocked (type_idxs, 1, num_transitions,
+ f) != num_transitions, 0))
+ goto lose;
+ }
+
+ /* Check for bogus indices in the data file, so we can hereafter
+ safely use type_idxs[T] as indices into `types' and never crash. */
+ for (i = 0; i < num_transitions; ++i)
+ if (__glibc_unlikely (type_idxs[i] >= num_types))
+ goto lose;
+
+ if ((BYTE_ORDER != BIG_ENDIAN && (sizeof (time_t) == 4 || trans_width == 4))
+ || (BYTE_ORDER == BIG_ENDIAN && sizeof (time_t) == 8
+ && trans_width == 4))
+ {
+ /* Decode the transition times, stored as 4-byte integers in
+ network (big-endian) byte order. We work from the end of
+ the array so as not to clobber the next element to be
+ processed when sizeof (time_t) > 4. */
+ i = num_transitions;
+ while (i-- > 0)
+ transitions[i] = decode ((char *) transitions + i * 4);
+ }
+ else if (BYTE_ORDER != BIG_ENDIAN && sizeof (time_t) == 8)
+ {
+ /* Decode the transition times, stored as 8-byte integers in
+ network (big-endian) byte order. */
+ for (i = 0; i < num_transitions; ++i)
+ transitions[i] = decode64 ((char *) transitions + i * 8);
+ }
+
+ for (i = 0; i < num_types; ++i)
+ {
+ unsigned char x[4];
+ int c;
+ if (__builtin_expect (__fread_unlocked (x, 1,
+ sizeof (x), f) != sizeof (x),
+ 0))
+ goto lose;
+ c = getc_unlocked (f);
+ if (__glibc_unlikely ((unsigned int) c > 1u))
+ goto lose;
+ types[i].isdst = c;
+ c = getc_unlocked (f);
+ if (__glibc_unlikely ((size_t) c > chars))
+ /* Bogus index in data file. */
+ goto lose;
+ types[i].idx = c;
+ types[i].offset = (long int) decode (x);
+ }
+
+ if (__glibc_unlikely (__fread_unlocked (zone_names, 1, chars, f) != chars))
+ goto lose;
+
+ for (i = 0; i < num_leaps; ++i)
+ {
+ unsigned char x[8];
+ if (__builtin_expect (__fread_unlocked (x, 1, trans_width, f)
+ != trans_width, 0))
+ goto lose;
+ if (sizeof (time_t) == 4 || trans_width == 4)
+ leaps[i].transition = (time_t) decode (x);
+ else
+ leaps[i].transition = (time_t) decode64 (x);
+
+ if (__glibc_unlikely (__fread_unlocked (x, 1, 4, f) != 4))
+ goto lose;
+ leaps[i].change = (long int) decode (x);
+ }
+
+ for (i = 0; i < num_isstd; ++i)
+ {
+ int c = getc_unlocked (f);
+ if (__glibc_unlikely (c == EOF))
+ goto lose;
+ types[i].isstd = c != 0;
+ }
+ while (i < num_types)
+ types[i++].isstd = 0;
+
+ for (i = 0; i < num_isgmt; ++i)
+ {
+ int c = getc_unlocked (f);
+ if (__glibc_unlikely (c == EOF))
+ goto lose;
+ types[i].isgmt = c != 0;
+ }
+ while (i < num_types)
+ types[i++].isgmt = 0;
+
+ /* Read the POSIX TZ-style information if possible. */
+ if (sizeof (time_t) == 8 && tzspec != NULL)
+ {
+ /* Skip over the newline first. */
+ if (getc_unlocked (f) != '\n'
+ || (__fread_unlocked (tzspec, 1, tzspec_len - 1, f)
+ != tzspec_len - 1))
+ tzspec = NULL;
+ else
+ tzspec[tzspec_len - 1] = '\0';
+ }
+ else if (sizeof (time_t) == 4 && tzhead.tzh_version[0] != '\0')
+ {
+ /* Get the TZ string. */
+ if (__builtin_expect (__fread_unlocked ((void *) &tzhead,
+ sizeof (tzhead), 1, f) != 1, 0)
+ || (memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic))
+ != 0))
+ goto lose;
+
+ size_t num_transitions2 = (size_t) decode (tzhead.tzh_timecnt);
+ size_t num_types2 = (size_t) decode (tzhead.tzh_typecnt);
+ size_t chars2 = (size_t) decode (tzhead.tzh_charcnt);
+ size_t num_leaps2 = (size_t) decode (tzhead.tzh_leapcnt);
+ size_t num_isstd2 = (size_t) decode (tzhead.tzh_ttisstdcnt);
+ size_t num_isgmt2 = (size_t) decode (tzhead.tzh_ttisgmtcnt);
+
+ /* Position the stream before the second header. */
+ size_t to_skip = (num_transitions2 * (8 + 1)
+ + num_types2 * 6
+ + chars2
+ + num_leaps2 * 12
+ + num_isstd2
+ + num_isgmt2);
+ off_t off;
+ if (fseek (f, to_skip, SEEK_CUR) != 0
+ || (off = __ftello (f)) < 0
+ || st.st_size < off + 2)
+ goto lose;
+
+ tzspec_len = st.st_size - off - 1;
+ if (tzspec_len == 0)
+ goto lose;
+ char *tzstr = malloc (tzspec_len);
+ if (tzstr == NULL)
+ goto lose;
+ if (getc_unlocked (f) != '\n'
+ || (__fread_unlocked (tzstr, 1, tzspec_len - 1, f)
+ != tzspec_len - 1))
+ {
+ free (tzstr);
+ goto lose;
+ }
+ tzstr[tzspec_len - 1] = '\0';
+ tzspec = __tzstring (tzstr);
+ free (tzstr);
+ }
+
+ /* Don't use an empty TZ string. */
+ if (tzspec != NULL && tzspec[0] == '\0')
+ tzspec = NULL;
+
+ fclose (f);
+
+ /* First "register" all timezone names. */
+ for (i = 0; i < num_types; ++i)
+ (void) __tzstring (&zone_names[types[i].idx]);
+
+ /* Find the standard and daylight time offsets used by the rule file.
+ We choose the offsets in the types of each flavor that are
+ transitioned to earliest in time. */
+ __tzname[0] = NULL;
+ __tzname[1] = NULL;
+ for (i = num_transitions; i > 0; )
+ {
+ int type = type_idxs[--i];
+ int dst = types[type].isdst;
+
+ if (__tzname[dst] == NULL)
+ {
+ int idx = types[type].idx;
+
+ __tzname[dst] = __tzstring (&zone_names[idx]);
+
+ if (__tzname[1 - dst] != NULL)
+ break;
+ }
+ }
+ if (__tzname[0] == NULL)
+ {
+ /* This should only happen if there are no transition rules.
+ In this case there should be only one single type. */
+ assert (num_types == 1);
+ __tzname[0] = __tzstring (zone_names);
+ }
+ if (__tzname[1] == NULL)
+ __tzname[1] = __tzname[0];
+
+ if (num_transitions == 0)
+ /* Use the first rule (which should also be the only one). */
+ rule_stdoff = rule_dstoff = types[0].offset;
+ else
+ {
+ int stdoff_set = 0, dstoff_set = 0;
+ rule_stdoff = rule_dstoff = 0;
+ i = num_transitions - 1;
+ do
+ {
+ if (!stdoff_set && !types[type_idxs[i]].isdst)
+ {
+ stdoff_set = 1;
+ rule_stdoff = types[type_idxs[i]].offset;
+ }
+ else if (!dstoff_set && types[type_idxs[i]].isdst)
+ {
+ dstoff_set = 1;
+ rule_dstoff = types[type_idxs[i]].offset;
+ }
+ if (stdoff_set && dstoff_set)
+ break;
+ }
+ while (i-- > 0);
+
+ if (!dstoff_set)
+ rule_dstoff = rule_stdoff;
+ }
+
+ __daylight = rule_stdoff != rule_dstoff;
+ __timezone = -rule_stdoff;
+
+ done:
+ __use_tzfile = 1;
+ free (new);
+ return;
+
+ lose:
+ fclose (f);
+ ret_free_transitions:
+ free (new);
+ free ((void *) transitions);
+ transitions = NULL;
+}
+
+/* The user specified a hand-made timezone, but not its DST rules.
+ We will use the names and offsets from the user, and the rules
+ from the TZDEFRULES file. */
+
+void
+__tzfile_default (const char *std, const char *dst,
+ long int stdoff, long int dstoff)
+{
+ size_t stdlen = strlen (std) + 1;
+ size_t dstlen = strlen (dst) + 1;
+ size_t i;
+ int isdst;
+ char *cp;
+
+ __tzfile_read (TZDEFRULES, stdlen + dstlen, &cp);
+ if (!__use_tzfile)
+ return;
+
+ if (num_types < 2)
+ {
+ __use_tzfile = 0;
+ return;
+ }
+
+ /* Ignore the zone names read from the file and use the given ones
+ instead. */
+ __mempcpy (__mempcpy (cp, std, stdlen), dst, dstlen);
+ zone_names = cp;
+
+ /* Now there are only two zones, regardless of what the file contained. */
+ num_types = 2;
+
+ /* Now correct the transition times for the user-specified standard and
+ daylight offsets from GMT. */
+ isdst = 0;
+ for (i = 0; i < num_transitions; ++i)
+ {
+ struct ttinfo *trans_type = &types[type_idxs[i]];
+
+ /* We will use only types 0 (standard) and 1 (daylight).
+ Fix up this transition to point to whichever matches
+ the flavor of its original type. */
+ type_idxs[i] = trans_type->isdst;
+
+ if (trans_type->isgmt)
+ /* The transition time is in GMT. No correction to apply. */ ;
+ else if (isdst && !trans_type->isstd)
+ /* The type says this transition is in "local wall clock time", and
+ wall clock time as of the previous transition was DST. Correct
+ for the difference between the rule's DST offset and the user's
+ DST offset. */
+ transitions[i] += dstoff - rule_dstoff;
+ else
+ /* This transition is in "local wall clock time", and wall clock
+ time as of this iteration is non-DST. Correct for the
+ difference between the rule's standard offset and the user's
+ standard offset. */
+ transitions[i] += stdoff - rule_stdoff;
+
+ /* The DST state of "local wall clock time" for the next iteration is
+ as specified by this transition. */
+ isdst = trans_type->isdst;
+ }
+
+ /* Now that we adjusted the transitions to the requested offsets,
+ reset the rule_stdoff and rule_dstoff values appropriately. They
+ are used elsewhere. */
+ rule_stdoff = stdoff;
+ rule_dstoff = dstoff;
+
+ /* Reset types 0 and 1 to describe the user's settings. */
+ types[0].idx = 0;
+ types[0].offset = stdoff;
+ types[0].isdst = 0;
+ types[1].idx = stdlen;
+ types[1].offset = dstoff;
+ types[1].isdst = 1;
+
+ /* Reset the zone names to point to the user's names. */
+ __tzname[0] = (char *) std;
+ __tzname[1] = (char *) dst;
+
+ /* Set the timezone. */
+ __timezone = -types[0].offset;
+
+ /* Invalidate the tzfile attribute cache to force rereading
+ TZDEFRULES the next time it is used. */
+ tzfile_dev = 0;
+ tzfile_ino = 0;
+ tzfile_mtime = 0;
+}
+
+void
+__tzfile_compute (time_t timer, int use_localtime,
+ long int *leap_correct, int *leap_hit,
+ struct tm *tp)
+{
+ size_t i;
+
+ if (use_localtime)
+ {
+ __tzname[0] = NULL;
+ __tzname[1] = NULL;
+
+ if (__glibc_unlikely (num_transitions == 0 || timer < transitions[0]))
+ {
+ /* TIMER is before any transition (or there are no transitions).
+ Choose the first non-DST type
+ (or the first if they're all DST types). */
+ i = 0;
+ while (i < num_types && types[i].isdst)
+ {
+ if (__tzname[1] == NULL)
+ __tzname[1] = __tzstring (&zone_names[types[i].idx]);
+
+ ++i;
+ }
+
+ if (i == num_types)
+ i = 0;
+ __tzname[0] = __tzstring (&zone_names[types[i].idx]);
+ if (__tzname[1] == NULL)
+ {
+ size_t j = i;
+ while (j < num_types)
+ if (types[j].isdst)
+ {
+ __tzname[1] = __tzstring (&zone_names[types[j].idx]);
+ break;
+ }
+ else
+ ++j;
+ }
+ }
+ else if (__glibc_unlikely (timer >= transitions[num_transitions - 1]))
+ {
+ if (__glibc_unlikely (tzspec == NULL))
+ {
+ use_last:
+ i = num_transitions;
+ goto found;
+ }
+
+ /* Parse the POSIX TZ-style string. */
+ __tzset_parse_tz (tzspec);
+
+ /* Convert to broken down structure. If this fails do not
+ use the string. */
+ if (__glibc_unlikely (! __offtime (&timer, 0, tp)))
+ goto use_last;
+
+ /* Use the rules from the TZ string to compute the change. */
+ __tz_compute (timer, tp, 1);
+
+ /* If tzspec comes from posixrules loaded by __tzfile_default,
+ override the STD and DST zone names with the ones user
+ requested in TZ envvar. */
+ if (__glibc_unlikely (zone_names == (char *) &leaps[num_leaps]))
+ {
+ assert (num_types == 2);
+ __tzname[0] = __tzstring (zone_names);
+ __tzname[1] = __tzstring (&zone_names[strlen (zone_names) + 1]);
+ }
+
+ goto leap;
+ }
+ else
+ {
+ /* Find the first transition after TIMER, and
+ then pick the type of the transition before it. */
+ size_t lo = 0;
+ size_t hi = num_transitions - 1;
+ /* Assume that DST is changing twice a year and guess initial
+ search spot from it.
+ Half of a gregorian year has on average 365.2425 * 86400 / 2
+ = 15778476 seconds. */
+ i = (transitions[num_transitions - 1] - timer) / 15778476;
+ if (i < num_transitions)
+ {
+ i = num_transitions - 1 - i;
+ if (timer < transitions[i])
+ {
+ if (i < 10 || timer >= transitions[i - 10])
+ {
+ /* Linear search. */
+ while (timer < transitions[i - 1])
+ --i;
+ goto found;
+ }
+ hi = i - 10;
+ }
+ else
+ {
+ if (i + 10 >= num_transitions || timer < transitions[i + 10])
+ {
+ /* Linear search. */
+ while (timer >= transitions[i])
+ ++i;
+ goto found;
+ }
+ lo = i + 10;
+ }
+ }
+
+ /* Binary search. */
+ /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
+ while (lo + 1 < hi)
+ {
+ i = (lo + hi) / 2;
+ if (timer < transitions[i])
+ hi = i;
+ else
+ lo = i;
+ }
+ i = hi;
+
+ found:
+ /* assert (timer >= transitions[i - 1]
+ && (i == num_transitions || timer < transitions[i])); */
+ __tzname[types[type_idxs[i - 1]].isdst]
+ = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
+ size_t j = i;
+ while (j < num_transitions)
+ {
+ int type = type_idxs[j];
+ int dst = types[type].isdst;
+ int idx = types[type].idx;
+
+ if (__tzname[dst] == NULL)
+ {
+ __tzname[dst] = __tzstring (&zone_names[idx]);
+
+ if (__tzname[1 - dst] != NULL)
+ break;
+ }
+
+ ++j;
+ }
+
+ if (__glibc_unlikely (__tzname[0] == NULL))
+ __tzname[0] = __tzname[1];
+
+ i = type_idxs[i - 1];
+ }
+
+ struct ttinfo *info = &types[i];
+ __daylight = rule_stdoff != rule_dstoff;
+ __timezone = -rule_stdoff;
+
+ if (__tzname[0] == NULL)
+ {
+ /* This should only happen if there are no transition rules.
+ In this case there should be only one single type. */
+ assert (num_types == 1);
+ __tzname[0] = __tzstring (zone_names);
+ }
+ if (__tzname[1] == NULL)
+ /* There is no daylight saving time. */
+ __tzname[1] = __tzname[0];
+ tp->tm_isdst = info->isdst;
+ assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0);
+ tp->tm_zone = __tzname[tp->tm_isdst];
+ tp->tm_gmtoff = info->offset;
+ }
+
+ leap:
+ *leap_correct = 0L;
+ *leap_hit = 0;
+
+ /* Find the last leap second correction transition time before TIMER. */
+ i = num_leaps;
+ do
+ if (i-- == 0)
+ return;
+ while (timer < leaps[i].transition);
+
+ /* Apply its correction. */
+ *leap_correct = leaps[i].change;
+
+ if (timer == leaps[i].transition && /* Exactly at the transition time. */
+ ((i == 0 && leaps[i].change > 0) ||
+ leaps[i].change > leaps[i - 1].change))
+ {
+ *leap_hit = 1;
+ while (i > 0
+ && leaps[i].transition == leaps[i - 1].transition + 1
+ && leaps[i].change == leaps[i - 1].change + 1)
+ {
+ ++*leap_hit;
+ --i;
+ }
+ }
+}
diff --git a/REORG.TODO/time/tzset.c b/REORG.TODO/time/tzset.c
new file mode 100644
index 0000000000..8868e9aada
--- /dev/null
+++ b/REORG.TODO/time/tzset.c
@@ -0,0 +1,632 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <ctype.h>
+#include <errno.h>
+#include <libc-lock.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <timezone/tzfile.h>
+
+char *__tzname[2] = { (char *) "GMT", (char *) "GMT" };
+int __daylight = 0;
+long int __timezone = 0L;
+
+weak_alias (__tzname, tzname)
+weak_alias (__daylight, daylight)
+weak_alias (__timezone, timezone)
+
+/* This locks all the state variables in tzfile.c and this file. */
+__libc_lock_define_initialized (static, tzset_lock)
+
+/* This structure contains all the information about a
+ timezone given in the POSIX standard TZ envariable. */
+typedef struct
+ {
+ const char *name;
+
+ /* When to change. */
+ enum { J0, J1, M } type; /* Interpretation of: */
+ unsigned short int m, n, d; /* Month, week, day. */
+ int secs; /* Time of day. */
+
+ long int offset; /* Seconds east of GMT (west if < 0). */
+
+ /* We cache the computed time of change for a
+ given year so we don't have to recompute it. */
+ time_t change; /* When to change to this zone. */
+ int computed_for; /* Year above is computed for. */
+ } tz_rule;
+
+/* tz_rules[0] is standard, tz_rules[1] is daylight. */
+static tz_rule tz_rules[2];
+
+
+static void compute_change (tz_rule *rule, int year) __THROW internal_function;
+static void tzset_internal (int always);
+
+/* List of buffers containing time zone strings. */
+struct tzstring_l
+{
+ struct tzstring_l *next;
+ size_t len; /* strlen(data) - doesn't count terminating NUL! */
+ char data[0];
+};
+
+static struct tzstring_l *tzstring_list;
+
+/* Allocate a permanent home for the first LEN characters of S. It
+ will never be moved or deallocated, but may share space with other
+ strings. Don't modify the returned string. */
+static char *
+__tzstring_len (const char *s, size_t len)
+{
+ char *p;
+ struct tzstring_l *t, *u, *new;
+
+ /* Walk the list and look for a match. If this string is the same
+ as the end of an already-allocated string, it can share space. */
+ for (u = t = tzstring_list; t; u = t, t = t->next)
+ if (len <= t->len)
+ {
+ p = &t->data[t->len - len];
+ if (memcmp (s, p, len) == 0)
+ return p;
+ }
+
+ /* Not found; allocate a new buffer. */
+ new = malloc (sizeof (struct tzstring_l) + len + 1);
+ if (!new)
+ return NULL;
+
+ new->next = NULL;
+ new->len = len;
+ memcpy (new->data, s, len);
+ new->data[len] = '\0';
+
+ if (u)
+ u->next = new;
+ else
+ tzstring_list = new;
+
+ return new->data;
+}
+
+/* Allocate a permanent home for S. It will never be moved or
+ deallocated, but may share space with other strings. Don't modify
+ the returned string. */
+char *
+__tzstring (const char *s)
+{
+ return __tzstring_len (s, strlen (s));
+}
+
+static char *old_tz;
+
+static void
+internal_function
+update_vars (void)
+{
+ __daylight = tz_rules[0].offset != tz_rules[1].offset;
+ __timezone = -tz_rules[0].offset;
+ __tzname[0] = (char *) tz_rules[0].name;
+ __tzname[1] = (char *) tz_rules[1].name;
+}
+
+
+static unsigned int
+compute_offset (unsigned int ss, unsigned int mm, unsigned int hh)
+{
+ if (ss > 59)
+ ss = 59;
+ if (mm > 59)
+ mm = 59;
+ if (hh > 24)
+ hh = 24;
+ return ss + mm * 60 + hh * 60 * 60;
+}
+
+/* Parses the time zone name at *TZP, and writes a pointer to an
+ interned string to tz_rules[WHICHRULE].name. On success, advances
+ *TZP, and returns true. Returns false otherwise. */
+static bool
+parse_tzname (const char **tzp, int whichrule)
+{
+ const char *start = *tzp;
+ const char *p = start;
+ while (('a' <= *p && *p <= 'z')
+ || ('A' <= *p && *p <= 'Z'))
+ ++p;
+ size_t len = p - start;
+ if (len < 3)
+ {
+ p = *tzp;
+ if (__glibc_unlikely (*p++ != '<'))
+ return false;
+ start = p;
+ while (('a' <= *p && *p <= 'z')
+ || ('A' <= *p && *p <= 'Z')
+ || ('0' <= *p && *p <= '9')
+ || *p == '+' || *p == '-')
+ ++p;
+ len = p - start;
+ if (*p++ != '>' || len < 3)
+ return false;
+ }
+
+ const char *name = __tzstring_len (start, len);
+ if (name == NULL)
+ return false;
+ tz_rules[whichrule].name = name;
+
+ *tzp = p;
+ return true;
+}
+
+/* Parses the time zone offset at *TZP, and writes it to
+ tz_rules[WHICHRULE].offset. Returns true if the parse was
+ successful. */
+static bool
+parse_offset (const char **tzp, int whichrule)
+{
+ const char *tz = *tzp;
+ if (whichrule == 0
+ && (*tz == '\0' || (*tz != '+' && *tz != '-' && !isdigit (*tz))))
+ return false;
+
+ long sign;
+ if (*tz == '-' || *tz == '+')
+ sign = *tz++ == '-' ? 1L : -1L;
+ else
+ sign = -1L;
+ *tzp = tz;
+
+ unsigned short int hh;
+ unsigned short mm = 0;
+ unsigned short ss = 0;
+ int consumed = 0;
+ if (sscanf (tz, "%hu%n:%hu%n:%hu%n",
+ &hh, &consumed, &mm, &consumed, &ss, &consumed) > 0)
+ tz_rules[whichrule].offset = sign * compute_offset (ss, mm, hh);
+ else
+ /* Nothing could be parsed. */
+ if (whichrule == 0)
+ {
+ /* Standard time defaults to offset zero. */
+ tz_rules[0].offset = 0;
+ return false;
+ }
+ else
+ /* DST defaults to one hour later than standard time. */
+ tz_rules[1].offset = tz_rules[0].offset + (60 * 60);
+ *tzp = tz + consumed;
+ return true;
+}
+
+/* Parses the standard <-> DST rules at *TZP. Updates
+ tz_rule[WHICHRULE]. On success, advances *TZP and returns true.
+ Otherwise, returns false. */
+static bool
+parse_rule (const char **tzp, int whichrule)
+{
+ const char *tz = *tzp;
+ tz_rule *tzr = &tz_rules[whichrule];
+
+ /* Ignore comma to support string following the incorrect
+ specification in early POSIX.1 printings. */
+ tz += *tz == ',';
+
+ /* Get the date of the change. */
+ if (*tz == 'J' || isdigit (*tz))
+ {
+ char *end;
+ tzr->type = *tz == 'J' ? J1 : J0;
+ if (tzr->type == J1 && !isdigit (*++tz))
+ return false;
+ unsigned long int d = strtoul (tz, &end, 10);
+ if (end == tz || d > 365)
+ return false;
+ if (tzr->type == J1 && d == 0)
+ return false;
+ tzr->d = d;
+ tz = end;
+ }
+ else if (*tz == 'M')
+ {
+ tzr->type = M;
+ int consumed;
+ if (sscanf (tz, "M%hu.%hu.%hu%n",
+ &tzr->m, &tzr->n, &tzr->d, &consumed) != 3
+ || tzr->m < 1 || tzr->m > 12
+ || tzr->n < 1 || tzr->n > 5 || tzr->d > 6)
+ return false;
+ tz += consumed;
+ }
+ else if (*tz == '\0')
+ {
+ /* Daylight time rules in the U.S. are defined in the U.S. Code,
+ Title 15, Chapter 6, Subchapter IX - Standard Time. These
+ dates were established by Congress in the Energy Policy Act
+ of 2005 [Pub. L. no. 109-58, 119 Stat 594 (2005)].
+ Below is the equivalent of "M3.2.0,M11.1.0" [/2 not needed
+ since 2:00AM is the default]. */
+ tzr->type = M;
+ if (tzr == &tz_rules[0])
+ {
+ tzr->m = 3;
+ tzr->n = 2;
+ tzr->d = 0;
+ }
+ else
+ {
+ tzr->m = 11;
+ tzr->n = 1;
+ tzr->d = 0;
+ }
+ }
+ else
+ return false;
+
+ if (*tz != '\0' && *tz != '/' && *tz != ',')
+ return false;
+ else if (*tz == '/')
+ {
+ /* Get the time of day of the change. */
+ int negative;
+ ++tz;
+ if (*tz == '\0')
+ return false;
+ negative = *tz == '-';
+ tz += negative;
+ /* Default to 2:00 AM. */
+ unsigned short hh = 2;
+ unsigned short mm = 0;
+ unsigned short ss = 0;
+ int consumed = 0;
+ sscanf (tz, "%hu%n:%hu%n:%hu%n",
+ &hh, &consumed, &mm, &consumed, &ss, &consumed);;
+ tz += consumed;
+ tzr->secs = (negative ? -1 : 1) * ((hh * 60 * 60) + (mm * 60) + ss);
+ }
+ else
+ /* Default to 2:00 AM. */
+ tzr->secs = 2 * 60 * 60;
+
+ tzr->computed_for = -1;
+ *tzp = tz;
+ return true;
+}
+
+/* Parse the POSIX TZ-style string. */
+void
+__tzset_parse_tz (const char *tz)
+{
+ /* Clear out old state and reset to unnamed UTC. */
+ memset (tz_rules, '\0', sizeof tz_rules);
+ tz_rules[0].name = tz_rules[1].name = "";
+
+ /* Get the standard timezone name. */
+ if (parse_tzname (&tz, 0) && parse_offset (&tz, 0))
+ {
+ /* Get the DST timezone name (if any). */
+ if (*tz != '\0')
+ {
+ if (parse_tzname (&tz, 1))
+ {
+ parse_offset (&tz, 1);
+ if (*tz == '\0' || (tz[0] == ',' && tz[1] == '\0'))
+ {
+ /* There is no rule. See if there is a default rule
+ file. */
+ __tzfile_default (tz_rules[0].name, tz_rules[1].name,
+ tz_rules[0].offset, tz_rules[1].offset);
+ if (__use_tzfile)
+ {
+ free (old_tz);
+ old_tz = NULL;
+ return;
+ }
+ }
+ }
+ /* Figure out the standard <-> DST rules. */
+ if (parse_rule (&tz, 0))
+ parse_rule (&tz, 1);
+ }
+ else
+ {
+ /* There is no DST. */
+ tz_rules[1].name = tz_rules[0].name;
+ tz_rules[1].offset = tz_rules[0].offset;
+ }
+ }
+
+ update_vars ();
+}
+
+/* Interpret the TZ envariable. */
+static void
+tzset_internal (int always)
+{
+ static int is_initialized;
+ const char *tz;
+
+ if (is_initialized && !always)
+ return;
+ is_initialized = 1;
+
+ /* Examine the TZ environment variable. */
+ tz = getenv ("TZ");
+ if (tz && *tz == '\0')
+ /* User specified the empty string; use UTC explicitly. */
+ tz = "Universal";
+
+ /* A leading colon means "implementation defined syntax".
+ We ignore the colon and always use the same algorithm:
+ try a data file, and if none exists parse the 1003.1 syntax. */
+ if (tz && *tz == ':')
+ ++tz;
+
+ /* Check whether the value changed since the last run. */
+ if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
+ /* No change, simply return. */
+ return;
+
+ if (tz == NULL)
+ /* No user specification; use the site-wide default. */
+ tz = TZDEFAULT;
+
+ tz_rules[0].name = NULL;
+ tz_rules[1].name = NULL;
+
+ /* Save the value of `tz'. */
+ free (old_tz);
+ old_tz = tz ? __strdup (tz) : NULL;
+
+ /* Try to read a data file. */
+ __tzfile_read (tz, 0, NULL);
+ if (__use_tzfile)
+ return;
+
+ /* No data file found. Default to UTC if nothing specified. */
+
+ if (tz == NULL || *tz == '\0'
+ || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
+ {
+ memset (tz_rules, '\0', sizeof tz_rules);
+ tz_rules[0].name = tz_rules[1].name = "UTC";
+ if (J0 != 0)
+ tz_rules[0].type = tz_rules[1].type = J0;
+ tz_rules[0].change = tz_rules[1].change = (time_t) -1;
+ update_vars ();
+ return;
+ }
+
+ __tzset_parse_tz (tz);
+}
+
+/* Figure out the exact time (as a time_t) in YEAR
+ when the change described by RULE will occur and
+ put it in RULE->change, saving YEAR in RULE->computed_for. */
+static void
+internal_function
+compute_change (tz_rule *rule, int year)
+{
+ time_t t;
+
+ if (year != -1 && rule->computed_for == year)
+ /* Operations on times in 2 BC will be slower. Oh well. */
+ return;
+
+ /* First set T to January 1st, 0:00:00 GMT in YEAR. */
+ if (year > 1970)
+ t = ((year - 1970) * 365
+ + /* Compute the number of leapdays between 1970 and YEAR
+ (exclusive). There is a leapday every 4th year ... */
+ + ((year - 1) / 4 - 1970 / 4)
+ /* ... except every 100th year ... */
+ - ((year - 1) / 100 - 1970 / 100)
+ /* ... but still every 400th year. */
+ + ((year - 1) / 400 - 1970 / 400)) * SECSPERDAY;
+ else
+ t = 0;
+
+ switch (rule->type)
+ {
+ case J1:
+ /* Jn - Julian day, 1 == January 1, 60 == March 1 even in leap years.
+ In non-leap years, or if the day number is 59 or less, just
+ add SECSPERDAY times the day number-1 to the time of
+ January 1, midnight, to get the day. */
+ t += (rule->d - 1) * SECSPERDAY;
+ if (rule->d >= 60 && __isleap (year))
+ t += SECSPERDAY;
+ break;
+
+ case J0:
+ /* n - Day of year.
+ Just add SECSPERDAY times the day number to the time of Jan 1st. */
+ t += rule->d * SECSPERDAY;
+ break;
+
+ case M:
+ /* Mm.n.d - Nth "Dth day" of month M. */
+ {
+ unsigned int i;
+ int d, m1, yy0, yy1, yy2, dow;
+ const unsigned short int *myday =
+ &__mon_yday[__isleap (year)][rule->m];
+
+ /* First add SECSPERDAY for each day in months before M. */
+ t += myday[-1] * SECSPERDAY;
+
+ /* Use Zeller's Congruence to get day-of-week of first day of month. */
+ m1 = (rule->m + 9) % 12 + 1;
+ yy0 = (rule->m <= 2) ? (year - 1) : year;
+ yy1 = yy0 / 100;
+ yy2 = yy0 % 100;
+ dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
+ if (dow < 0)
+ dow += 7;
+
+ /* DOW is the day-of-week of the first day of the month. Get the
+ day-of-month (zero-origin) of the first DOW day of the month. */
+ d = rule->d - dow;
+ if (d < 0)
+ d += 7;
+ for (i = 1; i < rule->n; ++i)
+ {
+ if (d + 7 >= (int) myday[0] - myday[-1])
+ break;
+ d += 7;
+ }
+
+ /* D is the day-of-month (zero-origin) of the day we want. */
+ t += d * SECSPERDAY;
+ }
+ break;
+ }
+
+ /* T is now the Epoch-relative time of 0:00:00 GMT on the day we want.
+ Just add the time of day and local offset from GMT, and we're done. */
+
+ rule->change = t - rule->offset + rule->secs;
+ rule->computed_for = year;
+}
+
+
+/* Figure out the correct timezone for TM and set `__tzname',
+ `__timezone', and `__daylight' accordingly. */
+void
+internal_function
+__tz_compute (time_t timer, struct tm *tm, int use_localtime)
+{
+ compute_change (&tz_rules[0], 1900 + tm->tm_year);
+ compute_change (&tz_rules[1], 1900 + tm->tm_year);
+
+ if (use_localtime)
+ {
+ int isdst;
+
+ /* We have to distinguish between northern and southern
+ hemisphere. For the latter the daylight saving time
+ ends in the next year. */
+ if (__builtin_expect (tz_rules[0].change
+ > tz_rules[1].change, 0))
+ isdst = (timer < tz_rules[1].change
+ || timer >= tz_rules[0].change);
+ else
+ isdst = (timer >= tz_rules[0].change
+ && timer < tz_rules[1].change);
+ tm->tm_isdst = isdst;
+ tm->tm_zone = __tzname[isdst];
+ tm->tm_gmtoff = tz_rules[isdst].offset;
+ }
+}
+
+/* Reinterpret the TZ environment variable and set `tzname'. */
+#undef tzset
+
+void
+__tzset (void)
+{
+ __libc_lock_lock (tzset_lock);
+
+ tzset_internal (1);
+
+ if (!__use_tzfile)
+ {
+ /* Set `tzname'. */
+ __tzname[0] = (char *) tz_rules[0].name;
+ __tzname[1] = (char *) tz_rules[1].name;
+ }
+
+ __libc_lock_unlock (tzset_lock);
+}
+weak_alias (__tzset, tzset)
+
+/* Return the `struct tm' representation of *TIMER in the local timezone.
+ Use local time if USE_LOCALTIME is nonzero, UTC otherwise. */
+struct tm *
+__tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
+{
+ long int leap_correction;
+ int leap_extra_secs;
+
+ if (timer == NULL)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ __libc_lock_lock (tzset_lock);
+
+ /* Update internal database according to current TZ setting.
+ POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
+ This is a good idea since this allows at least a bit more parallelism. */
+ tzset_internal (tp == &_tmbuf && use_localtime);
+
+ if (__use_tzfile)
+ __tzfile_compute (*timer, use_localtime, &leap_correction,
+ &leap_extra_secs, tp);
+ else
+ {
+ if (! __offtime (timer, 0, tp))
+ tp = NULL;
+ else
+ __tz_compute (*timer, tp, use_localtime);
+ leap_correction = 0L;
+ leap_extra_secs = 0;
+ }
+
+ __libc_lock_unlock (tzset_lock);
+
+ if (tp)
+ {
+ if (! use_localtime)
+ {
+ tp->tm_isdst = 0;
+ tp->tm_zone = "GMT";
+ tp->tm_gmtoff = 0L;
+ }
+
+ if (__offtime (timer, tp->tm_gmtoff - leap_correction, tp))
+ tp->tm_sec += leap_extra_secs;
+ else
+ tp = NULL;
+ }
+
+ return tp;
+}
+
+
+libc_freeres_fn (free_mem)
+{
+ while (tzstring_list != NULL)
+ {
+ struct tzstring_l *old = tzstring_list;
+
+ tzstring_list = tzstring_list->next;
+ free (old);
+ }
+ free (old_tz);
+ old_tz = NULL;
+}
diff --git a/REORG.TODO/time/wcsftime.c b/REORG.TODO/time/wcsftime.c
new file mode 100644
index 0000000000..cbc4161cb5
--- /dev/null
+++ b/REORG.TODO/time/wcsftime.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <wchar.h>
+#include <locale/localeinfo.h>
+
+
+size_t
+wcsftime (wchar_t *s, size_t maxsize, const wchar_t *format,
+ const struct tm *tp)
+{
+ return __wcsftime_l (s, maxsize, format, tp, _NL_CURRENT_LOCALE);
+}
+libc_hidden_def (wcsftime)
diff --git a/REORG.TODO/time/wcsftime_l.c b/REORG.TODO/time/wcsftime_l.c
new file mode 100644
index 0000000000..32101064e3
--- /dev/null
+++ b/REORG.TODO/time/wcsftime_l.c
@@ -0,0 +1,25 @@
+/* Copyright (C) 2002-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <wchar.h>
+#include <wctype.h>
+
+#define USE_IN_EXTENDED_LOCALE_MODEL 1
+#define COMPILE_WIDE 1
+#include "strftime_l.c"
+
+weak_alias (__wcsftime_l, wcsftime_l)