Paul Eggert suggested a new module 'c-nstrftime', as the base for the migration away from function 'ctime'.
These two patches implement it. 2024-02-07 Bruno Haible <[email protected]> c-nstrftime: Add tests. * tests/test-c-nstrftime.c: New file, based on tests/test-nstrftime.c. * tests/test-c-nstrftime-1.sh: New file, based on tests/test-nstrftime-1.sh. * tests/test-c-nstrftime-2.sh: New file, based on tests/test-nstrftime-2.sh. * modules/c-nstrftime-tests: New file. c-nstrftime: New module. Suggested by Paul Eggert. * lib/strftime.h (c_nstrftime): New declaration. * lib/c-nstrftime.c: New file. * lib/strftime.c (FPRINTFTIME): Move fallback definition before its first use. (USE_C_LOCALE): Add fallback definition. If USE_C_LOCALE is set, include c-ctype.h instead of <ctype.h>. Conditionally include <locale.h>. (TOUPPER, TOLOWER): Define differently if USE_C_LOCALE is set. (c_locale_cache, c_locale): New definitions, copied from lib/c-strtod.c. (c_weekday_names, c_month_names): New variables, based on glibc/time/strftime_l.c. (__strftime_internal): Define a_wkday, aw_len, f_wkday, a_month, am_len, f_month, ampm, ap_len differently for USE_C_LOCALE. Avoid a 'goto underlying_strftime' if USE_C_LOCALE && !HAVE_STRFTIME_L. If USE_C_LOCALE, use strftime_l() with the C locale object instead of strftime(). * m4/c-nstrftime.m4: New file, based on m4/nstrftime.m4. * modules/c-nstrftime: New file, based on modules/nstrftime.
>From 2e665106444eb32b81e8e94df4b5d8e67723837f Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Thu, 8 Feb 2024 01:09:08 +0100 Subject: [PATCH 1/2] c-nstrftime: New module. Suggested by Paul Eggert. * lib/strftime.h (c_nstrftime): New declaration. * lib/c-nstrftime.c: New file. * lib/strftime.c (FPRINTFTIME): Move fallback definition before its first use. (USE_C_LOCALE): Add fallback definition. If USE_C_LOCALE is set, include c-ctype.h instead of <ctype.h>. Conditionally include <locale.h>. (TOUPPER, TOLOWER): Define differently if USE_C_LOCALE is set. (c_locale_cache, c_locale): New definitions, copied from lib/c-strtod.c. (c_weekday_names, c_month_names): New variables, based on glibc/time/strftime_l.c. (__strftime_internal): Define a_wkday, aw_len, f_wkday, a_month, am_len, f_month, ampm, ap_len differently for USE_C_LOCALE. Avoid a 'goto underlying_strftime' if USE_C_LOCALE && !HAVE_STRFTIME_L. Make the strftime fallback declaration ISO C 23 compliant. If USE_C_LOCALE, use strftime_l() with the C locale object instead of strftime(). * m4/c-nstrftime.m4: New file, based on m4/nstrftime.m4. * modules/c-nstrftime: New file, based on modules/nstrftime. --- ChangeLog | 23 +++++++++ lib/c-nstrftime.c | 20 ++++++++ lib/strftime.c | 121 ++++++++++++++++++++++++++++++++++++++++---- lib/strftime.h | 6 +++ m4/c-nstrftime.m4 | 21 ++++++++ modules/c-nstrftime | 37 ++++++++++++++ 6 files changed, 217 insertions(+), 11 deletions(-) create mode 100644 lib/c-nstrftime.c create mode 100644 m4/c-nstrftime.m4 create mode 100644 modules/c-nstrftime diff --git a/ChangeLog b/ChangeLog index ecbe0ea7b2..0d9b82b1e9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2024-02-07 Bruno Haible <[email protected]> + + c-nstrftime: New module. + Suggested by Paul Eggert. + * lib/strftime.h (c_nstrftime): New declaration. + * lib/c-nstrftime.c: New file. + * lib/strftime.c (FPRINTFTIME): Move fallback definition before its + first use. + (USE_C_LOCALE): Add fallback definition. + If USE_C_LOCALE is set, include c-ctype.h instead of <ctype.h>. + Conditionally include <locale.h>. + (TOUPPER, TOLOWER): Define differently if USE_C_LOCALE is set. + (c_locale_cache, c_locale): New definitions, copied from lib/c-strtod.c. + (c_weekday_names, c_month_names): New variables, based on + glibc/time/strftime_l.c. + (__strftime_internal): Define a_wkday, aw_len, f_wkday, a_month, am_len, + f_month, ampm, ap_len differently for USE_C_LOCALE. Avoid a + 'goto underlying_strftime' if USE_C_LOCALE && !HAVE_STRFTIME_L. If + USE_C_LOCALE, use strftime_l() with the C locale object instead of + strftime(). + * m4/c-nstrftime.m4: New file, based on m4/nstrftime.m4. + * modules/c-nstrftime: New file, based on modules/nstrftime. + 2024-02-07 Bruno Haible <[email protected]> nstrftime: Add tests of all directives, also in non-trivial locales. diff --git a/lib/c-nstrftime.c b/lib/c-nstrftime.c new file mode 100644 index 0000000000..cee7437e10 --- /dev/null +++ b/lib/c-nstrftime.c @@ -0,0 +1,20 @@ +/* Generate time strings in the "C" locale. + + Copyright (C) 2024 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file 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 <https://www.gnu.org/licenses/>. */ + +#define USE_C_LOCALE 1 +#define my_strftime c_nstrftime +#include "strftime.c" diff --git a/lib/strftime.c b/lib/strftime.c index d81c7eddfa..f6714524bd 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -14,6 +14,14 @@ You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ +#ifndef FPRINTFTIME +# define FPRINTFTIME 0 +#endif + +#ifndef USE_C_LOCALE +# define USE_C_LOCALE 0 +#endif + #ifdef _LIBC # define USE_IN_EXTENDED_LOCALE_MODEL 1 # define HAVE_STRUCT_ERA_ENTRY 1 @@ -31,7 +39,11 @@ # include "time-internal.h" #endif -#include <ctype.h> +#if USE_C_LOCALE +# include "c-ctype.h" +#else +# include <ctype.h> +#endif #include <errno.h> #include <time.h> @@ -67,6 +79,10 @@ extern char *tzname[]; #include <stdlib.h> #include <string.h> +#if USE_C_LOCALE && HAVE_STRFTIME_L +# include <locale.h> +#endif + #include "attribute.h" #include <intprops.h> @@ -127,10 +143,6 @@ extern char *tzname[]; # define mktime(tp) __mktime64 (tp) #endif -#ifndef FPRINTFTIME -# define FPRINTFTIME 0 -#endif - #if FPRINTFTIME # define STREAM_OR_CHAR_T FILE # define STRFTIME_ARG(x) /* empty */ @@ -270,8 +282,13 @@ extern char *tzname[]; # 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) +# if USE_C_LOCALE +# define TOUPPER(Ch, L) c_toupper (Ch) +# define TOLOWER(Ch, L) c_tolower (Ch) +# else +# define TOUPPER(Ch, L) toupper (Ch) +# define TOLOWER(Ch, L) tolower (Ch) +# endif # endif #endif /* We don't use 'isdigit' here since the locale dependent @@ -333,6 +350,26 @@ memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM) #endif +#if USE_C_LOCALE && HAVE_STRFTIME_L + +/* Cache for the C locale object. + Marked volatile so that different threads see the same value + (avoids locking). */ +static volatile locale_t c_locale_cache; + +/* Return the C locale object, or (locale_t) 0 with errno set + if it cannot be created. */ +static locale_t +c_locale (void) +{ + if (!c_locale_cache) + c_locale_cache = newlocale (LC_ALL_MASK, "C", (locale_t) 0); + return c_locale_cache; +} + +#endif + + #if ! HAVE_TM_GMTOFF /* Yield the difference between *A and *B, measured in seconds, ignoring leap seconds. */ @@ -381,6 +418,21 @@ iso_week_days (int yday, int wday) } +#if !defined _NL_CURRENT && (USE_C_LOCALE && !HAVE_STRFTIME_L) +static CHAR_T const c_weekday_names[][sizeof "Wednesday"] = + { + L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"), + L_("Thursday"), L_("Friday"), L_("Saturday") + }; +static CHAR_T const c_month_names[][sizeof "September"] = + { + 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 + + /* When compiling this file, GNU applications can #define my_strftime to a symbol (typically nstrftime) to get an extended strftime with extra arguments TZ and NS. */ @@ -478,6 +530,24 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) # define am_len STRLEN (a_month) # define aam_len STRLEN (a_altmonth) # define ap_len STRLEN (ampm) +#elif USE_C_LOCALE && !HAVE_STRFTIME_L +/* The English abbreviated weekday names are just the first 3 characters of the + English full weekday names. */ +# define a_wkday \ + (tp->tm_wday < 0 || tp->tm_wday > 6 ? L_("?") : c_weekday_names[tp->tm_wday]) +# define aw_len 3 +# define f_wkday \ + (tp->tm_wday < 0 || tp->tm_wday > 6 ? L_("?") : c_weekday_names[tp->tm_wday]) +/* The English abbreviated month names are just the first 3 characters of the + English full month names. */ +# define a_month \ + (tp->tm_mon < 0 || tp->tm_mon > 11 ? L_("?") : c_month_names[tp->tm_mon]) +# define am_len 3 +# define f_month \ + (tp->tm_mon < 0 || tp->tm_mon > 11 ? L_("?") : c_month_names[tp->tm_mon]) +/* The English AM/PM strings happen to have the same length, namely 2. */ +# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11)) +# define ap_len 2 #endif #if HAVE_TZNAME char **tzname_vec = tzname; @@ -765,7 +835,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) to_uppcase = true; to_lowcase = false; } -#ifdef _NL_CURRENT +#if defined _NL_CURRENT || (USE_C_LOCALE && !HAVE_STRFTIME_L) cpy (aw_len, a_wkday); break; #else @@ -780,7 +850,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) to_uppcase = true; to_lowcase = false; } -#ifdef _NL_CURRENT +#if defined _NL_CURRENT || (USE_C_LOCALE && !HAVE_STRFTIME_L) cpy (STRLEN (f_wkday), f_wkday); break; #else @@ -802,6 +872,9 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) else cpy (am_len, a_month); break; +#elif USE_C_LOCALE && !HAVE_STRFTIME_L + cpy (am_len, a_month); + break; #else goto underlying_strftime; #endif @@ -820,6 +893,9 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) else cpy (STRLEN (f_month), f_month); break; +#elif USE_C_LOCALE && !HAVE_STRFTIME_L + cpy (STRLEN (f_month), f_month); + break; #else goto underlying_strftime; #endif @@ -834,6 +910,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) NLW(ERA_D_T_FMT))) != '\0'))) subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT)); +#elif USE_C_LOCALE && !HAVE_STRFTIME_L + subfmt = L_("%a %b %e %H:%M:%S %Y"); #else goto underlying_strftime; #endif @@ -854,7 +932,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) } break; -#if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) +#if !((defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) || (USE_C_LOCALE && !HAVE_STRFTIME_L)) underlying_strftime: { /* The relevant information is available only via the @@ -879,7 +957,15 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) *u++ = modifier; *u++ = format_char; *u = '\0'; + +# if USE_C_LOCALE /* implies HAVE_STRFTIME_L */ + locale_t locale = c_locale (); + if (!locale) + return 0; /* errno is set here */ + len = strftime_l (ubuf, sizeof ubuf, ufmt, tp, locale); +# else len = strftime (ubuf, sizeof ubuf, ufmt, tp); +# endif if (len != 0) cpy (len - 1, ubuf + 1); } @@ -902,6 +988,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) # endif break; } +#elif USE_C_LOCALE && !HAVE_STRFTIME_L #else goto underlying_strftime; #endif @@ -925,6 +1012,9 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) != L_('\0')))) subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT)); goto subformat; +#elif USE_C_LOCALE && !HAVE_STRFTIME_L + subfmt = L_("%m/%d/%y"); + goto subformat; #else goto underlying_strftime; #endif @@ -1000,6 +1090,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) break; } } +#elif USE_C_LOCALE && !HAVE_STRFTIME_L #else goto underlying_strftime; #endif @@ -1147,7 +1238,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) to_uppcase = false; to_lowcase = true; } -#ifdef _NL_CURRENT +#if defined _NL_CURRENT || (USE_C_LOCALE && !HAVE_STRFTIME_L) cpy (ap_len, ampm); break; #else @@ -1168,6 +1259,9 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) == L_('\0')) subfmt = L_("%I:%M:%S %p"); goto subformat; +#elif USE_C_LOCALE && !HAVE_STRFTIME_L + subfmt = L_("%I:%M:%S %p"); + goto subformat; #elif (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ /* macOS, FreeBSD strftime() may produce empty output for "%r". */ subfmt = L_("%I:%M:%S %p"); @@ -1225,6 +1319,9 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) != L_('\0')))) subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT)); goto subformat; +#elif USE_C_LOCALE && !HAVE_STRFTIME_L + subfmt = L_("%H:%M:%S"); + goto subformat; #else goto underlying_strftime; #endif @@ -1332,6 +1429,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) pad = yr_spec; goto subformat; } +#elif USE_C_LOCALE && !HAVE_STRFTIME_L #else goto underlying_strftime; #endif @@ -1355,6 +1453,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) DO_NUMBER (2, (era->offset + delta * era->absolute_direction)); } +#elif USE_C_LOCALE && !HAVE_STRFTIME_L #else goto underlying_strftime; #endif diff --git a/lib/strftime.h b/lib/strftime.h index 6e3dbf834c..8ce62cdb6d 100644 --- a/lib/strftime.h +++ b/lib/strftime.h @@ -78,6 +78,12 @@ size_t nstrftime (char *restrict __s, size_t __maxsize, char const *__format, struct tm const *__tp, timezone_t __tz, int __ns); +/* Like nstrftime, except that it uses the "C" locale instead of the + current locale. */ +size_t c_nstrftime (char *restrict __s, size_t __maxsize, + char const *__format, + struct tm const *__tp, timezone_t __tz, int __ns); + #ifdef __cplusplus } #endif diff --git a/m4/c-nstrftime.m4 b/m4/c-nstrftime.m4 new file mode 100644 index 0000000000..9c8268b557 --- /dev/null +++ b/m4/c-nstrftime.m4 @@ -0,0 +1,21 @@ +# c-nstrftime.m4 serial 1 +dnl Copyright (C) 1996-2024 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_C_GNU_STRFTIME], +[ + AC_REQUIRE([AC_C_RESTRICT]) + + # This defines (or not) HAVE_TZNAME and HAVE_STRUCT_TM_TM_ZONE. + AC_REQUIRE([AC_STRUCT_TIMEZONE]) + + AC_REQUIRE([gl_TM_GMTOFF]) + + dnl Test for strftime_l. It exists in + dnl glibc >= 2.3, musl libc, + dnl macOS >= 10.4, FreeBSD >= 9.0, NetBSD >= 8.0, OpenBSD >= 6.2, Minix >= 3.3, + dnl AIX >= 7.2, Solaris >= 11.4, Cygwin >= 2.6, Android API level >= 21. + gl_CHECK_FUNCS_ANDROID([strftime_l], [[#include <time.h>]]) +]) diff --git a/modules/c-nstrftime b/modules/c-nstrftime new file mode 100644 index 0000000000..8b2348c227 --- /dev/null +++ b/modules/c-nstrftime @@ -0,0 +1,37 @@ +Description: +c_nstrftime() function: convert date and time to string, with GNU extensions, in "C" locale. + +Files: +lib/strftime.h +lib/c-nstrftime.c +lib/strftime.c +m4/tm_gmtoff.m4 +m4/c-nstrftime.m4 + +Depends-on: +attribute +c-ctype +c99 +errno +extensions +intprops +libc-config +locale +stdbool +stdckdint +time_rz + +configure.ac: +gl_C_GNU_STRFTIME + +Makefile.am: +lib_SOURCES += c-nstrftime.c + +Include: +"strftime.h" + +License: +LGPL + +Maintainer: +Jim Meyering, glibc -- 2.34.1
>From e9ae614c441e32027f5a0280f091ddc0c702a3ca Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Thu, 8 Feb 2024 01:24:12 +0100 Subject: [PATCH 2/2] c-nstrftime: Add tests. * tests/test-c-nstrftime.c: New file, based on tests/test-nstrftime.c. * tests/test-c-nstrftime-1.sh: New file, based on tests/test-nstrftime-1.sh. * tests/test-c-nstrftime-2.sh: New file, based on tests/test-nstrftime-2.sh. * modules/c-nstrftime-tests: New file. --- ChangeLog | 8 ++++++ modules/c-nstrftime-tests | 26 +++++++++++++++++ tests/test-c-nstrftime-1.sh | 5 ++++ tests/test-c-nstrftime-2.sh | 23 +++++++++++++++ tests/test-c-nstrftime.c | 56 +++++++++++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+) create mode 100644 modules/c-nstrftime-tests create mode 100755 tests/test-c-nstrftime-1.sh create mode 100755 tests/test-c-nstrftime-2.sh create mode 100644 tests/test-c-nstrftime.c diff --git a/ChangeLog b/ChangeLog index 0d9b82b1e9..53f6cb1765 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2024-02-07 Bruno Haible <[email protected]> + c-nstrftime: Add tests. + * tests/test-c-nstrftime.c: New file, based on tests/test-nstrftime.c. + * tests/test-c-nstrftime-1.sh: New file, based on + tests/test-nstrftime-1.sh. + * tests/test-c-nstrftime-2.sh: New file, based on + tests/test-nstrftime-2.sh. + * modules/c-nstrftime-tests: New file. + c-nstrftime: New module. Suggested by Paul Eggert. * lib/strftime.h (c_nstrftime): New declaration. diff --git a/modules/c-nstrftime-tests b/modules/c-nstrftime-tests new file mode 100644 index 0000000000..fda810d09b --- /dev/null +++ b/modules/c-nstrftime-tests @@ -0,0 +1,26 @@ +Files: +tests/test-c-nstrftime-1.sh +tests/test-c-nstrftime-2.sh +tests/test-c-nstrftime.c +tests/test-nstrftime.h +tests/macros.h +m4/locale-fr.m4 +m4/codeset.m4 + +Depends-on: +atoll +c99 +intprops +strerror + +configure.ac: +gt_LOCALE_FR +gt_LOCALE_FR_UTF8 + +Makefile.am: +TESTS += test-c-nstrftime-1.sh test-c-nstrftime-2.sh +TESTS_ENVIRONMENT += \ + LOCALE_FR='@LOCALE_FR@' \ + LOCALE_FR_UTF8='@LOCALE_FR_UTF8@' +check_PROGRAMS += test-c-nstrftime +test_c_nstrftime_LDADD = $(LDADD) $(SETLOCALE_LIB) diff --git a/tests/test-c-nstrftime-1.sh b/tests/test-c-nstrftime-1.sh new file mode 100755 index 0000000000..34b70effd3 --- /dev/null +++ b/tests/test-c-nstrftime-1.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +LC_ALL=C ${CHECKER} ./test-c-nstrftime${EXEEXT} || exit 1 + +exit 0 diff --git a/tests/test-c-nstrftime-2.sh b/tests/test-c-nstrftime-2.sh new file mode 100755 index 0000000000..e2bf1fae60 --- /dev/null +++ b/tests/test-c-nstrftime-2.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +: "${LOCALE_FR=fr_FR}" +: "${LOCALE_FR_UTF8=fr_FR.UTF-8}" + +if test $LOCALE_FR = none && test $LOCALE_FR_UTF8 = none; then + if test -f /usr/bin/localedef; then + echo "Skipping test: no locale for testing is installed" + else + echo "Skipping test: no locale for testing is supported" + fi + exit 77 +fi + +if test $LOCALE_FR != none; then + LC_ALL=$LOCALE_FR ${CHECKER} ./test-c-nstrftime${EXEEXT} || exit 1 +fi + +if test $LOCALE_FR_UTF8 != none; then + LC_ALL=$LOCALE_FR_UTF8 ${CHECKER} ./test-c-nstrftime${EXEEXT} || exit 1 +fi + +exit 0 diff --git a/tests/test-c-nstrftime.c b/tests/test-c-nstrftime.c new file mode 100644 index 0000000000..46ab58c92b --- /dev/null +++ b/tests/test-c-nstrftime.c @@ -0,0 +1,56 @@ +/* Test that c_nstrftime works as required. + Copyright (C) 2011-2024 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +#include <config.h> + +/* Specification. */ +#include "strftime.h" + +#include <locale.h> + +#include "intprops.h" + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "macros.h" + +#define FUNC c_nstrftime +#include "test-nstrftime.h" + +int +main (void) +{ + /* Try to set the locale by implicitly looking at the LC_ALL environment + variable. + configure should already have checked that the locale is supported. */ + if (setlocale (LC_ALL, "") == NULL) + return 1; + + int fail = 0; + fail |= posixtm_test (); + fail |= tzalloc_test (); + fail |= quarter_test (); + fail |= errno_test (); + fail |= locales_test (english); + return fail; +} -- 2.34.1
