bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
* new module 'c-nstrftime'
@ 2024-02-08  0:29 Bruno Haible
  0 siblings, 0 replies; only message in thread
From: Bruno Haible @ 2024-02-08  0:29 UTC (permalink / raw)
  To: bug-gnulib

[-- Attachment #1: Type: text/plain, Size: 1470 bytes --]

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  <bruno@clisp.org>

	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.


[-- Attachment #2: 0001-c-nstrftime-New-module.patch --]
[-- Type: text/x-patch, Size: 15674 bytes --]

From 2e665106444eb32b81e8e94df4b5d8e67723837f Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
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  <bruno@clisp.org>
+
+	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  <bruno@clisp.org>
 
 	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


[-- Attachment #3: 0002-c-nstrftime-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4973 bytes --]

From e9ae614c441e32027f5a0280f091ddc0c702a3ca Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
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  <bruno@clisp.org>
 
+	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


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2024-02-08  0:30 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-08  0:29 new module 'c-nstrftime' Bruno Haible

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).