summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2015-10-25 10:35:32 +0000
committerAndy Wingo <wingo@pobox.com>2015-10-25 10:36:09 +0000
commitf63093c80179f4a0d1ff7b00ccf7d813f43b37dd (patch)
treea28289862366c90859d40b58777881fb4a13b299
parent2adc01ba510e4b3aba1ec13800be055749f552f6 (diff)
downloadguile-f63093c80179f4a0d1ff7b00ccf7d813f43b37dd.tar.gz
Add strptime gnulib module.
* lib/Makefile.am: * lib/strcasecmp.c: * lib/strings.in.h: * lib/strncasecmp.c: * lib/strptime.c: * m4/gnulib-cache.m4: * m4/gnulib-comp.m4: * m4/strcase.m4: * m4/strings_h.m4: * m4/strptime.m4: Import strptime module from gnulib.
-rw-r--r--lib/Makefile.am51
-rw-r--r--lib/strcasecmp.c62
-rw-r--r--lib/strings.in.h122
-rw-r--r--lib/strncasecmp.c62
-rw-r--r--lib/strptime.c1143
-rw-r--r--m4/gnulib-cache.m43
-rw-r--r--m4/gnulib-comp.m426
-rw-r--r--m4/strcase.m445
-rw-r--r--m4/strings_h.m452
-rw-r--r--m4/strptime.m422
10 files changed, 1586 insertions, 2 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index efdd0d23b..e91ea9c0b 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -21,7 +21,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --local-dir=gnulib-local --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=lock --lgpl=3 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap c-strcase canonicalize-lgpl ceil clock-time close connect copysign dirfd duplocale environ extensions flock floor fpieee frexp fstat fsync full-read full-write func gendocs getaddrinfo getlogin getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isfinite isinf isnan ldexp lib-symbol-versions lib-symbol-visibility libunistring link listen localcharset locale log1p lstat maintainer-makefile malloc-gnu malloca mkdir mkstemp nl_langinfo nproc open pipe-posix pipe2 poll putenv readlink recv recvfrom regex rename rmdir select send sendto setenv setsockopt shutdown socket stat-time stdlib strftime striconveh string sys_stat time time_rz times trunc unistd verify vsnprintf warnings wchar
+# Reproduce by: gnulib-tool --import --dir=. --local-dir=gnulib-local --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=lock --lgpl=3 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap c-strcase canonicalize-lgpl ceil clock-time close connect copysign dirfd duplocale environ extensions flock floor fpieee frexp fstat fsync full-read full-write func gendocs getaddrinfo getlogin getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isfinite isinf isnan ldexp lib-symbol-versions lib-symbol-visibility libunistring link listen localcharset locale log1p lstat maintainer-makefile malloc-gnu malloca mkdir mkstemp nl_langinfo nproc open pipe-posix pipe2 poll putenv readlink recv recvfrom regex rename rmdir select send sendto setenv setsockopt shutdown socket stat-time stdlib strftime striconveh string strptime sys_stat time time_rz times trunc unistd verify vsnprintf warnings wchar
AUTOMAKE_OPTIONS = 1.9.6 gnits subdir-objects
@@ -2387,6 +2387,15 @@ EXTRA_DIST += stdlib.in.h
## end gnulib module stdlib
+## begin gnulib module strcase
+
+
+EXTRA_DIST += strcasecmp.c strncasecmp.c
+
+EXTRA_libgnu_la_SOURCES += strcasecmp.c strncasecmp.c
+
+## end gnulib module strcase
+
## begin gnulib module strdup-posix
@@ -2522,6 +2531,46 @@ EXTRA_DIST += string.in.h
## end gnulib module string
+## begin gnulib module strings
+
+BUILT_SOURCES += strings.h
+
+# We need the following in order to create <strings.h> when the system
+# doesn't have one that works with the given compiler.
+strings.h: strings.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H)
+ $(AM_V_GEN)rm -f $@-t $@ && \
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ -e 's|@''HAVE_STRINGS_H''@|$(HAVE_STRINGS_H)|g' \
+ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+ -e 's|@''NEXT_STRINGS_H''@|$(NEXT_STRINGS_H)|g' \
+ -e 's|@''GNULIB_FFS''@|$(GNULIB_FFS)|g' \
+ -e 's|@''HAVE_FFS''@|$(HAVE_FFS)|g' \
+ -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \
+ -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \
+ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ < $(srcdir)/strings.in.h; \
+ } > $@-t && \
+ mv $@-t $@
+MOSTLYCLEANFILES += strings.h strings.h-t
+
+EXTRA_DIST += strings.in.h
+
+## end gnulib module strings
+
+## begin gnulib module strptime
+
+
+EXTRA_DIST += strptime.c
+
+EXTRA_libgnu_la_SOURCES += strptime.c
+
+## end gnulib module strptime
+
## begin gnulib module sys_file
BUILT_SOURCES += sys/file.h
diff --git a/lib/strcasecmp.c b/lib/strcasecmp.c
new file mode 100644
index 000000000..dc8bd9048
--- /dev/null
+++ b/lib/strcasecmp.c
@@ -0,0 +1,62 @@
+/* Case-insensitive string comparison function.
+ Copyright (C) 1998-1999, 2005-2007, 2009-2015 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#include <ctype.h>
+#include <limits.h>
+
+#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+
+/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
+ greater than zero if S1 is lexicographically less than, equal to or greater
+ than S2.
+ Note: This function does not work with multibyte strings! */
+
+int
+strcasecmp (const char *s1, const char *s2)
+{
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+
+ if (p1 == p2)
+ return 0;
+
+ do
+ {
+ c1 = TOLOWER (*p1);
+ c2 = TOLOWER (*p2);
+
+ if (c1 == '\0')
+ break;
+
+ ++p1;
+ ++p2;
+ }
+ while (c1 == c2);
+
+ if (UCHAR_MAX <= INT_MAX)
+ return c1 - c2;
+ else
+ /* On machines where 'char' and 'int' are types of the same size, the
+ difference of two 'unsigned char' values - including the sign bit -
+ doesn't fit in an 'int'. */
+ return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+}
diff --git a/lib/strings.in.h b/lib/strings.in.h
new file mode 100644
index 000000000..0dbb5109d
--- /dev/null
+++ b/lib/strings.in.h
@@ -0,0 +1,122 @@
+/* A substitute <strings.h>.
+
+ Copyright (C) 2007-2015 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _@GUARD_PREFIX@_STRINGS_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* Minix 3.1.8 has a bug: <sys/types.h> must be included before <strings.h>.
+ But avoid namespace pollution on glibc systems. */
+#if defined __minix && !defined __GLIBC__
+# include <sys/types.h>
+#endif
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_STRINGS_H@
+# @INCLUDE_NEXT@ @NEXT_STRINGS_H@
+#endif
+
+#ifndef _@GUARD_PREFIX@_STRINGS_H
+#define _@GUARD_PREFIX@_STRINGS_H
+
+#if ! @HAVE_DECL_STRNCASECMP@
+/* Get size_t. */
+# include <stddef.h>
+#endif
+
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
+
+/* The definition of _GL_ARG_NONNULL is copied here. */
+
+/* The definition of _GL_WARN_ON_USE is copied here. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+ /* Find the index of the least-significant set bit. */
+#if @GNULIB_FFS@
+# if !@HAVE_FFS@
+_GL_FUNCDECL_SYS (ffs, int, (int i));
+# endif
+_GL_CXXALIAS_SYS (ffs, int, (int i));
+_GL_CXXALIASWARN (ffs);
+#elif defined GNULIB_POSIXCHECK
+# undef ffs
+# if HAVE_RAW_DECL_FFS
+_GL_WARN_ON_USE (ffs, "ffs is not portable - use the ffs module");
+# endif
+#endif
+
+/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
+ greater than zero if S1 is lexicographically less than, equal to or greater
+ than S2.
+ Note: This function does not work in multibyte locales. */
+#if ! @HAVE_STRCASECMP@
+extern int strcasecmp (char const *s1, char const *s2)
+ _GL_ARG_NONNULL ((1, 2));
+#endif
+#if defined GNULIB_POSIXCHECK
+/* strcasecmp() does not work with multibyte strings:
+ POSIX says that it operates on "strings", and "string" in POSIX is defined
+ as a sequence of bytes, not of characters. */
+# undef strcasecmp
+# if HAVE_RAW_DECL_STRCASECMP
+_GL_WARN_ON_USE (strcasecmp, "strcasecmp cannot work correctly on character "
+ "strings in multibyte locales - "
+ "use mbscasecmp if you care about "
+ "internationalization, or use c_strcasecmp , "
+ "gnulib module c-strcase) if you want a locale "
+ "independent function");
+# endif
+#endif
+
+/* Compare no more than N bytes of strings S1 and S2, ignoring case,
+ returning less than, equal to or greater than zero if S1 is
+ lexicographically less than, equal to or greater than S2.
+ Note: This function cannot work correctly in multibyte locales. */
+#if ! @HAVE_DECL_STRNCASECMP@
+extern int strncasecmp (char const *s1, char const *s2, size_t n)
+ _GL_ARG_NONNULL ((1, 2));
+#endif
+#if defined GNULIB_POSIXCHECK
+/* strncasecmp() does not work with multibyte strings:
+ POSIX says that it operates on "strings", and "string" in POSIX is defined
+ as a sequence of bytes, not of characters. */
+# undef strncasecmp
+# if HAVE_RAW_DECL_STRNCASECMP
+_GL_WARN_ON_USE (strncasecmp, "strncasecmp cannot work correctly on character "
+ "strings in multibyte locales - "
+ "use mbsncasecmp or mbspcasecmp if you care about "
+ "internationalization, or use c_strncasecmp , "
+ "gnulib module c-strcase) if you want a locale "
+ "independent function");
+# endif
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _@GUARD_PREFIX@_STRING_H */
+#endif /* _@GUARD_PREFIX@_STRING_H */
diff --git a/lib/strncasecmp.c b/lib/strncasecmp.c
new file mode 100644
index 000000000..2d1aeba52
--- /dev/null
+++ b/lib/strncasecmp.c
@@ -0,0 +1,62 @@
+/* strncasecmp.c -- case insensitive string comparator
+ Copyright (C) 1998-1999, 2005-2007, 2009-2015 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#include <ctype.h>
+#include <limits.h>
+
+#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+
+/* Compare no more than N bytes of strings S1 and S2, ignoring case,
+ returning less than, equal to or greater than zero if S1 is
+ lexicographically less than, equal to or greater than S2.
+ Note: This function cannot work correctly in multibyte locales. */
+
+int
+strncasecmp (const char *s1, const char *s2, size_t n)
+{
+ register const unsigned char *p1 = (const unsigned char *) s1;
+ register const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+
+ if (p1 == p2 || n == 0)
+ return 0;
+
+ do
+ {
+ c1 = TOLOWER (*p1);
+ c2 = TOLOWER (*p2);
+
+ if (--n == 0 || c1 == '\0')
+ break;
+
+ ++p1;
+ ++p2;
+ }
+ while (c1 == c2);
+
+ if (UCHAR_MAX <= INT_MAX)
+ return c1 - c2;
+ else
+ /* On machines where 'char' and 'int' are types of the same size, the
+ difference of two 'unsigned char' values - including the sign bit -
+ doesn't fit in an 'int'. */
+ return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+}
diff --git a/lib/strptime.c b/lib/strptime.c
new file mode 100644
index 000000000..740bfa2c0
--- /dev/null
+++ b/lib/strptime.c
@@ -0,0 +1,1143 @@
+/* Copyright (C) 2002, 2004-2005, 2007, 2009-2015 Free Software Foundation,
+ Inc.
+ This file is part of the GNU C Library.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include <time.h>
+
+#include <assert.h>
+#include <ctype.h>
+#ifdef _LIBC
+# include <langinfo.h>
+#endif
+#include <limits.h>
+#include <string.h>
+#include <stdbool.h>
+
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+#endif
+
+#ifndef _LIBC
+enum ptime_locale_status { not, loc, raw };
+#endif
+
+
+
+#define match_char(ch1, ch2) if (ch1 != ch2) return NULL
+#if defined _LIBC && 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 (*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 (*decided != raw) \
+ { \
+ val = _nl_parse_alt_digit (&rp HELPER_LOCALE_ARG); \
+ if (val == -1 && *decided != loc) \
+ { \
+ *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, \
+ decided, era_cnt 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
+# define LOCALE_ARG , locale
+# define LOCALE_PARAM_PROTO , __locale_t locale
+# define LOCALE_PARAM_DECL __locale_t locale;
+# define HELPER_LOCALE_ARG , current
+# define ISSPACE(Ch) __isspace_l (Ch, locale)
+#else
+# define LOCALE_PARAM
+# define LOCALE_ARG
+# define LOCALE_PARAM_DECL
+# define LOCALE_PARAM_PROTO
+# 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 (rp, fmt, tm, decided, era_cnt LOCALE_PARAM)
+ const char *rp;
+ const char *fmt;
+ struct tm *tm;
+ enum ptime_locale_status *decided;
+ int era_cnt;
+ LOCALE_PARAM_DECL
+{
+#ifdef _LIBC
+ struct locale_data *const current = locale->__locales[LC_TIME];
+#endif
+
+ int cnt;
+ size_t val;
+ int have_I, is_pm;
+ int century, want_century;
+ int want_era;
+ int have_wday, want_xday;
+ int have_yday;
+ int have_mon, have_mday;
+ int have_uweek, have_wweek;
+ int week_no;
+#ifdef _NL_CURRENT
+ size_t num_eras;
+ struct era_entry *era = NULL;
+ const char *rp_backup;
+#endif
+
+ have_I = is_pm = 0;
+ century = -1;
+ want_century = 0;
+ want_era = 0;
+ week_no = 0;
+
+ have_wday = want_xday = have_yday = have_mon = have_mday = have_uweek = 0;
+ have_wweek = 0;
+
+ 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;
+#ifndef _NL_CURRENT
+ /* We need this for handling the 'E' modifier. */
+ start_over:
+#else
+ /* Make back up of current processing pointer. */
+ rp_backup = rp;
+#endif
+
+ switch (*fmt++)
+ {
+ case '%':
+ /* Match the '%' character itself. */
+ match_char ('%', *rp++);
+ break;
+ case 'a':
+ case 'A':
+ /* Match day of week. */
+ for (cnt = 0; cnt < 7; ++cnt)
+ {
+#ifdef _NL_CURRENT
+ if (*decided !=raw)
+ {
+ if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
+ {
+ if (*decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
+ weekday_name[cnt]))
+ *decided = loc;
+ break;
+ }
+ if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
+ {
+ if (*decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
+ ab_weekday_name[cnt]))
+ *decided = loc;
+ break;
+ }
+ }
+#endif
+ if (*decided != loc
+ && (match_string (weekday_name[cnt], rp)
+ || match_string (ab_weekday_name[cnt], rp)))
+ {
+ *decided = raw;
+ break;
+ }
+ }
+ if (cnt == 7)
+ /* Does not match a weekday name. */
+ return NULL;
+ tm->tm_wday = cnt;
+ have_wday = 1;
+ break;
+ case 'b':
+ case 'B':
+ case 'h':
+ /* Match month name. */
+ for (cnt = 0; cnt < 12; ++cnt)
+ {
+#ifdef _NL_CURRENT
+ if (*decided !=raw)
+ {
+ if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
+ {
+ if (*decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
+ month_name[cnt]))
+ *decided = loc;
+ break;
+ }
+ if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
+ {
+ if (*decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
+ ab_month_name[cnt]))
+ *decided = loc;
+ break;
+ }
+ }
+#endif
+ if (match_string (month_name[cnt], rp)
+ || match_string (ab_month_name[cnt], rp))
+ {
+ *decided = raw;
+ break;
+ }
+ }
+ if (cnt == 12)
+ /* Does not match a month name. */
+ return NULL;
+ tm->tm_mon = cnt;
+ want_xday = 1;
+ break;
+ case 'c':
+ /* Match locale's date and time format. */
+#ifdef _NL_CURRENT
+ if (*decided != raw)
+ {
+ if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
+ {
+ if (*decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (*decided == not &&
+ strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
+ *decided = loc;
+ want_xday = 1;
+ break;
+ }
+ *decided = raw;
+ }
+#endif
+ if (!recursive (HERE_D_T_FMT))
+ return NULL;
+ want_xday = 1;
+ break;
+ case 'C':
+ /* Match century number. */
+#ifdef _NL_CURRENT
+ match_century:
+#endif
+ get_number (0, 99, 2);
+ century = val;
+ want_xday = 1;
+ break;
+ case 'd':
+ case 'e':
+ /* Match day of month. */
+ get_number (1, 31, 2);
+ tm->tm_mday = val;
+ have_mday = 1;
+ want_xday = 1;
+ break;
+ case 'F':
+ if (!recursive ("%Y-%m-%d"))
+ return NULL;
+ want_xday = 1;
+ break;
+ case 'x':
+#ifdef _NL_CURRENT
+ if (*decided != raw)
+ {
+ if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
+ {
+ if (*decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (*decided == not
+ && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
+ *decided = loc;
+ want_xday = 1;
+ break;
+ }
+ *decided = raw;
+ }
+#endif
+ /* Fall through. */
+ case 'D':
+ /* Match standard day format. */
+ if (!recursive (HERE_D_FMT))
+ return NULL;
+ want_xday = 1;
+ break;
+ case 'k':
+ case 'H':
+ /* Match hour in 24-hour clock. */
+ get_number (0, 23, 2);
+ tm->tm_hour = val;
+ 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;
+ have_I = 1;
+ break;
+ case 'j':
+ /* Match day number of year. */
+ get_number (1, 366, 3);
+ tm->tm_yday = val - 1;
+ have_yday = 1;
+ break;
+ case 'm':
+ /* Match number of month. */
+ get_number (1, 12, 2);
+ tm->tm_mon = val - 1;
+ have_mon = 1;
+ 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 (*decided != raw)
+ {
+ if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
+ {
+ if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
+ *decided = loc;
+ break;
+ }
+ if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
+ {
+ if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
+ *decided = loc;
+ is_pm = 1;
+ break;
+ }
+ *decided = raw;
+ }
+#endif
+ if (!match_string (HERE_AM_STR, rp))
+ {
+ if (match_string (HERE_PM_STR, rp))
+ is_pm = 1;
+ else
+ return NULL;
+ }
+ break;
+ case 'r':
+#ifdef _NL_CURRENT
+ if (*decided != raw)
+ {
+ if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
+ {
+ if (*decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (*decided == not &&
+ strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
+ HERE_T_FMT_AMPM))
+ *decided = loc;
+ break;
+ }
+ *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 (*decided != raw)
+ {
+ if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
+ {
+ if (*decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
+ *decided = loc;
+ break;
+ }
+ *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;
+ 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);
+ week_no = val;
+ have_uweek = 1;
+ break;
+ case 'W':
+ get_number (0, 53, 2);
+ week_no = val;
+ 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;
+ have_wday = 1;
+ break;
+ case 'y':
+#ifdef _NL_CURRENT
+ match_year_in_century:
+#endif
+ /* 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. */
+ want_century = 1;
+ want_xday = 1;
+ break;
+ case 'Y':
+ /* Match year including century number. */
+ get_number (0, 9999, 4);
+ tm->tm_year = val - 1900;
+ want_century = 0;
+ want_xday = 1;
+ break;
+ case 'Z':
+ /* XXX How to handle this? */
+ break;
+ case 'z':
+ /* We recognize two formats: if two digits are given, these
+ specify hours. If fours digits are used, minutes are
+ also specified. */
+ {
+ bool neg _GL_UNUSED;
+ int n;
+
+ val = 0;
+ while (*rp == ' ')
+ ++rp;
+ if (*rp != '+' && *rp != '-')
+ return NULL;
+ neg = *rp++ == '-';
+ n = 0;
+ while (n < 4 && *rp >= '0' && *rp <= '9')
+ {
+ val = val * 10 + *rp++ - '0';
+ ++n;
+ }
+ if (n == 2)
+ val *= 100;
+ else if (n != 4)
+ /* Only two or four digits recognized. */
+ return NULL;
+ else
+ {
+ /* We have to convert the minutes into decimal. */
+ if (val % 100 >= 60)
+ return NULL;
+ val = (val / 100) * 100 + ((val % 100) * 50) / 30;
+ }
+ if (val > 1200)
+ return NULL;
+#if defined _LIBC || HAVE_TM_GMTOFF
+ tm->tm_gmtoff = (val * 3600) / 100;
+ if (neg)
+ tm->tm_gmtoff = -tm->tm_gmtoff;
+#endif
+ }
+ break;
+ case 'E':
+#ifdef _NL_CURRENT
+ switch (*fmt++)
+ {
+ case 'c':
+ /* Match locale's alternate date and time format. */
+ if (*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 (*decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (strcmp (fmt, HERE_D_T_FMT))
+ *decided = loc;
+ want_xday = 1;
+ break;
+ }
+ *decided = raw;
+ }
+ /* The C locale has no era information, so use the
+ normal representation. */
+ if (!recursive (HERE_D_T_FMT))
+ return NULL;
+ want_xday = 1;
+ break;
+ case 'C':
+ if (*decided != raw)
+ {
+ if (era_cnt >= 0)
+ {
+ era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
+ if (era != NULL && match_string (era->era_name, rp))
+ {
+ *decided = loc;
+ break;
+ }
+ else
+ return NULL;
+ }
+
+ num_eras = _NL_CURRENT_WORD (LC_TIME,
+ _NL_TIME_ERA_NUM_ENTRIES);
+ for (era_cnt = 0; era_cnt < (int) num_eras;
+ ++era_cnt, rp = rp_backup)
+ {
+ era = _nl_select_era_entry (era_cnt
+ HELPER_LOCALE_ARG);
+ if (era != NULL && match_string (era->era_name, rp))
+ {
+ *decided = loc;
+ break;
+ }
+ }
+ if (era_cnt != (int) num_eras)
+ break;
+
+ era_cnt = -1;
+ if (*decided == loc)
+ return NULL;
+
+ *decided = raw;
+ }
+ /* The C locale has no era information, so use the
+ normal representation. */
+ goto match_century;
+ case 'y':
+ if (*decided != raw)
+ {
+ get_number(0, 9999, 4);
+ tm->tm_year = val;
+ want_era = 1;
+ want_xday = 1;
+ want_century = 1;
+
+ if (era_cnt >= 0)
+ {
+ assert (*decided == loc);
+
+ era = _nl_select_era_entry (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 (era_cnt = 0; era_cnt < (int) num_eras; ++era_cnt)
+ {
+ era = _nl_select_era_entry (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))
+ {
+ *decided = loc;
+ break;
+ }
+ }
+ }
+ if (era_cnt != (int) num_eras)
+ break;
+
+ era_cnt = -1;
+ if (*decided == loc)
+ return NULL;
+
+ *decided = raw;
+ }
+
+ goto match_year_in_century;
+ case 'Y':
+ if (*decided != raw)
+ {
+ num_eras = _NL_CURRENT_WORD (LC_TIME,
+ _NL_TIME_ERA_NUM_ENTRIES);
+ for (era_cnt = 0; era_cnt < (int) num_eras;
+ ++era_cnt, rp = rp_backup)
+ {
+ era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
+ if (era != NULL && recursive (era->era_format))
+ break;
+ }
+ if (era_cnt == (int) num_eras)
+ {
+ era_cnt = -1;
+ if (*decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ *decided = loc;
+ era_cnt = -1;
+ break;
+ }
+
+ *decided = raw;
+ }
+ get_number (0, 9999, 4);
+ tm->tm_year = val - 1900;
+ want_century = 0;
+ want_xday = 1;
+ break;
+ case 'x':
+ if (*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 (*decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (strcmp (fmt, HERE_D_FMT))
+ *decided = loc;
+ break;
+ }
+ *decided = raw;
+ }
+ if (!recursive (HERE_D_FMT))
+ return NULL;
+ break;
+ case 'X':
+ if (*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 (*decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ if (strcmp (fmt, HERE_T_FMT))
+ *decided = loc;
+ break;
+ }
+ *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;
+ have_mday = 1;
+ 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;
+ 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;
+ have_I = 1;
+ break;
+ case 'm':
+ /* Match month using alternate numeric symbols. */
+ get_alt_number (1, 12, 2);
+ tm->tm_mon = val - 1;
+ have_mon = 1;
+ 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);
+ week_no = val;
+ have_uweek = 1;
+ break;
+ case 'W':
+ get_alt_number (0, 53, 2);
+ week_no = val;
+ 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;
+ 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;
+ want_xday = 1;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ default:
+ return NULL;
+ }
+ }
+
+ if (have_I && is_pm)
+ tm->tm_hour += 12;
+
+ if (century != -1)
+ {
+ if (want_century)
+ tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
+ else
+ /* Only the century, but not the year. Strange, but so be it. */
+ tm->tm_year = (century - 19) * 100;
+ }
+
+ if (era_cnt != -1)
+ {
+#ifdef _NL_CURRENT
+ era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
+ if (era == NULL)
+ return NULL;
+ if (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];
+#endif
+ }
+ else
+ if (want_era)
+ {
+ /* No era found but we have seen an E modifier. Rectify some
+ values. */
+ if (want_century && century == -1 && tm->tm_year < 69)
+ tm->tm_year += 100;
+ }
+
+ if (want_xday && !have_wday)
+ {
+ if ( !(have_mon && have_mday) && 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 (!have_mon)
+ tm->tm_mon = t_mon - 1;
+ if (!have_mday)
+ tm->tm_mday =
+ (tm->tm_yday
+ - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
+ }
+ day_of_the_week (tm);
+ }
+
+ if (want_xday && !have_yday)
+ day_of_the_year (tm);
+
+ if ((have_uweek || have_wweek) && have_wday)
+ {
+ int save_wday = tm->tm_wday;
+ int save_mday = tm->tm_mday;
+ int save_mon = tm->tm_mon;
+ int w_offset = have_uweek ? 0 : 1;
+
+ tm->tm_mday = 1;
+ tm->tm_mon = 0;
+ day_of_the_week (tm);
+ if (have_mday)
+ tm->tm_mday = save_mday;
+ if (have_mon)
+ tm->tm_mon = save_mon;
+
+ if (!have_yday)
+ tm->tm_yday = ((7 - (tm->tm_wday - w_offset)) % 7
+ + (week_no - 1) *7
+ + save_wday - w_offset);
+
+ if (!have_mday || !have_mon)
+ {
+ int t_mon = 0;
+ while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon]
+ <= tm->tm_yday)
+ t_mon++;
+ if (!have_mon)
+ tm->tm_mon = t_mon - 1;
+ if (!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 (buf, format, tm LOCALE_PARAM)
+ const char *restrict buf;
+ const char *restrict format;
+ struct tm *restrict tm;
+ LOCALE_PARAM_DECL
+{
+ enum ptime_locale_status decided;
+
+#ifdef _NL_CURRENT
+ decided = not;
+#else
+ decided = raw;
+#endif
+ return __strptime_internal (buf, format, tm, &decided, -1 LOCALE_ARG);
+}
+
+#ifdef _LIBC
+weak_alias (__strptime_l, strptime_l)
+#endif
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index b4eddfd2f..6485dc476 100644
--- a/m4/gnulib-cache.m4
+++ b/m4/gnulib-cache.m4
@@ -27,7 +27,7 @@
# Specification in the form of a command-line invocation:
-# gnulib-tool --import --dir=. --local-dir=gnulib-local --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=lock --lgpl=3 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap c-strcase canonicalize-lgpl ceil clock-time close connect copysign dirfd duplocale environ extensions flock floor fpieee frexp fstat fsync full-read full-write func gendocs getaddrinfo getlogin getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isfinite isinf isnan ldexp lib-symbol-versions lib-symbol-visibility libunistring link listen localcharset locale log1p lstat maintainer-makefile malloc-gnu malloca mkdir mkstemp nl_langinfo nproc open pipe-posix pipe2 poll putenv readlink recv recvfrom regex rename rmdir select send sendto setenv setsockopt shutdown socket stat-time stdlib strftime striconveh string sys_stat time time_rz times trunc unistd verify vsnprintf warnings wchar
+# gnulib-tool --import --dir=. --local-dir=gnulib-local --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=lock --lgpl=3 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap c-strcase canonicalize-lgpl ceil clock-time close connect copysign dirfd duplocale environ extensions flock floor fpieee frexp fstat fsync full-read full-write func gendocs getaddrinfo getlogin getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isfinite isinf isnan ldexp lib-symbol-versions lib-symbol-visibility libunistring link listen localcharset locale log1p lstat maintainer-makefile malloc-gnu malloca mkdir mkstemp nl_langinfo nproc open pipe-posix pipe2 poll putenv readlink recv recvfrom regex rename rmdir select send sendto setenv setsockopt shutdown socket stat-time stdlib strftime striconveh string strptime sys_stat time time_rz times trunc unistd verify vsnprintf warnings wchar
# Specification in the form of a few gnulib-tool.m4 macro invocations:
gl_LOCAL_DIR([gnulib-local])
@@ -116,6 +116,7 @@ gl_MODULES([
strftime
striconveh
string
+ strptime
sys_stat
time
time_rz
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index a52f18593..926d26386 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -211,11 +211,14 @@ AC_DEFUN([gl_EARLY],
# Code from module stdint:
# Code from module stdio:
# Code from module stdlib:
+ # Code from module strcase:
# Code from module strdup-posix:
# Code from module streq:
# Code from module strftime:
# Code from module striconveh:
# Code from module string:
+ # Code from module strings:
+ # Code from module strptime:
# Code from module sys_file:
# Code from module sys_select:
# Code from module sys_socket:
@@ -789,6 +792,15 @@ AC_SUBST([LTALLOCA])
gl_STDINT_H
gl_STDIO_H
gl_STDLIB_H
+ gl_STRCASE
+ if test $HAVE_STRCASECMP = 0; then
+ AC_LIBOBJ([strcasecmp])
+ gl_PREREQ_STRCASECMP
+ fi
+ if test $HAVE_STRNCASECMP = 0; then
+ AC_LIBOBJ([strncasecmp])
+ gl_PREREQ_STRNCASECMP
+ fi
gl_FUNC_STRDUP_POSIX
if test $ac_cv_func_strdup = no || test $REPLACE_STRDUP = 1; then
AC_LIBOBJ([strdup])
@@ -801,6 +813,13 @@ AC_SUBST([LTALLOCA])
gl_libdeps="$gl_libdeps $LIBICONV"
fi
gl_HEADER_STRING_H
+ gl_HEADER_STRINGS_H
+ gl_FUNC_STRPTIME
+ if test $HAVE_STRPTIME = 0; then
+ AC_LIBOBJ([strptime])
+ gl_PREREQ_STRPTIME
+ fi
+ gl_TIME_MODULE_INDICATOR([strptime])
gl_HEADER_SYS_FILE_H
AC_PROG_MKDIR_P
gl_HEADER_SYS_SELECT
@@ -1205,6 +1224,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/stdint.in.h
lib/stdio.in.h
lib/stdlib.in.h
+ lib/strcasecmp.c
lib/strdup.c
lib/streq.h
lib/strftime.c
@@ -1212,7 +1232,10 @@ AC_DEFUN([gl_FILE_LIST], [
lib/striconveh.c
lib/striconveh.h
lib/string.in.h
+ lib/strings.in.h
lib/stripslash.c
+ lib/strncasecmp.c
+ lib/strptime.c
lib/sys_file.in.h
lib/sys_select.in.h
lib/sys_socket.c
@@ -1400,9 +1423,12 @@ AC_DEFUN([gl_FILE_LIST], [
m4/stdint_h.m4
m4/stdio_h.m4
m4/stdlib_h.m4
+ m4/strcase.m4
m4/strdup.m4
m4/strftime.m4
m4/string_h.m4
+ m4/strings_h.m4
+ m4/strptime.m4
m4/sys_file_h.m4
m4/sys_select_h.m4
m4/sys_socket_h.m4
diff --git a/m4/strcase.m4 b/m4/strcase.m4
new file mode 100644
index 000000000..ece6722af
--- /dev/null
+++ b/m4/strcase.m4
@@ -0,0 +1,45 @@
+# strcase.m4 serial 11
+dnl Copyright (C) 2002, 2005-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_STRCASE],
+[
+ gl_FUNC_STRCASECMP
+ gl_FUNC_STRNCASECMP
+])
+
+AC_DEFUN([gl_FUNC_STRCASECMP],
+[
+ AC_REQUIRE([gl_HEADER_STRINGS_H_DEFAULTS])
+ AC_CHECK_FUNCS([strcasecmp])
+ if test $ac_cv_func_strcasecmp = no; then
+ HAVE_STRCASECMP=0
+ fi
+])
+
+AC_DEFUN([gl_FUNC_STRNCASECMP],
+[
+ AC_REQUIRE([gl_HEADER_STRINGS_H_DEFAULTS])
+ AC_CHECK_FUNCS([strncasecmp])
+ if test $ac_cv_func_strncasecmp = yes; then
+ HAVE_STRNCASECMP=1
+ else
+ HAVE_STRNCASECMP=0
+ fi
+ AC_CHECK_DECLS([strncasecmp])
+ if test $ac_cv_have_decl_strncasecmp = no; then
+ HAVE_DECL_STRNCASECMP=0
+ fi
+])
+
+# Prerequisites of lib/strcasecmp.c.
+AC_DEFUN([gl_PREREQ_STRCASECMP], [
+ :
+])
+
+# Prerequisites of lib/strncasecmp.c.
+AC_DEFUN([gl_PREREQ_STRNCASECMP], [
+ :
+])
diff --git a/m4/strings_h.m4 b/m4/strings_h.m4
new file mode 100644
index 000000000..28b754b6e
--- /dev/null
+++ b/m4/strings_h.m4
@@ -0,0 +1,52 @@
+# Configure a replacement for <strings.h>.
+# serial 6
+
+# Copyright (C) 2007, 2009-2015 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_HEADER_STRINGS_H],
+[
+ dnl Use AC_REQUIRE here, so that the default behavior below is expanded
+ dnl once only, before all statements that occur in other macros.
+ AC_REQUIRE([gl_HEADER_STRINGS_H_BODY])
+])
+
+AC_DEFUN([gl_HEADER_STRINGS_H_BODY],
+[
+ AC_REQUIRE([gl_HEADER_STRINGS_H_DEFAULTS])
+
+ gl_CHECK_NEXT_HEADERS([strings.h])
+ if test $ac_cv_header_strings_h = yes; then
+ HAVE_STRINGS_H=1
+ else
+ HAVE_STRINGS_H=0
+ fi
+ AC_SUBST([HAVE_STRINGS_H])
+
+ dnl Check for declarations of anything we want to poison if the
+ dnl corresponding gnulib module is not in use.
+ gl_WARN_ON_USE_PREPARE([[
+ /* Minix 3.1.8 has a bug: <sys/types.h> must be included before
+ <strings.h>. */
+ #include <sys/types.h>
+ #include <strings.h>
+ ]], [ffs strcasecmp strncasecmp])
+])
+
+AC_DEFUN([gl_STRINGS_MODULE_INDICATOR],
+[
+ dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+ AC_REQUIRE([gl_HEADER_STRINGS_H_DEFAULTS])
+ gl_MODULE_INDICATOR_SET_VARIABLE([$1])
+])
+
+AC_DEFUN([gl_HEADER_STRINGS_H_DEFAULTS],
+[
+ GNULIB_FFS=0; AC_SUBST([GNULIB_FFS])
+ dnl Assume proper GNU behavior unless another module says otherwise.
+ HAVE_FFS=1; AC_SUBST([HAVE_FFS])
+ HAVE_STRCASECMP=1; AC_SUBST([HAVE_STRCASECMP])
+ HAVE_DECL_STRNCASECMP=1; AC_SUBST([HAVE_DECL_STRNCASECMP])
+])
diff --git a/m4/strptime.m4 b/m4/strptime.m4
new file mode 100644
index 000000000..34f51a641
--- /dev/null
+++ b/m4/strptime.m4
@@ -0,0 +1,22 @@
+# strptime.m4 serial 7
+dnl Copyright (C) 2007, 2009-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_STRPTIME],
+[
+ AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
+ AC_REQUIRE([AC_C_RESTRICT])
+ AC_CHECK_FUNCS_ONCE([strptime])
+ if test $ac_cv_func_strptime != yes; then
+ HAVE_STRPTIME=0
+ fi
+])
+
+# Prerequisites of lib/strptime.c.
+AC_DEFUN([gl_PREREQ_STRPTIME],
+[
+ AC_REQUIRE([gl_TM_GMTOFF])
+ :
+])