aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2011-01-30 15:34:18 -0800
committerPaul Eggert2011-01-30 15:34:18 -0800
commit16c3e636a68cf74386d3d4d582a3a189b84d700c (patch)
tree43ef51bef626bf3b4c4d578e8dce0ad9857e98df
parent4eec7f8b2b465c6fc2c09d37d4da2b540f607df0 (diff)
downloademacs-16c3e636a68cf74386d3d4d582a3a189b84d700c.tar.gz
emacs-16c3e636a68cf74386d3d4d582a3a189b84d700c.zip
strftime: import from gnulib
-rw-r--r--ChangeLog16
-rw-r--r--Makefile.in2
-rw-r--r--aclocal.m43
-rw-r--r--admin/ChangeLog5
-rw-r--r--admin/notes/copyright1
-rwxr-xr-xconfigure210
-rw-r--r--configure.in6
-rw-r--r--lib/Makefile.in38
-rw-r--r--lib/gnulib.mk29
-rw-r--r--lib/stdbool.in.h122
-rw-r--r--lib/strftime.c1468
-rw-r--r--lib/strftime.h34
-rw-r--r--m4/gl-comp.m412
-rw-r--r--m4/stdbool.m4103
-rw-r--r--m4/strftime.m430
-rw-r--r--m4/tm_gmtoff.m414
-rw-r--r--src/ChangeLog10
-rw-r--r--src/Makefile.in2
-rw-r--r--src/config.in16
-rw-r--r--src/deps.mk1
-rw-r--r--src/editfns.c12
-rw-r--r--src/strftime.c1444
22 files changed, 2043 insertions, 1535 deletions
diff --git a/ChangeLog b/ChangeLog
index 2878150f5cb..bded0a22921 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
12011-01-30 Paul Eggert <eggert@cs.ucla.edu> 12011-01-30 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 strftime: import from gnulib
4 * Makefile.in (GNULIB_MODULES): Add strftime.
5 * configure.in (AC_FUNC_STRFTIME, my_strftime): Remove; no longer
6 needed.
7 * aclocal.m4, configure, lib/Makefile.in, lib/gnulib.mk, m4/gl-comp.m4:
8 Regenerate.
9 * lib/strftime.c, lib/strftime.h, lib/stdbool.in.h: New files,
10 imported from gnulib.
11 * m4/strftime.m4, m4/stdbool.m4, m4/tm_gmtoff.m4: Likewise.
12 This incorporates many changes from gnulib, including simpler
13 handling of multibyte formats, porting to mingw32 and other
14 platforms, and support for higher-resolution time stamps.
15 Emacs does not yet use the higher-resolution interface.
16
172011-01-30 Paul Eggert <eggert@cs.ucla.edu>
18
3 gnulib: import mktime and move-if-change fixes from gnulib 19 gnulib: import mktime and move-if-change fixes from gnulib
4 20
5 * configure: Regenerate from the following. 21 * configure: Regenerate from the following.
diff --git a/Makefile.in b/Makefile.in
index 63fd8332797..e3d2849940c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -330,7 +330,7 @@ DOS_gnulib_comp.m4 = gl-comp.m4
330# Update modules from gnulib, for maintainers, who should have it in 330# Update modules from gnulib, for maintainers, who should have it in
331# $(gnulib_srcdir) (relative to $(srcdir) and should have build tools 331# $(gnulib_srcdir) (relative to $(srcdir) and should have build tools
332# as per $(gnulib_srcdir)/DEPENDENCIES. 332# as per $(gnulib_srcdir)/DEPENDENCIES.
333GNULIB_MODULES = dtoastr getopt-gnu mktime 333GNULIB_MODULES = dtoastr getopt-gnu mktime strftime
334GNULIB_TOOL_FLAGS = \ 334GNULIB_TOOL_FLAGS = \
335 --import --no-changelog --no-vc-files --makefile-name=gnulib.mk 335 --import --no-changelog --no-vc-files --makefile-name=gnulib.mk
336sync-from-gnulib: $(gnulib_srcdir) 336sync-from-gnulib: $(gnulib_srcdir)
diff --git a/aclocal.m4 b/aclocal.m4
index 8fca11b5414..62d57bb59fd 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -993,8 +993,11 @@ m4_include([m4/gnulib-common.m4])
993m4_include([m4/include_next.m4]) 993m4_include([m4/include_next.m4])
994m4_include([m4/mktime.m4]) 994m4_include([m4/mktime.m4])
995m4_include([m4/multiarch.m4]) 995m4_include([m4/multiarch.m4])
996m4_include([m4/stdbool.m4])
996m4_include([m4/stddef_h.m4]) 997m4_include([m4/stddef_h.m4])
998m4_include([m4/strftime.m4])
997m4_include([m4/time_h.m4]) 999m4_include([m4/time_h.m4])
998m4_include([m4/time_r.m4]) 1000m4_include([m4/time_r.m4])
1001m4_include([m4/tm_gmtoff.m4])
999m4_include([m4/unistd_h.m4]) 1002m4_include([m4/unistd_h.m4])
1000m4_include([m4/wchar_t.m4]) 1003m4_include([m4/wchar_t.m4])
diff --git a/admin/ChangeLog b/admin/ChangeLog
index 5ce38fdfbd5..04fcf732bd9 100644
--- a/admin/ChangeLog
+++ b/admin/ChangeLog
@@ -1,3 +1,8 @@
12011-01-30 Paul Eggert <eggert@cs.ucla.edu>
2
3 strftime: import from gnulib
4 * notes/copyright: strftime.c moved from src to lib.
5
12011-01-25 Glenn Morris <rgm@gnu.org> 62011-01-25 Glenn Morris <rgm@gnu.org>
2 7
3 * bzrmerge.el (bzrmerge-skip-regexp): New variable. 8 * bzrmerge.el (bzrmerge-skip-regexp): New variable.
diff --git a/admin/notes/copyright b/admin/notes/copyright
index df48d098f19..e4077caf77b 100644
--- a/admin/notes/copyright
+++ b/admin/notes/copyright
@@ -635,7 +635,6 @@ alone (may import them from Gnulib again). These are:
635 src/gmalloc.c 635 src/gmalloc.c
636 src/md5.c 636 src/md5.c
637 src/md5.h 637 src/md5.h
638 src/strftime.c
639 src/termcap.c 638 src/termcap.c
640 src/tparam.c 639 src/tparam.c
641 640
diff --git a/configure b/configure
index 0aa010d3c65..aea8d2d079f 100755
--- a/configure
+++ b/configure
@@ -682,6 +682,8 @@ NEXT_STDDEF_H
682STDDEF_H 682STDDEF_H
683HAVE_WCHAR_T 683HAVE_WCHAR_T
684REPLACE_NULL 684REPLACE_NULL
685HAVE__BOOL
686STDBOOL_H
685APPLE_UNIVERSAL_BUILD 687APPLE_UNIVERSAL_BUILD
686REPLACE_TIMEGM 688REPLACE_TIMEGM
687REPLACE_NANOSLEEP 689REPLACE_NANOSLEEP
@@ -2658,6 +2660,7 @@ as_fn_append ac_header_list " sys/param.h"
2658gl_getopt_required=GNU 2660gl_getopt_required=GNU
2659as_fn_append ac_header_list " getopt.h" 2661as_fn_append ac_header_list " getopt.h"
2660as_fn_append ac_func_list " alarm" 2662as_fn_append ac_func_list " alarm"
2663as_fn_append ac_func_list " tzset"
2661as_fn_append ac_header_list " sys/time.h" 2664as_fn_append ac_header_list " sys/time.h"
2662as_fn_append ac_func_list " localtime_r" 2665as_fn_append ac_func_list " localtime_r"
2663# Check that the precious variables saved in the cache have kept the same 2666# Check that the precious variables saved in the cache have kept the same
@@ -5827,7 +5830,9 @@ $as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
5827 # Code from module intprops: 5830 # Code from module intprops:
5828 # Code from module mktime: 5831 # Code from module mktime:
5829 # Code from module multiarch: 5832 # Code from module multiarch:
5833 # Code from module stdbool:
5830 # Code from module stddef: 5834 # Code from module stddef:
5835 # Code from module strftime:
5831 # Code from module time: 5836 # Code from module time:
5832 # Code from module time_r: 5837 # Code from module time_r:
5833 # Code from module unistd: 5838 # Code from module unistd:
@@ -14400,6 +14405,97 @@ _ACEOF
14400 ;; 14405 ;;
14401esac 14406esac
14402 14407
14408{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
14409$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
14410if ${ac_cv_header_stdbool_h+:} false; then :
14411 $as_echo_n "(cached) " >&6
14412else
14413 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
14414/* end confdefs.h. */
14415
14416 #include <stdbool.h>
14417 #ifndef bool
14418 "error: bool is not defined"
14419 #endif
14420 #ifndef false
14421 "error: false is not defined"
14422 #endif
14423 #if false
14424 "error: false is not 0"
14425 #endif
14426 #ifndef true
14427 "error: true is not defined"
14428 #endif
14429 #if true != 1
14430 "error: true is not 1"
14431 #endif
14432 #ifndef __bool_true_false_are_defined
14433 "error: __bool_true_false_are_defined is not defined"
14434 #endif
14435
14436 struct s { _Bool s: 1; _Bool t; } s;
14437
14438 char a[true == 1 ? 1 : -1];
14439 char b[false == 0 ? 1 : -1];
14440 char c[__bool_true_false_are_defined == 1 ? 1 : -1];
14441 char d[(bool) 0.5 == true ? 1 : -1];
14442 /* See body of main program for 'e'. */
14443 char f[(_Bool) 0.0 == false ? 1 : -1];
14444 char g[true];
14445 char h[sizeof (_Bool)];
14446 char i[sizeof s.t];
14447 enum { j = false, k = true, l = false * true, m = true * 256 };
14448 /* The following fails for
14449 HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
14450 _Bool n[m];
14451 char o[sizeof n == m * sizeof n[0] ? 1 : -1];
14452 char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
14453 /* Catch a bug in an HP-UX C compiler. See
14454 http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
14455 http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
14456 */
14457 _Bool q = true;
14458 _Bool *pq = &q;
14459
14460int
14461main ()
14462{
14463
14464 bool e = &s;
14465 *pq |= q;
14466 *pq |= ! q;
14467 /* Refer to every declared value, to avoid compiler optimizations. */
14468 return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
14469 + !m + !n + !o + !p + !q + !pq);
14470
14471 ;
14472 return 0;
14473}
14474_ACEOF
14475if ac_fn_c_try_compile "$LINENO"; then :
14476 ac_cv_header_stdbool_h=yes
14477else
14478 ac_cv_header_stdbool_h=no
14479fi
14480rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
14481fi
14482{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
14483$as_echo "$ac_cv_header_stdbool_h" >&6; }
14484 ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
14485if test "x$ac_cv_type__Bool" = xyes; then :
14486
14487cat >>confdefs.h <<_ACEOF
14488#define HAVE__BOOL 1
14489_ACEOF
14490
14491
14492fi
14493
14494 if test $ac_cv_header_stdbool_h = yes; then
14495
14496$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
14497
14498 fi
14403 14499
14404 REPLACE_NULL=0; 14500 REPLACE_NULL=0;
14405 HAVE_WCHAR_T=1; 14501 HAVE_WCHAR_T=1;
@@ -14438,6 +14534,18 @@ $as_echo "#define HAVE_WCHAR_T 1" >>confdefs.h
14438 14534
14439 fi 14535 fi
14440 14536
14537
14538 ac_fn_c_check_member "$LINENO" "struct tm" "tm_gmtoff" "ac_cv_member_struct_tm_tm_gmtoff" "#include <time.h>
14539"
14540if test "x$ac_cv_member_struct_tm_tm_gmtoff" = xyes; then :
14541
14542$as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h
14543
14544fi
14545
14546
14547
14548
14441{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5 14549{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
14442$as_echo_n "checking for C/C++ restrict keyword... " >&6; } 14550$as_echo_n "checking for C/C++ restrict keyword... " >&6; }
14443if ${ac_cv_c_restrict+:} false; then : 14551if ${ac_cv_c_restrict+:} false; then :
@@ -14998,6 +15106,26 @@ fi
14998 15106
14999 # Code from module multiarch: 15107 # Code from module multiarch:
15000 15108
15109 # Code from module stdbool:
15110
15111
15112
15113 # Define two additional variables used in the Makefile substitution.
15114
15115 if test "$ac_cv_header_stdbool_h" = yes; then
15116 STDBOOL_H=''
15117 else
15118 STDBOOL_H='stdbool.h'
15119 fi
15120
15121
15122 if test "$ac_cv_type__Bool" = yes; then
15123 HAVE__BOOL=1
15124 else
15125 HAVE__BOOL=0
15126 fi
15127
15128
15001 # Code from module stddef: 15129 # Code from module stddef:
15002 15130
15003 15131
@@ -15093,6 +15221,32 @@ $as_echo "$gl_cv_next_stddef_h" >&6; }
15093 15221
15094 fi 15222 fi
15095 15223
15224 # Code from module strftime:
15225
15226
15227
15228
15229
15230
15231
15232
15233
15234
15235 gl_LIBOBJS="$gl_LIBOBJS strftime.$ac_objext"
15236
15237
15238 # This defines (or not) HAVE_TZNAME and HAVE_TM_ZONE.
15239
15240
15241
15242
15243
15244
15245
15246$as_echo "#define my_strftime nstrftime" >>confdefs.h
15247
15248
15249
15096 # Code from module time: 15250 # Code from module time:
15097 15251
15098 15252
@@ -15292,62 +15446,6 @@ $as_echo "$gl_cv_next_unistd_h" >&6; }
15292 15446
15293 15447
15294 15448
15295for ac_func in strftime
15296do :
15297 ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime"
15298if test "x$ac_cv_func_strftime" = xyes; then :
15299 cat >>confdefs.h <<_ACEOF
15300#define HAVE_STRFTIME 1
15301_ACEOF
15302
15303else
15304 # strftime is in -lintl on SCO UNIX.
15305{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5
15306$as_echo_n "checking for strftime in -lintl... " >&6; }
15307if ${ac_cv_lib_intl_strftime+:} false; then :
15308 $as_echo_n "(cached) " >&6
15309else
15310 ac_check_lib_save_LIBS=$LIBS
15311LIBS="-lintl $LIBS"
15312cat confdefs.h - <<_ACEOF >conftest.$ac_ext
15313/* end confdefs.h. */
15314
15315/* Override any GCC internal prototype to avoid an error.
15316 Use char because int might match the return type of a GCC
15317 builtin and then its argument prototype would still apply. */
15318#ifdef __cplusplus
15319extern "C"
15320#endif
15321char strftime ();
15322int
15323main ()
15324{
15325return strftime ();
15326 ;
15327 return 0;
15328}
15329_ACEOF
15330if ac_fn_c_try_link "$LINENO"; then :
15331 ac_cv_lib_intl_strftime=yes
15332else
15333 ac_cv_lib_intl_strftime=no
15334fi
15335rm -f core conftest.err conftest.$ac_objext \
15336 conftest$ac_exeext conftest.$ac_ext
15337LIBS=$ac_check_lib_save_LIBS
15338fi
15339{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5
15340$as_echo "$ac_cv_lib_intl_strftime" >&6; }
15341if test "x$ac_cv_lib_intl_strftime" = xyes; then :
15342 $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h
15343
15344LIBS="-lintl $LIBS"
15345fi
15346
15347fi
15348done
15349
15350
15351# UNIX98 PTYs. 15449# UNIX98 PTYs.
15352for ac_func in grantpt 15450for ac_func in grantpt
15353do : 15451do :
diff --git a/configure.in b/configure.in
index 91bb66d1187..627b76af59d 100644
--- a/configure.in
+++ b/configure.in
@@ -517,7 +517,7 @@ case "${canonical}" in
517 machine=hp800 opsys=hpux11 517 machine=hp800 opsys=hpux11
518 ## FIXME. Peter O'Gorman reports that dumping using unexelf.o doesn't 518 ## FIXME. Peter O'Gorman reports that dumping using unexelf.o doesn't
519 ## work either: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=6811 519 ## work either: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=6811
520 CANNOT_DUMP=yes 520 CANNOT_DUMP=yes
521 ;; 521 ;;
522 522
523 hppa*-*-linux-gnu* ) 523 hppa*-*-linux-gnu* )
@@ -2675,8 +2675,6 @@ gl_ASSERT_NO_GNULIB_POSIXCHECK
2675gl_ASSERT_NO_GNULIB_TESTS 2675gl_ASSERT_NO_GNULIB_TESTS
2676gl_INIT 2676gl_INIT
2677 2677
2678AC_FUNC_STRFTIME
2679
2680# UNIX98 PTYs. 2678# UNIX98 PTYs.
2681AC_CHECK_FUNCS(grantpt) 2679AC_CHECK_FUNCS(grantpt)
2682 2680
@@ -3528,8 +3526,6 @@ AH_BOTTOM([
3528#endif 3526#endif
3529#endif 3527#endif
3530 3528
3531#define my_strftime nstrftime /* for strftime.c */
3532
3533/* These default definitions are good for almost all machines. 3529/* These default definitions are good for almost all machines.
3534 The exceptions override them in m/MACHINE.h. */ 3530 The exceptions override them in m/MACHINE.h. */
3535 3531
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 2ac0278f7ec..7cd98417463 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -24,7 +24,7 @@
24# the same distribution terms as the rest of that program. 24# the same distribution terms as the rest of that program.
25# 25#
26# Generated by gnulib-tool. 26# Generated by gnulib-tool.
27# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files dtoastr getopt-gnu mktime 27# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files dtoastr getopt-gnu mktime strftime
28 28
29VPATH = @srcdir@ 29VPATH = @srcdir@
30pkgdatadir = $(datadir)/@PACKAGE@ 30pkgdatadir = $(datadir)/@PACKAGE@
@@ -54,10 +54,11 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \
54 $(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/gl-comp.m4 \ 54 $(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/gl-comp.m4 \
55 $(top_srcdir)/m4/gnulib-common.m4 \ 55 $(top_srcdir)/m4/gnulib-common.m4 \
56 $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/mktime.m4 \ 56 $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/mktime.m4 \
57 $(top_srcdir)/m4/multiarch.m4 $(top_srcdir)/m4/stddef_h.m4 \ 57 $(top_srcdir)/m4/multiarch.m4 $(top_srcdir)/m4/stdbool.m4 \
58 $(top_srcdir)/m4/stddef_h.m4 $(top_srcdir)/m4/strftime.m4 \
58 $(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/time_r.m4 \ 59 $(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/time_r.m4 \
59 $(top_srcdir)/m4/unistd_h.m4 $(top_srcdir)/m4/wchar_t.m4 \ 60 $(top_srcdir)/m4/tm_gmtoff.m4 $(top_srcdir)/m4/unistd_h.m4 \
60 $(top_srcdir)/configure.in 61 $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/configure.in
61am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 62am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
62 $(ACLOCAL_M4) 63 $(ACLOCAL_M4)
63mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs 64mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -232,6 +233,7 @@ HAVE_UNLINKAT = @HAVE_UNLINKAT@
232HAVE_USLEEP = @HAVE_USLEEP@ 233HAVE_USLEEP = @HAVE_USLEEP@
233HAVE_WCHAR_T = @HAVE_WCHAR_T@ 234HAVE_WCHAR_T = @HAVE_WCHAR_T@
234HAVE_XSERVER = @HAVE_XSERVER@ 235HAVE_XSERVER = @HAVE_XSERVER@
236HAVE__BOOL = @HAVE__BOOL@
235IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@ 237IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@
236IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@ 238IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@
237INCLUDE_NEXT = @INCLUDE_NEXT@ 239INCLUDE_NEXT = @INCLUDE_NEXT@
@@ -363,6 +365,7 @@ RSVG_LIBS = @RSVG_LIBS@
363SET_MAKE = @SET_MAKE@ 365SET_MAKE = @SET_MAKE@
364SHELL = @SHELL@ 366SHELL = @SHELL@
365START_FILES = @START_FILES@ 367START_FILES = @START_FILES@
368STDBOOL_H = @STDBOOL_H@
366STDDEF_H = @STDDEF_H@ 369STDDEF_H = @STDDEF_H@
367STRIP = @STRIP@ 370STRIP = @STRIP@
368SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ 371SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
@@ -467,23 +470,24 @@ x_default_search_path = @x_default_search_path@
467# statements but through direct file reference. Therefore this snippet must be 470# statements but through direct file reference. Therefore this snippet must be
468# present in all Makefile.am that need it. This is ensured by the applicability 471# present in all Makefile.am that need it. This is ensured by the applicability
469# 'all' defined above. 472# 'all' defined above.
470BUILT_SOURCES = arg-nonnull.h c++defs.h $(GETOPT_H) $(STDDEF_H) time.h \ 473BUILT_SOURCES = arg-nonnull.h c++defs.h $(GETOPT_H) $(STDBOOL_H) \
471 unistd.h warn-on-use.h 474 $(STDDEF_H) time.h unistd.h warn-on-use.h
472EXTRA_DIST = $(top_srcdir)/./arg-nonnull.h $(top_srcdir)/./c++defs.h \ 475EXTRA_DIST = $(top_srcdir)/./arg-nonnull.h $(top_srcdir)/./c++defs.h \
473 ftoastr.c ftoastr.h getopt.c getopt.in.h getopt1.c \ 476 ftoastr.c ftoastr.h getopt.c getopt.in.h getopt1.c \
474 getopt_int.h intprops.h mktime-internal.h mktime.c stddef.in.h \ 477 getopt_int.h intprops.h mktime-internal.h mktime.c \
475 time.in.h time_r.c unistd.in.h $(top_srcdir)/./warn-on-use.h 478 stdbool.in.h stddef.in.h strftime.c strftime.h time.in.h \
479 time_r.c unistd.in.h $(top_srcdir)/./warn-on-use.h
476MOSTLYCLEANFILES = core *.stackdump arg-nonnull.h arg-nonnull.h-t \ 480MOSTLYCLEANFILES = core *.stackdump arg-nonnull.h arg-nonnull.h-t \
477 c++defs.h c++defs.h-t getopt.h getopt.h-t stddef.h stddef.h-t \ 481 c++defs.h c++defs.h-t getopt.h getopt.h-t stdbool.h \
478 time.h time.h-t unistd.h unistd.h-t warn-on-use.h \ 482 stdbool.h-t stddef.h stddef.h-t time.h time.h-t unistd.h \
479 warn-on-use.h-t 483 unistd.h-t warn-on-use.h warn-on-use.h-t
480noinst_LIBRARIES = libgnu.a 484noinst_LIBRARIES = libgnu.a
481DEFAULT_INCLUDES = -I. -I../src -I$(top_srcdir)/src 485DEFAULT_INCLUDES = -I. -I../src -I$(top_srcdir)/src
482libgnu_a_SOURCES = dtoastr.c gettext.h 486libgnu_a_SOURCES = dtoastr.c gettext.h
483libgnu_a_LIBADD = $(gl_LIBOBJS) 487libgnu_a_LIBADD = $(gl_LIBOBJS)
484libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) 488libgnu_a_DEPENDENCIES = $(gl_LIBOBJS)
485EXTRA_libgnu_a_SOURCES = ftoastr.c getopt.c getopt1.c mktime.c \ 489EXTRA_libgnu_a_SOURCES = ftoastr.c getopt.c getopt1.c mktime.c \
486 time_r.c 490 strftime.c time_r.c
487ARG_NONNULL_H = arg-nonnull.h 491ARG_NONNULL_H = arg-nonnull.h
488CXXDEFS_H = c++defs.h 492CXXDEFS_H = c++defs.h
489WARN_ON_USE_H = warn-on-use.h 493WARN_ON_USE_H = warn-on-use.h
@@ -541,6 +545,7 @@ distclean-compile:
541@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ 545@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
542@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ 546@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
543@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktime.Po@am__quote@ 547@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktime.Po@am__quote@
548@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strftime.Po@am__quote@
544@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_r.Po@am__quote@ 549@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_r.Po@am__quote@
545 550
546.c.o: 551.c.o:
@@ -789,6 +794,15 @@ getopt.h: getopt.in.h $(ARG_NONNULL_H)
789 } > $@-t && \ 794 } > $@-t && \
790 mv -f $@-t $@ 795 mv -f $@-t $@
791 796
797# We need the following in order to create <stdbool.h> when the system
798# doesn't have one that works.
799stdbool.h: stdbool.in.h
800 $(AM_V_GEN)rm -f $@-t $@ && \
801 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
802 sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \
803 } > $@-t && \
804 mv $@-t $@
805
792# We need the following in order to create <stddef.h> when the system 806# We need the following in order to create <stddef.h> when the system
793# doesn't have one that works with the given compiler. 807# doesn't have one that works with the given compiler.
794stddef.h: stddef.in.h 808stddef.h: stddef.in.h
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index f1b5d236e21..ea6759e4532 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -9,7 +9,7 @@
9# the same distribution terms as the rest of that program. 9# the same distribution terms as the rest of that program.
10# 10#
11# Generated by gnulib-tool. 11# Generated by gnulib-tool.
12# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files dtoastr getopt-gnu mktime 12# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files dtoastr getopt-gnu mktime strftime
13 13
14 14
15MOSTLYCLEANFILES += core *.stackdump 15MOSTLYCLEANFILES += core *.stackdump
@@ -127,6 +127,24 @@ EXTRA_libgnu_a_SOURCES += mktime.c
127 127
128## end gnulib module mktime 128## end gnulib module mktime
129 129
130## begin gnulib module stdbool
131
132BUILT_SOURCES += $(STDBOOL_H)
133
134# We need the following in order to create <stdbool.h> when the system
135# doesn't have one that works.
136stdbool.h: stdbool.in.h
137 $(AM_V_GEN)rm -f $@-t $@ && \
138 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
139 sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \
140 } > $@-t && \
141 mv $@-t $@
142MOSTLYCLEANFILES += stdbool.h stdbool.h-t
143
144EXTRA_DIST += stdbool.in.h
145
146## end gnulib module stdbool
147
130## begin gnulib module stddef 148## begin gnulib module stddef
131 149
132BUILT_SOURCES += $(STDDEF_H) 150BUILT_SOURCES += $(STDDEF_H)
@@ -151,6 +169,15 @@ EXTRA_DIST += stddef.in.h
151 169
152## end gnulib module stddef 170## end gnulib module stddef
153 171
172## begin gnulib module strftime
173
174
175EXTRA_DIST += strftime.c strftime.h
176
177EXTRA_libgnu_a_SOURCES += strftime.c
178
179## end gnulib module strftime
180
154## begin gnulib module time 181## begin gnulib module time
155 182
156BUILT_SOURCES += time.h 183BUILT_SOURCES += time.h
diff --git a/lib/stdbool.in.h b/lib/stdbool.in.h
new file mode 100644
index 00000000000..b64dc75b20c
--- /dev/null
+++ b/lib/stdbool.in.h
@@ -0,0 +1,122 @@
1/* Copyright (C) 2001-2003, 2006-2011 Free Software Foundation, Inc.
2 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#ifndef _GL_STDBOOL_H
19#define _GL_STDBOOL_H
20
21/* ISO C 99 <stdbool.h> for platforms that lack it. */
22
23/* Usage suggestions:
24
25 Programs that use <stdbool.h> should be aware of some limitations
26 and standards compliance issues.
27
28 Standards compliance:
29
30 - <stdbool.h> must be #included before 'bool', 'false', 'true'
31 can be used.
32
33 - You cannot assume that sizeof (bool) == 1.
34
35 - Programs should not undefine the macros bool, true, and false,
36 as C99 lists that as an "obsolescent feature".
37
38 Limitations of this substitute, when used in a C89 environment:
39
40 - <stdbool.h> must be #included before the '_Bool' type can be used.
41
42 - You cannot assume that _Bool is a typedef; it might be a macro.
43
44 - Bit-fields of type 'bool' are not supported. Portable code
45 should use 'unsigned int foo : 1;' rather than 'bool foo : 1;'.
46
47 - In C99, casts and automatic conversions to '_Bool' or 'bool' are
48 performed in such a way that every nonzero value gets converted
49 to 'true', and zero gets converted to 'false'. This doesn't work
50 with this substitute. With this substitute, only the values 0 and 1
51 give the expected result when converted to _Bool' or 'bool'.
52
53 - C99 allows the use of (_Bool)0.0 in constant expressions, but
54 this substitute cannot always provide this property.
55
56 Also, it is suggested that programs use 'bool' rather than '_Bool';
57 this isn't required, but 'bool' is more common. */
58
59
60/* 7.16. Boolean type and values */
61
62/* BeOS <sys/socket.h> already #defines false 0, true 1. We use the same
63 definitions below, but temporarily we have to #undef them. */
64#if defined __BEOS__ && !defined __HAIKU__
65# include <OS.h> /* defines bool but not _Bool */
66# undef false
67# undef true
68#endif
69
70/* For the sake of symbolic names in gdb, we define true and false as
71 enum constants, not only as macros.
72 It is tempting to write
73 typedef enum { false = 0, true = 1 } _Bool;
74 so that gdb prints values of type 'bool' symbolically. But if we do
75 this, values of type '_Bool' may promote to 'int' or 'unsigned int'
76 (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int'
77 (see ISO C 99 6.3.1.1.(2)). So we add a negative value to the
78 enum; this ensures that '_Bool' promotes to 'int'. */
79#if defined __cplusplus || (defined __BEOS__ && !defined __HAIKU__)
80 /* A compiler known to have 'bool'. */
81 /* If the compiler already has both 'bool' and '_Bool', we can assume they
82 are the same types. */
83# if !@HAVE__BOOL@
84typedef bool _Bool;
85# endif
86#else
87# if !defined __GNUC__
88 /* If @HAVE__BOOL@:
89 Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when
90 the built-in _Bool type is used. See
91 http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
92 http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
93 http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html
94 Similar bugs are likely with other compilers as well; this file
95 wouldn't be used if <stdbool.h> was working.
96 So we override the _Bool type.
97 If !@HAVE__BOOL@:
98 Need to define _Bool ourselves. As 'signed char' or as an enum type?
99 Use of a typedef, with SunPRO C, leads to a stupid
100 "warning: _Bool is a keyword in ISO C99".
101 Use of an enum type, with IRIX cc, leads to a stupid
102 "warning(1185): enumerated type mixed with another type".
103 Even the existence of an enum type, without a typedef,
104 "Invalid enumerator. (badenum)" with HP-UX cc on Tru64.
105 The only benefit of the enum, debuggability, is not important
106 with these compilers. So use 'signed char' and no enum. */
107# define _Bool signed char
108# else
109 /* With this compiler, trust the _Bool type if the compiler has it. */
110# if !@HAVE__BOOL@
111typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool;
112# endif
113# endif
114#endif
115#define bool _Bool
116
117/* The other macros must be usable in preprocessor directives. */
118#define false 0
119#define true 1
120#define __bool_true_false_are_defined 1
121
122#endif /* _GL_STDBOOL_H */
diff --git a/lib/strftime.c b/lib/strftime.c
new file mode 100644
index 00000000000..0a02b507744
--- /dev/null
+++ b/lib/strftime.c
@@ -0,0 +1,1468 @@
1/* Copyright (C) 1991-2001, 2003-2007, 2009-2011 Free Software Foundation, Inc.
2
3 NOTE: The canonical source of this file is maintained with the GNU C Library.
4 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19#ifdef _LIBC
20# define HAVE_STRUCT_ERA_ENTRY 1
21# define HAVE_TM_GMTOFF 1
22# define HAVE_TM_ZONE 1
23# define HAVE_TZNAME 1
24# define HAVE_TZSET 1
25# include "../locale/localeinfo.h"
26#else
27# include <config.h>
28# if FPRINTFTIME
29# include "ignore-value.h"
30# include "fprintftime.h"
31# else
32# include "strftime.h"
33# endif
34#endif
35
36#include <ctype.h>
37#include <time.h>
38
39#if HAVE_TZNAME && !HAVE_DECL_TZNAME
40extern char *tzname[];
41#endif
42
43/* Do multibyte processing if multibytes are supported, unless
44 multibyte sequences are safe in formats. Multibyte sequences are
45 safe if they cannot contain byte sequences that look like format
46 conversion specifications. The multibyte encodings used by the
47 C library on the various platforms (UTF-8, GB2312, GBK, CP936,
48 GB18030, EUC-TW, BIG5, BIG5-HKSCS, CP950, EUC-JP, EUC-KR, CP949,
49 SHIFT_JIS, CP932, JOHAB) are safe for formats, because the byte '%'
50 cannot occur in a multibyte character except in the first byte.
51
52 The DEC-HANYU encoding used on OSF/1 is not safe for formats, but
53 this encoding has never been seen in real-life use, so we ignore
54 it. */
55#if !(defined __osf__ && 0)
56# define MULTIBYTE_IS_FORMAT_SAFE 1
57#endif
58#define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE)
59
60#if DO_MULTIBYTE
61# include <wchar.h>
62 static const mbstate_t mbstate_zero;
63#endif
64
65#include <limits.h>
66#include <stdbool.h>
67#include <stddef.h>
68#include <stdlib.h>
69#include <string.h>
70
71#ifdef COMPILE_WIDE
72# include <endian.h>
73# define CHAR_T wchar_t
74# define UCHAR_T unsigned int
75# define L_(Str) L##Str
76# define NLW(Sym) _NL_W##Sym
77
78# define MEMCPY(d, s, n) __wmemcpy (d, s, n)
79# define STRLEN(s) __wcslen (s)
80
81#else
82# define CHAR_T char
83# define UCHAR_T unsigned char
84# define L_(Str) Str
85# define NLW(Sym) Sym
86
87# define MEMCPY(d, s, n) memcpy (d, s, n)
88# define STRLEN(s) strlen (s)
89
90#endif
91
92/* Shift A right by B bits portably, by dividing A by 2**B and
93 truncating towards minus infinity. A and B should be free of side
94 effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
95 INT_BITS is the number of useful bits in an int. GNU code can
96 assume that INT_BITS is at least 32.
97
98 ISO C99 says that A >> B is implementation-defined if A < 0. Some
99 implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
100 right in the usual way when A < 0, so SHR falls back on division if
101 ordinary A >> B doesn't seem to be the usual signed shift. */
102#define SHR(a, b) \
103 (-1 >> 1 == -1 \
104 ? (a) >> (b) \
105 : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
106
107/* Bound on length of the string representing an integer type or expression T.
108 Subtract 1 for the sign bit if t is signed; log10 (2.0) < 146/485;
109 add 1 for integer division truncation; add 1 more for a minus sign
110 if needed. */
111#define INT_STRLEN_BOUND(t) \
112 ((sizeof (t) * CHAR_BIT - 1) * 146 / 485 + 2)
113
114#define TM_YEAR_BASE 1900
115
116#ifndef __isleap
117/* Nonzero if YEAR is a leap year (every 4 years,
118 except every 100th isn't, and every 400th is). */
119# define __isleap(year) \
120 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
121#endif
122
123
124#ifdef _LIBC
125# define tzname __tzname
126# define tzset __tzset
127#endif
128
129#if !HAVE_TM_GMTOFF
130/* Portable standalone applications should supply a "time.h" that
131 declares a POSIX-compliant localtime_r, for the benefit of older
132 implementations that lack localtime_r or have a nonstandard one.
133 See the gnulib time_r module for one way to implement this. */
134# undef __gmtime_r
135# undef __localtime_r
136# define __gmtime_r gmtime_r
137# define __localtime_r localtime_r
138#endif
139
140
141#ifndef FPRINTFTIME
142# define FPRINTFTIME 0
143#endif
144
145#if FPRINTFTIME
146# define STREAM_OR_CHAR_T FILE
147# define STRFTIME_ARG(x) /* empty */
148#else
149# define STREAM_OR_CHAR_T CHAR_T
150# define STRFTIME_ARG(x) x,
151#endif
152
153#if FPRINTFTIME
154# define memset_byte(P, Len, Byte) \
155 do { size_t _i; for (_i = 0; _i < Len; _i++) fputc (Byte, P); } while (0)
156# define memset_space(P, Len) memset_byte (P, Len, ' ')
157# define memset_zero(P, Len) memset_byte (P, Len, '0')
158#elif defined COMPILE_WIDE
159# define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
160# define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
161#else
162# define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
163# define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
164#endif
165
166#if FPRINTFTIME
167# define advance(P, N)
168#else
169# define advance(P, N) ((P) += (N))
170#endif
171
172#define add(n, f) \
173 do \
174 { \
175 int _n = (n); \
176 int _delta = width - _n; \
177 int _incr = _n + (_delta > 0 ? _delta : 0); \
178 if ((size_t) _incr >= maxsize - i) \
179 return 0; \
180 if (p) \
181 { \
182 if (digits == 0 && _delta > 0) \
183 { \
184 if (pad == L_('0')) \
185 memset_zero (p, _delta); \
186 else \
187 memset_space (p, _delta); \
188 } \
189 f; \
190 advance (p, _n); \
191 } \
192 i += _incr; \
193 } while (0)
194
195#if FPRINTFTIME
196# define add1(C) add (1, fputc (C, p))
197#else
198# define add1(C) add (1, *p = C)
199#endif
200
201#if FPRINTFTIME
202# define cpy(n, s) \
203 add ((n), \
204 do \
205 { \
206 if (to_lowcase) \
207 fwrite_lowcase (p, (s), _n); \
208 else if (to_uppcase) \
209 fwrite_uppcase (p, (s), _n); \
210 else \
211 { \
212 /* We are ignoring the value of fwrite here, in spite of the \
213 fact that technically, that may not be valid: the fwrite \
214 specification in POSIX 2008 defers to that of fputc, which \
215 is intended to be consistent with the one from ISO C, \
216 which permits failure due to ENOMEM *without* setting the \
217 stream's error indicator. */ \
218 ignore_value (fwrite ((s), _n, 1, p)); \
219 } \
220 } \
221 while (0) \
222 )
223#else
224# define cpy(n, s) \
225 add ((n), \
226 if (to_lowcase) \
227 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
228 else if (to_uppcase) \
229 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
230 else \
231 MEMCPY ((void *) p, (void const *) (s), _n))
232#endif
233
234#ifdef COMPILE_WIDE
235# ifndef USE_IN_EXTENDED_LOCALE_MODEL
236# undef __mbsrtowcs_l
237# define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
238# endif
239# define widen(os, ws, l) \
240 { \
241 mbstate_t __st; \
242 const char *__s = os; \
243 memset (&__st, '\0', sizeof (__st)); \
244 l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
245 ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \
246 (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
247 }
248#endif
249
250
251#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
252/* We use this code also for the extended locale handling where the
253 function gets as an additional argument the locale which has to be
254 used. To access the values we have to redefine the _NL_CURRENT
255 macro. */
256# define strftime __strftime_l
257# define wcsftime __wcsftime_l
258# undef _NL_CURRENT
259# define _NL_CURRENT(category, item) \
260 (current->values[_NL_ITEM_INDEX (item)].string)
261# define LOCALE_ARG , loc
262# define LOCALE_PARAM_PROTO , __locale_t loc
263# define HELPER_LOCALE_ARG , current
264#else
265# define LOCALE_PARAM_PROTO
266# define LOCALE_ARG
267# ifdef _LIBC
268# define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
269# else
270# define HELPER_LOCALE_ARG
271# endif
272#endif
273
274#ifdef COMPILE_WIDE
275# ifdef USE_IN_EXTENDED_LOCALE_MODEL
276# define TOUPPER(Ch, L) __towupper_l (Ch, L)
277# define TOLOWER(Ch, L) __towlower_l (Ch, L)
278# else
279# define TOUPPER(Ch, L) towupper (Ch)
280# define TOLOWER(Ch, L) towlower (Ch)
281# endif
282#else
283# ifdef USE_IN_EXTENDED_LOCALE_MODEL
284# define TOUPPER(Ch, L) __toupper_l (Ch, L)
285# define TOLOWER(Ch, L) __tolower_l (Ch, L)
286# else
287# define TOUPPER(Ch, L) toupper (Ch)
288# define TOLOWER(Ch, L) tolower (Ch)
289# endif
290#endif
291/* We don't use `isdigit' here since the locale dependent
292 interpretation is not what we want here. We only need to accept
293 the arabic digits in the ASCII range. One day there is perhaps a
294 more reliable way to accept other sets of digits. */
295#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
296
297#if FPRINTFTIME
298static void
299fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len)
300{
301 while (len-- > 0)
302 {
303 fputc (TOLOWER ((UCHAR_T) *src, loc), fp);
304 ++src;
305 }
306}
307
308static void
309fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len)
310{
311 while (len-- > 0)
312 {
313 fputc (TOUPPER ((UCHAR_T) *src, loc), fp);
314 ++src;
315 }
316}
317#else
318static CHAR_T *
319memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
320 size_t len LOCALE_PARAM_PROTO)
321{
322 while (len-- > 0)
323 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
324 return dest;
325}
326
327static CHAR_T *
328memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
329 size_t len LOCALE_PARAM_PROTO)
330{
331 while (len-- > 0)
332 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
333 return dest;
334}
335#endif
336
337
338#if ! HAVE_TM_GMTOFF
339/* Yield the difference between *A and *B,
340 measured in seconds, ignoring leap seconds. */
341# define tm_diff ftime_tm_diff
342static int
343tm_diff (const struct tm *a, const struct tm *b)
344{
345 /* Compute intervening leap days correctly even if year is negative.
346 Take care to avoid int overflow in leap day calculations,
347 but it's OK to assume that A and B are close to each other. */
348 int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
349 int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
350 int a100 = a4 / 25 - (a4 % 25 < 0);
351 int b100 = b4 / 25 - (b4 % 25 < 0);
352 int a400 = SHR (a100, 2);
353 int b400 = SHR (b100, 2);
354 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
355 int years = a->tm_year - b->tm_year;
356 int days = (365 * years + intervening_leap_days
357 + (a->tm_yday - b->tm_yday));
358 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
359 + (a->tm_min - b->tm_min))
360 + (a->tm_sec - b->tm_sec));
361}
362#endif /* ! HAVE_TM_GMTOFF */
363
364
365
366/* The number of days from the first day of the first ISO week of this
367 year to the year day YDAY with week day WDAY. ISO weeks start on
368 Monday; the first ISO week has the year's first Thursday. YDAY may
369 be as small as YDAY_MINIMUM. */
370#define ISO_WEEK_START_WDAY 1 /* Monday */
371#define ISO_WEEK1_WDAY 4 /* Thursday */
372#define YDAY_MINIMUM (-366)
373#ifdef __GNUC__
374__inline__
375#endif
376static int
377iso_week_days (int yday, int wday)
378{
379 /* Add enough to the first operand of % to make it nonnegative. */
380 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
381 return (yday
382 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
383 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
384}
385
386
387/* When compiling this file, GNU applications can #define my_strftime
388 to a symbol (typically nstrftime) to get an extended strftime with
389 extra arguments UT and NS. Emacs is a special case for now, but
390 this Emacs-specific code can be removed once Emacs's config.h
391 defines my_strftime. */
392#if defined emacs && !defined my_strftime
393# define my_strftime nstrftime
394#endif
395
396#if FPRINTFTIME
397# undef my_strftime
398# define my_strftime fprintftime
399#endif
400
401#ifdef my_strftime
402# define extra_args , ut, ns
403# define extra_args_spec , int ut, int ns
404#else
405# if defined COMPILE_WIDE
406# define my_strftime wcsftime
407# define nl_get_alt_digit _nl_get_walt_digit
408# else
409# define my_strftime strftime
410# define nl_get_alt_digit _nl_get_alt_digit
411# endif
412# define extra_args
413# define extra_args_spec
414/* We don't have this information in general. */
415# define ut 0
416# define ns 0
417#endif
418
419
420/* Just like my_strftime, below, but with one more parameter, UPCASE,
421 to indicate that the result should be converted to upper case. */
422static size_t
423strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
424 STRFTIME_ARG (size_t maxsize)
425 const CHAR_T *format,
426 const struct tm *tp extra_args_spec LOCALE_PARAM_PROTO)
427{
428#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
429 struct locale_data *const current = loc->__locales[LC_TIME];
430#endif
431#if FPRINTFTIME
432 size_t maxsize = (size_t) -1;
433#endif
434
435 int hour12 = tp->tm_hour;
436#ifdef _NL_CURRENT
437 /* We cannot make the following values variables since we must delay
438 the evaluation of these values until really needed since some
439 expressions might not be valid in every situation. The `struct tm'
440 might be generated by a strptime() call that initialized
441 only a few elements. Dereference the pointers only if the format
442 requires this. Then it is ok to fail if the pointers are invalid. */
443# define a_wkday \
444 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
445# define f_wkday \
446 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
447# define a_month \
448 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
449# define f_month \
450 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
451# define ampm \
452 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
453 ? NLW(PM_STR) : NLW(AM_STR)))
454
455# define aw_len STRLEN (a_wkday)
456# define am_len STRLEN (a_month)
457# define ap_len STRLEN (ampm)
458#endif
459 const char *zone;
460 size_t i = 0;
461 STREAM_OR_CHAR_T *p = s;
462 const CHAR_T *f;
463#if DO_MULTIBYTE && !defined COMPILE_WIDE
464 const char *format_end = NULL;
465#endif
466
467#if ! defined _LIBC && ! HAVE_RUN_TZSET_TEST
468 /* Solaris 2.5.x and 2.6 tzset sometimes modify the storage returned
469 by localtime. On such systems, we must either use the tzset and
470 localtime wrappers to work around the bug (which sets
471 HAVE_RUN_TZSET_TEST) or make a copy of the structure. */
472 struct tm copy = *tp;
473 tp = &copy;
474#endif
475
476 zone = NULL;
477#if HAVE_TM_ZONE
478 /* The POSIX test suite assumes that setting
479 the environment variable TZ to a new value before calling strftime()
480 will influence the result (the %Z format) even if the information in
481 TP is computed with a totally different time zone.
482 This is bogus: though POSIX allows bad behavior like this,
483 POSIX does not require it. Do the right thing instead. */
484 zone = (const char *) tp->tm_zone;
485#endif
486#if HAVE_TZNAME
487 if (ut)
488 {
489 if (! (zone && *zone))
490 zone = "GMT";
491 }
492 else
493 {
494 /* POSIX.1 requires that local time zone information be used as
495 though strftime called tzset. */
496# if HAVE_TZSET
497 tzset ();
498# endif
499 }
500#endif
501
502 if (hour12 > 12)
503 hour12 -= 12;
504 else
505 if (hour12 == 0)
506 hour12 = 12;
507
508 for (f = format; *f != '\0'; ++f)
509 {
510 int pad = 0; /* Padding for number ('-', '_', or 0). */
511 int modifier; /* Field modifier ('E', 'O', or 0). */
512 int digits = 0; /* Max digits for numeric format. */
513 int number_value; /* Numeric value to be printed. */
514 unsigned int u_number_value; /* (unsigned int) number_value. */
515 bool negative_number; /* The number is negative. */
516 bool always_output_a_sign; /* +/- should always be output. */
517 int tz_colon_mask; /* Bitmask of where ':' should appear. */
518 const CHAR_T *subfmt;
519 CHAR_T sign_char;
520 CHAR_T *bufp;
521 CHAR_T buf[1
522 + 2 /* for the two colons in a %::z or %:::z time zone */
523 + (sizeof (int) < sizeof (time_t)
524 ? INT_STRLEN_BOUND (time_t)
525 : INT_STRLEN_BOUND (int))];
526 int width = -1;
527 bool to_lowcase = false;
528 bool to_uppcase = upcase;
529 size_t colons;
530 bool change_case = false;
531 int format_char;
532
533#if DO_MULTIBYTE && !defined COMPILE_WIDE
534 switch (*f)
535 {
536 case L_('%'):
537 break;
538
539 case L_('\b'): case L_('\t'): case L_('\n'):
540 case L_('\v'): case L_('\f'): case L_('\r'):
541 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
542 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
543 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
544 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
545 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
546 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
547 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
548 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
549 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
550 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
551 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
552 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
553 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
554 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
555 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
556 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
557 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
558 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
559 case L_('~'):
560 /* The C Standard requires these 98 characters (plus '%') to
561 be in the basic execution character set. None of these
562 characters can start a multibyte sequence, so they need
563 not be analyzed further. */
564 add1 (*f);
565 continue;
566
567 default:
568 /* Copy this multibyte sequence until we reach its end, find
569 an error, or come back to the initial shift state. */
570 {
571 mbstate_t mbstate = mbstate_zero;
572 size_t len = 0;
573 size_t fsize;
574
575 if (! format_end)
576 format_end = f + strlen (f) + 1;
577 fsize = format_end - f;
578
579 do
580 {
581 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
582
583 if (bytes == 0)
584 break;
585
586 if (bytes == (size_t) -2)
587 {
588 len += strlen (f + len);
589 break;
590 }
591
592 if (bytes == (size_t) -1)
593 {
594 len++;
595 break;
596 }
597
598 len += bytes;
599 }
600 while (! mbsinit (&mbstate));
601
602 cpy (len, f);
603 f += len - 1;
604 continue;
605 }
606 }
607
608#else /* ! DO_MULTIBYTE */
609
610 /* Either multibyte encodings are not supported, they are
611 safe for formats, so any non-'%' byte can be copied through,
612 or this is the wide character version. */
613 if (*f != L_('%'))
614 {
615 add1 (*f);
616 continue;
617 }
618
619#endif /* ! DO_MULTIBYTE */
620
621 /* Check for flags that can modify a format. */
622 while (1)
623 {
624 switch (*++f)
625 {
626 /* This influences the number formats. */
627 case L_('_'):
628 case L_('-'):
629 case L_('0'):
630 pad = *f;
631 continue;
632
633 /* This changes textual output. */
634 case L_('^'):
635 to_uppcase = true;
636 continue;
637 case L_('#'):
638 change_case = true;
639 continue;
640
641 default:
642 break;
643 }
644 break;
645 }
646
647 /* As a GNU extension we allow to specify the field width. */
648 if (ISDIGIT (*f))
649 {
650 width = 0;
651 do
652 {
653 if (width > INT_MAX / 10
654 || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
655 /* Avoid overflow. */
656 width = INT_MAX;
657 else
658 {
659 width *= 10;
660 width += *f - L_('0');
661 }
662 ++f;
663 }
664 while (ISDIGIT (*f));
665 }
666
667 /* Check for modifiers. */
668 switch (*f)
669 {
670 case L_('E'):
671 case L_('O'):
672 modifier = *f++;
673 break;
674
675 default:
676 modifier = 0;
677 break;
678 }
679
680 /* Now do the specified format. */
681 format_char = *f;
682 switch (format_char)
683 {
684#define DO_NUMBER(d, v) \
685 digits = d; \
686 number_value = v; goto do_number
687#define DO_SIGNED_NUMBER(d, negative, v) \
688 digits = d; \
689 negative_number = negative; \
690 u_number_value = v; goto do_signed_number
691
692 /* The mask is not what you might think.
693 When the ordinal i'th bit is set, insert a colon
694 before the i'th digit of the time zone representation. */
695#define DO_TZ_OFFSET(d, negative, mask, v) \
696 digits = d; \
697 negative_number = negative; \
698 tz_colon_mask = mask; \
699 u_number_value = v; goto do_tz_offset
700#define DO_NUMBER_SPACEPAD(d, v) \
701 digits = d; \
702 number_value = v; goto do_number_spacepad
703
704 case L_('%'):
705 if (modifier != 0)
706 goto bad_format;
707 add1 (*f);
708 break;
709
710 case L_('a'):
711 if (modifier != 0)
712 goto bad_format;
713 if (change_case)
714 {
715 to_uppcase = true;
716 to_lowcase = false;
717 }
718#ifdef _NL_CURRENT
719 cpy (aw_len, a_wkday);
720 break;
721#else
722 goto underlying_strftime;
723#endif
724
725 case 'A':
726 if (modifier != 0)
727 goto bad_format;
728 if (change_case)
729 {
730 to_uppcase = true;
731 to_lowcase = false;
732 }
733#ifdef _NL_CURRENT
734 cpy (STRLEN (f_wkday), f_wkday);
735 break;
736#else
737 goto underlying_strftime;
738#endif
739
740 case L_('b'):
741 case L_('h'):
742 if (change_case)
743 {
744 to_uppcase = true;
745 to_lowcase = false;
746 }
747 if (modifier != 0)
748 goto bad_format;
749#ifdef _NL_CURRENT
750 cpy (am_len, a_month);
751 break;
752#else
753 goto underlying_strftime;
754#endif
755
756 case L_('B'):
757 if (modifier != 0)
758 goto bad_format;
759 if (change_case)
760 {
761 to_uppcase = true;
762 to_lowcase = false;
763 }
764#ifdef _NL_CURRENT
765 cpy (STRLEN (f_month), f_month);
766 break;
767#else
768 goto underlying_strftime;
769#endif
770
771 case L_('c'):
772 if (modifier == L_('O'))
773 goto bad_format;
774#ifdef _NL_CURRENT
775 if (! (modifier == 'E'
776 && (*(subfmt =
777 (const CHAR_T *) _NL_CURRENT (LC_TIME,
778 NLW(ERA_D_T_FMT)))
779 != '\0')))
780 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
781#else
782 goto underlying_strftime;
783#endif
784
785 subformat:
786 {
787 size_t len = strftime_case_ (to_uppcase,
788 NULL, STRFTIME_ARG ((size_t) -1)
789 subfmt,
790 tp extra_args LOCALE_ARG);
791 add (len, strftime_case_ (to_uppcase, p,
792 STRFTIME_ARG (maxsize - i)
793 subfmt,
794 tp extra_args LOCALE_ARG));
795 }
796 break;
797
798#if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
799 underlying_strftime:
800 {
801 /* The relevant information is available only via the
802 underlying strftime implementation, so use that. */
803 char ufmt[5];
804 char *u = ufmt;
805 char ubuf[1024]; /* enough for any single format in practice */
806 size_t len;
807 /* Make sure we're calling the actual underlying strftime.
808 In some cases, config.h contains something like
809 "#define strftime rpl_strftime". */
810# ifdef strftime
811# undef strftime
812 size_t strftime ();
813# endif
814
815 /* The space helps distinguish strftime failure from empty
816 output. */
817 *u++ = ' ';
818 *u++ = '%';
819 if (modifier != 0)
820 *u++ = modifier;
821 *u++ = format_char;
822 *u = '\0';
823 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
824 if (len != 0)
825 cpy (len - 1, ubuf + 1);
826 }
827 break;
828#endif
829
830 case L_('C'):
831 if (modifier == L_('O'))
832 goto bad_format;
833 if (modifier == L_('E'))
834 {
835#if HAVE_STRUCT_ERA_ENTRY
836 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
837 if (era)
838 {
839# ifdef COMPILE_WIDE
840 size_t len = __wcslen (era->era_wname);
841 cpy (len, era->era_wname);
842# else
843 size_t len = strlen (era->era_name);
844 cpy (len, era->era_name);
845# endif
846 break;
847 }
848#else
849 goto underlying_strftime;
850#endif
851 }
852
853 {
854 int century = tp->tm_year / 100 + TM_YEAR_BASE / 100;
855 century -= tp->tm_year % 100 < 0 && 0 < century;
856 DO_SIGNED_NUMBER (2, tp->tm_year < - TM_YEAR_BASE, century);
857 }
858
859 case L_('x'):
860 if (modifier == L_('O'))
861 goto bad_format;
862#ifdef _NL_CURRENT
863 if (! (modifier == L_('E')
864 && (*(subfmt =
865 (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
866 != L_('\0'))))
867 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
868 goto subformat;
869#else
870 goto underlying_strftime;
871#endif
872 case L_('D'):
873 if (modifier != 0)
874 goto bad_format;
875 subfmt = L_("%m/%d/%y");
876 goto subformat;
877
878 case L_('d'):
879 if (modifier == L_('E'))
880 goto bad_format;
881
882 DO_NUMBER (2, tp->tm_mday);
883
884 case L_('e'):
885 if (modifier == L_('E'))
886 goto bad_format;
887
888 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
889
890 /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
891 and then jump to one of these labels. */
892
893 do_tz_offset:
894 always_output_a_sign = true;
895 goto do_number_body;
896
897 do_number_spacepad:
898 /* Force `_' flag unless overridden by `0' or `-' flag. */
899 if (pad != L_('0') && pad != L_('-'))
900 pad = L_('_');
901
902 do_number:
903 /* Format NUMBER_VALUE according to the MODIFIER flag. */
904 negative_number = number_value < 0;
905 u_number_value = number_value;
906
907 do_signed_number:
908 always_output_a_sign = false;
909 tz_colon_mask = 0;
910
911 do_number_body:
912 /* Format U_NUMBER_VALUE according to the MODIFIER flag.
913 NEGATIVE_NUMBER is nonzero if the original number was
914 negative; in this case it was converted directly to
915 unsigned int (i.e., modulo (UINT_MAX + 1)) without
916 negating it. */
917 if (modifier == L_('O') && !negative_number)
918 {
919#ifdef _NL_CURRENT
920 /* Get the locale specific alternate representation of
921 the number. If none exist NULL is returned. */
922 const CHAR_T *cp = nl_get_alt_digit (u_number_value
923 HELPER_LOCALE_ARG);
924
925 if (cp != NULL)
926 {
927 size_t digitlen = STRLEN (cp);
928 if (digitlen != 0)
929 {
930 cpy (digitlen, cp);
931 break;
932 }
933 }
934#else
935 goto underlying_strftime;
936#endif
937 }
938
939 bufp = buf + sizeof (buf) / sizeof (buf[0]);
940
941 if (negative_number)
942 u_number_value = - u_number_value;
943
944 do
945 {
946 if (tz_colon_mask & 1)
947 *--bufp = ':';
948 tz_colon_mask >>= 1;
949 *--bufp = u_number_value % 10 + L_('0');
950 u_number_value /= 10;
951 }
952 while (u_number_value != 0 || tz_colon_mask != 0);
953
954 do_number_sign_and_padding:
955 if (digits < width)
956 digits = width;
957
958 sign_char = (negative_number ? L_('-')
959 : always_output_a_sign ? L_('+')
960 : 0);
961
962 if (pad == L_('-'))
963 {
964 if (sign_char)
965 add1 (sign_char);
966 }
967 else
968 {
969 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
970 - bufp) - !!sign_char;
971
972 if (padding > 0)
973 {
974 if (pad == L_('_'))
975 {
976 if ((size_t) padding >= maxsize - i)
977 return 0;
978
979 if (p)
980 memset_space (p, padding);
981 i += padding;
982 width = width > padding ? width - padding : 0;
983 if (sign_char)
984 add1 (sign_char);
985 }
986 else
987 {
988 if ((size_t) digits >= maxsize - i)
989 return 0;
990
991 if (sign_char)
992 add1 (sign_char);
993
994 if (p)
995 memset_zero (p, padding);
996 i += padding;
997 width = 0;
998 }
999 }
1000 else
1001 {
1002 if (sign_char)
1003 add1 (sign_char);
1004 }
1005 }
1006
1007 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1008 break;
1009
1010 case L_('F'):
1011 if (modifier != 0)
1012 goto bad_format;
1013 subfmt = L_("%Y-%m-%d");
1014 goto subformat;
1015
1016 case L_('H'):
1017 if (modifier == L_('E'))
1018 goto bad_format;
1019
1020 DO_NUMBER (2, tp->tm_hour);
1021
1022 case L_('I'):
1023 if (modifier == L_('E'))
1024 goto bad_format;
1025
1026 DO_NUMBER (2, hour12);
1027
1028 case L_('k'): /* GNU extension. */
1029 if (modifier == L_('E'))
1030 goto bad_format;
1031
1032 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1033
1034 case L_('l'): /* GNU extension. */
1035 if (modifier == L_('E'))
1036 goto bad_format;
1037
1038 DO_NUMBER_SPACEPAD (2, hour12);
1039
1040 case L_('j'):
1041 if (modifier == L_('E'))
1042 goto bad_format;
1043
1044 DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
1045
1046 case L_('M'):
1047 if (modifier == L_('E'))
1048 goto bad_format;
1049
1050 DO_NUMBER (2, tp->tm_min);
1051
1052 case L_('m'):
1053 if (modifier == L_('E'))
1054 goto bad_format;
1055
1056 DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
1057
1058#ifndef _LIBC
1059 case L_('N'): /* GNU extension. */
1060 if (modifier == L_('E'))
1061 goto bad_format;
1062
1063 number_value = ns;
1064 if (width == -1)
1065 width = 9;
1066 else
1067 {
1068 /* Take an explicit width less than 9 as a precision. */
1069 int j;
1070 for (j = width; j < 9; j++)
1071 number_value /= 10;
1072 }
1073
1074 DO_NUMBER (width, number_value);
1075#endif
1076
1077 case L_('n'):
1078 add1 (L_('\n'));
1079 break;
1080
1081 case L_('P'):
1082 to_lowcase = true;
1083#ifndef _NL_CURRENT
1084 format_char = L_('p');
1085#endif
1086 /* FALLTHROUGH */
1087
1088 case L_('p'):
1089 if (change_case)
1090 {
1091 to_uppcase = false;
1092 to_lowcase = true;
1093 }
1094#ifdef _NL_CURRENT
1095 cpy (ap_len, ampm);
1096 break;
1097#else
1098 goto underlying_strftime;
1099#endif
1100
1101 case L_('R'):
1102 subfmt = L_("%H:%M");
1103 goto subformat;
1104
1105 case L_('r'):
1106#ifdef _NL_CURRENT
1107 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1108 NLW(T_FMT_AMPM)))
1109 == L_('\0'))
1110 subfmt = L_("%I:%M:%S %p");
1111 goto subformat;
1112#else
1113 goto underlying_strftime;
1114#endif
1115
1116 case L_('S'):
1117 if (modifier == L_('E'))
1118 goto bad_format;
1119
1120 DO_NUMBER (2, tp->tm_sec);
1121
1122 case L_('s'): /* GNU extension. */
1123 {
1124 struct tm ltm;
1125 time_t t;
1126
1127 ltm = *tp;
1128 t = mktime (&ltm);
1129
1130 /* Generate string value for T using time_t arithmetic;
1131 this works even if sizeof (long) < sizeof (time_t). */
1132
1133 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1134 negative_number = t < 0;
1135
1136 do
1137 {
1138 int d = t % 10;
1139 t /= 10;
1140 *--bufp = (negative_number ? -d : d) + L_('0');
1141 }
1142 while (t != 0);
1143
1144 digits = 1;
1145 always_output_a_sign = false;
1146 goto do_number_sign_and_padding;
1147 }
1148
1149 case L_('X'):
1150 if (modifier == L_('O'))
1151 goto bad_format;
1152#ifdef _NL_CURRENT
1153 if (! (modifier == L_('E')
1154 && (*(subfmt =
1155 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1156 != L_('\0'))))
1157 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1158 goto subformat;
1159#else
1160 goto underlying_strftime;
1161#endif
1162 case L_('T'):
1163 subfmt = L_("%H:%M:%S");
1164 goto subformat;
1165
1166 case L_('t'):
1167 add1 (L_('\t'));
1168 break;
1169
1170 case L_('u'):
1171 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1172
1173 case L_('U'):
1174 if (modifier == L_('E'))
1175 goto bad_format;
1176
1177 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1178
1179 case L_('V'):
1180 case L_('g'):
1181 case L_('G'):
1182 if (modifier == L_('E'))
1183 goto bad_format;
1184 {
1185 /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
1186 is a leap year, except that YEAR and YEAR - 1 both work
1187 correctly even when (tp->tm_year + TM_YEAR_BASE) would
1188 overflow. */
1189 int year = (tp->tm_year
1190 + (tp->tm_year < 0
1191 ? TM_YEAR_BASE % 400
1192 : TM_YEAR_BASE % 400 - 400));
1193 int year_adjust = 0;
1194 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1195
1196 if (days < 0)
1197 {
1198 /* This ISO week belongs to the previous year. */
1199 year_adjust = -1;
1200 days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
1201 tp->tm_wday);
1202 }
1203 else
1204 {
1205 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1206 tp->tm_wday);
1207 if (0 <= d)
1208 {
1209 /* This ISO week belongs to the next year. */
1210 year_adjust = 1;
1211 days = d;
1212 }
1213 }
1214
1215 switch (*f)
1216 {
1217 case L_('g'):
1218 {
1219 int yy = (tp->tm_year % 100 + year_adjust) % 100;
1220 DO_NUMBER (2, (0 <= yy
1221 ? yy
1222 : tp->tm_year < -TM_YEAR_BASE - year_adjust
1223 ? -yy
1224 : yy + 100));
1225 }
1226
1227 case L_('G'):
1228 DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
1229 (tp->tm_year + (unsigned int) TM_YEAR_BASE
1230 + year_adjust));
1231
1232 default:
1233 DO_NUMBER (2, days / 7 + 1);
1234 }
1235 }
1236
1237 case L_('W'):
1238 if (modifier == L_('E'))
1239 goto bad_format;
1240
1241 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1242
1243 case L_('w'):
1244 if (modifier == L_('E'))
1245 goto bad_format;
1246
1247 DO_NUMBER (1, tp->tm_wday);
1248
1249 case L_('Y'):
1250 if (modifier == 'E')
1251 {
1252#if HAVE_STRUCT_ERA_ENTRY
1253 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1254 if (era)
1255 {
1256# ifdef COMPILE_WIDE
1257 subfmt = era->era_wformat;
1258# else
1259 subfmt = era->era_format;
1260# endif
1261 goto subformat;
1262 }
1263#else
1264 goto underlying_strftime;
1265#endif
1266 }
1267 if (modifier == L_('O'))
1268 goto bad_format;
1269 else
1270 DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE,
1271 tp->tm_year + (unsigned int) TM_YEAR_BASE);
1272
1273 case L_('y'):
1274 if (modifier == L_('E'))
1275 {
1276#if HAVE_STRUCT_ERA_ENTRY
1277 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1278 if (era)
1279 {
1280 int delta = tp->tm_year - era->start_date[0];
1281 DO_NUMBER (1, (era->offset
1282 + delta * era->absolute_direction));
1283 }
1284#else
1285 goto underlying_strftime;
1286#endif
1287 }
1288
1289 {
1290 int yy = tp->tm_year % 100;
1291 if (yy < 0)
1292 yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
1293 DO_NUMBER (2, yy);
1294 }
1295
1296 case L_('Z'):
1297 if (change_case)
1298 {
1299 to_uppcase = false;
1300 to_lowcase = true;
1301 }
1302
1303#if HAVE_TZNAME
1304 /* The tzset() call might have changed the value. */
1305 if (!(zone && *zone) && tp->tm_isdst >= 0)
1306 zone = tzname[tp->tm_isdst != 0];
1307#endif
1308 if (! zone)
1309 zone = "";
1310
1311#ifdef COMPILE_WIDE
1312 {
1313 /* The zone string is always given in multibyte form. We have
1314 to transform it first. */
1315 wchar_t *wczone;
1316 size_t len;
1317 widen (zone, wczone, len);
1318 cpy (len, wczone);
1319 }
1320#else
1321 cpy (strlen (zone), zone);
1322#endif
1323 break;
1324
1325 case L_(':'):
1326 /* :, ::, and ::: are valid only just before 'z'.
1327 :::: etc. are rejected later. */
1328 for (colons = 1; f[colons] == L_(':'); colons++)
1329 continue;
1330 if (f[colons] != L_('z'))
1331 goto bad_format;
1332 f += colons;
1333 goto do_z_conversion;
1334
1335 case L_('z'):
1336 colons = 0;
1337
1338 do_z_conversion:
1339 if (tp->tm_isdst < 0)
1340 break;
1341
1342 {
1343 int diff;
1344 int hour_diff;
1345 int min_diff;
1346 int sec_diff;
1347#if HAVE_TM_GMTOFF
1348 diff = tp->tm_gmtoff;
1349#else
1350 if (ut)
1351 diff = 0;
1352 else
1353 {
1354 struct tm gtm;
1355 struct tm ltm;
1356 time_t lt;
1357
1358 ltm = *tp;
1359 lt = mktime (&ltm);
1360
1361 if (lt == (time_t) -1)
1362 {
1363 /* mktime returns -1 for errors, but -1 is also a
1364 valid time_t value. Check whether an error really
1365 occurred. */
1366 struct tm tm;
1367
1368 if (! __localtime_r (&lt, &tm)
1369 || ((ltm.tm_sec ^ tm.tm_sec)
1370 | (ltm.tm_min ^ tm.tm_min)
1371 | (ltm.tm_hour ^ tm.tm_hour)
1372 | (ltm.tm_mday ^ tm.tm_mday)
1373 | (ltm.tm_mon ^ tm.tm_mon)
1374 | (ltm.tm_year ^ tm.tm_year)))
1375 break;
1376 }
1377
1378 if (! __gmtime_r (&lt, &gtm))
1379 break;
1380
1381 diff = tm_diff (&ltm, &gtm);
1382 }
1383#endif
1384
1385 hour_diff = diff / 60 / 60;
1386 min_diff = diff / 60 % 60;
1387 sec_diff = diff % 60;
1388
1389 switch (colons)
1390 {
1391 case 0: /* +hhmm */
1392 DO_TZ_OFFSET (5, diff < 0, 0, hour_diff * 100 + min_diff);
1393
1394 case 1: tz_hh_mm: /* +hh:mm */
1395 DO_TZ_OFFSET (6, diff < 0, 04, hour_diff * 100 + min_diff);
1396
1397 case 2: tz_hh_mm_ss: /* +hh:mm:ss */
1398 DO_TZ_OFFSET (9, diff < 0, 024,
1399 hour_diff * 10000 + min_diff * 100 + sec_diff);
1400
1401 case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */
1402 if (sec_diff != 0)
1403 goto tz_hh_mm_ss;
1404 if (min_diff != 0)
1405 goto tz_hh_mm;
1406 DO_TZ_OFFSET (3, diff < 0, 0, hour_diff);
1407
1408 default:
1409 goto bad_format;
1410 }
1411 }
1412
1413 case L_('\0'): /* GNU extension: % at end of format. */
1414 --f;
1415 /* Fall through. */
1416 default:
1417 /* Unknown format; output the format, including the '%',
1418 since this is most likely the right thing to do if a
1419 multibyte string has been misparsed. */
1420 bad_format:
1421 {
1422 int flen;
1423 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1424 continue;
1425 cpy (flen, &f[1 - flen]);
1426 }
1427 break;
1428 }
1429 }
1430
1431#if ! FPRINTFTIME
1432 if (p && maxsize != 0)
1433 *p = L_('\0');
1434#endif
1435
1436 return i;
1437}
1438
1439/* Write information from TP into S according to the format
1440 string FORMAT, writing no more that MAXSIZE characters
1441 (including the terminating '\0') and returning number of
1442 characters written. If S is NULL, nothing will be written
1443 anywhere, so to determine how many characters would be
1444 written, use NULL for S and (size_t) -1 for MAXSIZE. */
1445size_t
1446my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
1447 const CHAR_T *format,
1448 const struct tm *tp extra_args_spec LOCALE_PARAM_PROTO)
1449{
1450 return strftime_case_ (false, s, STRFTIME_ARG (maxsize)
1451 format, tp extra_args LOCALE_ARG);
1452}
1453
1454#if defined _LIBC && ! FPRINTFTIME
1455libc_hidden_def (my_strftime)
1456#endif
1457
1458
1459#if defined emacs && ! FPRINTFTIME
1460/* For Emacs we have a separate interface which corresponds to the normal
1461 strftime function plus the ut argument, but without the ns argument. */
1462size_t
1463emacs_strftimeu (char *s, size_t maxsize, const char *format,
1464 const struct tm *tp, int ut)
1465{
1466 return my_strftime (s, maxsize, format, tp, ut, 0);
1467}
1468#endif
diff --git a/lib/strftime.h b/lib/strftime.h
new file mode 100644
index 00000000000..3410568a9a4
--- /dev/null
+++ b/lib/strftime.h
@@ -0,0 +1,34 @@
1/* declarations for strftime.c
2
3 Copyright (C) 2002, 2004, 2008-2011 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18#include <time.h>
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24/* Just like strftime, but with two more arguments:
25 POSIX requires that strftime use the local timezone information.
26 When __UTC is nonzero and tm->tm_zone is NULL or the empty string,
27 use UTC instead. Use __NS as the number of nanoseconds in the
28 %N directive. */
29size_t nstrftime (char *, size_t, char const *, struct tm const *,
30 int __utc, int __ns);
31
32#ifdef __cplusplus
33}
34#endif
diff --git a/m4/gl-comp.m4 b/m4/gl-comp.m4
index 32d3cce4307..e5121918903 100644
--- a/m4/gl-comp.m4
+++ b/m4/gl-comp.m4
@@ -38,7 +38,9 @@ AC_DEFUN([gl_EARLY],
38 # Code from module intprops: 38 # Code from module intprops:
39 # Code from module mktime: 39 # Code from module mktime:
40 # Code from module multiarch: 40 # Code from module multiarch:
41 # Code from module stdbool:
41 # Code from module stddef: 42 # Code from module stddef:
43 # Code from module strftime:
42 # Code from module time: 44 # Code from module time:
43 # Code from module time_r: 45 # Code from module time_r:
44 # Code from module unistd: 46 # Code from module unistd:
@@ -81,8 +83,12 @@ AC_DEFUN([gl_INIT],
81 gl_TIME_MODULE_INDICATOR([mktime]) 83 gl_TIME_MODULE_INDICATOR([mktime])
82 # Code from module multiarch: 84 # Code from module multiarch:
83 gl_MULTIARCH 85 gl_MULTIARCH
86 # Code from module stdbool:
87 AM_STDBOOL_H
84 # Code from module stddef: 88 # Code from module stddef:
85 gl_STDDEF_H 89 gl_STDDEF_H
90 # Code from module strftime:
91 gl_FUNC_GNU_STRFTIME
86 # Code from module time: 92 # Code from module time:
87 gl_HEADER_TIME_H 93 gl_HEADER_TIME_H
88 # Code from module time_r: 94 # Code from module time_r:
@@ -245,7 +251,10 @@ AC_DEFUN([gl_FILE_LIST], [
245 lib/intprops.h 251 lib/intprops.h
246 lib/mktime-internal.h 252 lib/mktime-internal.h
247 lib/mktime.c 253 lib/mktime.c
254 lib/stdbool.in.h
248 lib/stddef.in.h 255 lib/stddef.in.h
256 lib/strftime.c
257 lib/strftime.h
249 lib/time.in.h 258 lib/time.in.h
250 lib/time_r.c 259 lib/time_r.c
251 lib/unistd.in.h 260 lib/unistd.in.h
@@ -257,9 +266,12 @@ AC_DEFUN([gl_FILE_LIST], [
257 m4/include_next.m4 266 m4/include_next.m4
258 m4/mktime.m4 267 m4/mktime.m4
259 m4/multiarch.m4 268 m4/multiarch.m4
269 m4/stdbool.m4
260 m4/stddef_h.m4 270 m4/stddef_h.m4
271 m4/strftime.m4
261 m4/time_h.m4 272 m4/time_h.m4
262 m4/time_r.m4 273 m4/time_r.m4
274 m4/tm_gmtoff.m4
263 m4/unistd_h.m4 275 m4/unistd_h.m4
264 m4/warn-on-use.m4 276 m4/warn-on-use.m4
265 m4/wchar_t.m4 277 m4/wchar_t.m4
diff --git a/m4/stdbool.m4 b/m4/stdbool.m4
new file mode 100644
index 00000000000..df10486d0a8
--- /dev/null
+++ b/m4/stdbool.m4
@@ -0,0 +1,103 @@
1# Check for stdbool.h that conforms to C99.
2
3dnl Copyright (C) 2002-2006, 2009-2011 Free Software Foundation, Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8#serial 3
9
10# Prepare for substituting <stdbool.h> if it is not supported.
11
12AC_DEFUN([AM_STDBOOL_H],
13[
14 AC_REQUIRE([AC_HEADER_STDBOOL])
15
16 # Define two additional variables used in the Makefile substitution.
17
18 if test "$ac_cv_header_stdbool_h" = yes; then
19 STDBOOL_H=''
20 else
21 STDBOOL_H='stdbool.h'
22 fi
23 AC_SUBST([STDBOOL_H])
24
25 if test "$ac_cv_type__Bool" = yes; then
26 HAVE__BOOL=1
27 else
28 HAVE__BOOL=0
29 fi
30 AC_SUBST([HAVE__BOOL])
31])
32
33# AM_STDBOOL_H will be renamed to gl_STDBOOL_H in the future.
34AC_DEFUN([gl_STDBOOL_H], [AM_STDBOOL_H])
35
36# This version of the macro is needed in autoconf <= 2.67. Autoconf has
37# it built in since 2.60, but we want the tweaks from the 2.68 version
38# to avoid rejecting xlc and clang due to relying on extensions.
39
40AC_DEFUN([AC_HEADER_STDBOOL],
41 [AC_CACHE_CHECK([for stdbool.h that conforms to C99],
42 [ac_cv_header_stdbool_h],
43 [AC_COMPILE_IFELSE(
44 [AC_LANG_PROGRAM(
45 [[
46 #include <stdbool.h>
47 #ifndef bool
48 "error: bool is not defined"
49 #endif
50 #ifndef false
51 "error: false is not defined"
52 #endif
53 #if false
54 "error: false is not 0"
55 #endif
56 #ifndef true
57 "error: true is not defined"
58 #endif
59 #if true != 1
60 "error: true is not 1"
61 #endif
62 #ifndef __bool_true_false_are_defined
63 "error: __bool_true_false_are_defined is not defined"
64 #endif
65
66 struct s { _Bool s: 1; _Bool t; } s;
67
68 char a[true == 1 ? 1 : -1];
69 char b[false == 0 ? 1 : -1];
70 char c[__bool_true_false_are_defined == 1 ? 1 : -1];
71 char d[(bool) 0.5 == true ? 1 : -1];
72 /* See body of main program for 'e'. */
73 char f[(_Bool) 0.0 == false ? 1 : -1];
74 char g[true];
75 char h[sizeof (_Bool)];
76 char i[sizeof s.t];
77 enum { j = false, k = true, l = false * true, m = true * 256 };
78 /* The following fails for
79 HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
80 _Bool n[m];
81 char o[sizeof n == m * sizeof n[0] ? 1 : -1];
82 char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
83 /* Catch a bug in an HP-UX C compiler. See
84 http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
85 http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
86 */
87 _Bool q = true;
88 _Bool *pq = &q;
89 ]],
90 [[
91 bool e = &s;
92 *pq |= q;
93 *pq |= ! q;
94 /* Refer to every declared value, to avoid compiler optimizations. */
95 return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
96 + !m + !n + !o + !p + !q + !pq);
97 ]])],
98 [ac_cv_header_stdbool_h=yes],
99 [ac_cv_header_stdbool_h=no])])
100 AC_CHECK_TYPES([_Bool])
101 if test $ac_cv_header_stdbool_h = yes; then
102 AC_DEFINE([HAVE_STDBOOL_H], [1], [Define to 1 if stdbool.h conforms to C99.])
103 fi])
diff --git a/m4/strftime.m4 b/m4/strftime.m4
new file mode 100644
index 00000000000..d9de341bf6d
--- /dev/null
+++ b/m4/strftime.m4
@@ -0,0 +1,30 @@
1# serial 32
2
3# Copyright (C) 1996-1997, 1999-2007, 2009-2011 Free Software Foundation, Inc.
4#
5# This file is free software; the Free Software Foundation
6# gives unlimited permission to copy and/or distribute it,
7# with or without modifications, as long as this notice is preserved.
8
9# Written by Jim Meyering and Paul Eggert.
10
11AC_DEFUN([gl_FUNC_GNU_STRFTIME],
12[
13 gl_FUNC_STRFTIME
14])
15
16# These are the prerequisite macros for GNU's strftime.c replacement.
17AC_DEFUN([gl_FUNC_STRFTIME],
18[
19 AC_LIBOBJ([strftime])
20
21 # This defines (or not) HAVE_TZNAME and HAVE_TM_ZONE.
22 AC_REQUIRE([AC_STRUCT_TIMEZONE])
23
24 AC_REQUIRE([gl_TM_GMTOFF])
25
26 AC_CHECK_FUNCS_ONCE([tzset])
27
28 AC_DEFINE([my_strftime], [nstrftime],
29 [Define to the name of the strftime replacement function.])
30])
diff --git a/m4/tm_gmtoff.m4 b/m4/tm_gmtoff.m4
new file mode 100644
index 00000000000..d65ddc013be
--- /dev/null
+++ b/m4/tm_gmtoff.m4
@@ -0,0 +1,14 @@
1# tm_gmtoff.m4 serial 3
2dnl Copyright (C) 2002, 2009-2011 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN([gl_TM_GMTOFF],
8[
9 AC_CHECK_MEMBER([struct tm.tm_gmtoff],
10 [AC_DEFINE([HAVE_TM_GMTOFF], [1],
11 [Define if struct tm has the tm_gmtoff member.])],
12 ,
13 [#include <time.h>])
14])
diff --git a/src/ChangeLog b/src/ChangeLog
index 5213669e319..393223c0802 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,15 @@
12011-01-30 Paul Eggert <eggert@cs.ucla.edu> 12011-01-30 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 strftime: import from gnulib
4 * Makefile.in (obj): Remove strftime.o, as gnulib now does this for us.
5 * deps.mk (strftime.o): Remove.
6 * editfns.c: Include <strftime.h>, supplied by gnulib.
7 (emacs_strftimeu): Remove decl.
8 (emacs_memftimeu): Use nstrftime (the gnulib name) rather than
9 emacs_strftimeu.
10 * config.in: Regenerate.
11 * strftime.c: Remove; we now use strftime from gnulib.
12
3 Use SSDATA when the context wants char *. 13 Use SSDATA when the context wants char *.
4 * alloc.c, buffer.c, bytecode.c, callproc.c, dired.c: 14 * alloc.c, buffer.c, bytecode.c, callproc.c, dired.c:
5 * dispnew.c, doc.c, editfns.c, emacs.c, fileio.c, filelock.c: 15 * dispnew.c, doc.c, editfns.c, emacs.c, fileio.c, filelock.c:
diff --git a/src/Makefile.in b/src/Makefile.in
index 6d5872d3667..98b4c981482 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -353,7 +353,7 @@ obj= dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
353 syntax.o $(UNEXEC_OBJ) bytecode.o \ 353 syntax.o $(UNEXEC_OBJ) bytecode.o \
354 process.o gnutls.o callproc.o \ 354 process.o gnutls.o callproc.o \
355 region-cache.o sound.o atimer.o \ 355 region-cache.o sound.o atimer.o \
356 doprnt.o strftime.o intervals.o textprop.o composite.o md5.o xml.o \ 356 doprnt.o intervals.o textprop.o composite.o md5.o xml.o \
357 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) 357 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ)
358 358
359## Object files used on some machine or other. 359## Object files used on some machine or other.
diff --git a/src/config.in b/src/config.in
index c08f10be178..48fc7a23d82 100644
--- a/src/config.in
+++ b/src/config.in
@@ -615,6 +615,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
615/* Define to 1 if `speed_t' is declared by <termios.h>. */ 615/* Define to 1 if `speed_t' is declared by <termios.h>. */
616#undef HAVE_SPEED_T 616#undef HAVE_SPEED_T
617 617
618/* Define to 1 if stdbool.h conforms to C99. */
619#undef HAVE_STDBOOL_H
620
618/* Define to 1 if you have the <stdint.h> header file. */ 621/* Define to 1 if you have the <stdint.h> header file. */
619#undef HAVE_STDINT_H 622#undef HAVE_STDINT_H
620 623
@@ -630,9 +633,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
630/* Define to 1 if you have the `strerror' function. */ 633/* Define to 1 if you have the `strerror' function. */
631#undef HAVE_STRERROR 634#undef HAVE_STRERROR
632 635
633/* Define to 1 if you have the `strftime' function. */
634#undef HAVE_STRFTIME
635
636/* Define to 1 if you have the <strings.h> header file. */ 636/* Define to 1 if you have the <strings.h> header file. */
637#undef HAVE_STRINGS_H 637#undef HAVE_STRINGS_H
638 638
@@ -729,7 +729,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
729/* Define to 1 if `struct timeval' is declared by <sys/time.h>. */ 729/* Define to 1 if `struct timeval' is declared by <sys/time.h>. */
730#undef HAVE_TIMEVAL 730#undef HAVE_TIMEVAL
731 731
732/* Define to 1 if `tm_gmtoff' is member of `struct tm'. */ 732/* Define if struct tm has the tm_gmtoff member. */
733#undef HAVE_TM_GMTOFF 733#undef HAVE_TM_GMTOFF
734 734
735/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use 735/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
@@ -831,6 +831,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
831/* Define to 1 if you want to use the X window system. */ 831/* Define to 1 if you want to use the X window system. */
832#undef HAVE_X_WINDOWS 832#undef HAVE_X_WINDOWS
833 833
834/* Define to 1 if the system has the type `_Bool'. */
835#undef HAVE__BOOL
836
834/* Define to 1 if you have the `__builtin_unwind_init' function. */ 837/* Define to 1 if you have the `__builtin_unwind_init' function. */
835#undef HAVE___BUILTIN_UNWIND_INIT 838#undef HAVE___BUILTIN_UNWIND_INIT
836 839
@@ -1092,6 +1095,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
1092/* Define to a type if <wchar.h> does not define. */ 1095/* Define to a type if <wchar.h> does not define. */
1093#undef mbstate_t 1096#undef mbstate_t
1094 1097
1098/* Define to the name of the strftime replacement function. */
1099#undef my_strftime
1100
1095/* Define to `int' if <sys/types.h> does not define. */ 1101/* Define to `int' if <sys/types.h> does not define. */
1096#undef pid_t 1102#undef pid_t
1097 1103
@@ -1192,8 +1198,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
1192#endif 1198#endif
1193#endif 1199#endif
1194 1200
1195#define my_strftime nstrftime /* for strftime.c */
1196
1197/* These default definitions are good for almost all machines. 1201/* These default definitions are good for almost all machines.
1198 The exceptions override them in m/MACHINE.h. */ 1202 The exceptions override them in m/MACHINE.h. */
1199 1203
diff --git a/src/deps.mk b/src/deps.mk
index 98cd7e66fed..7f90688c03b 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -168,7 +168,6 @@ search.o: search.c regex.h commands.h buffer.h region-cache.h syntax.h \
168 $(INTERVALS_H) \ 168 $(INTERVALS_H) \
169 lisp.h $(config_h) 169 lisp.h $(config_h)
170sound.o: sound.c dispextern.h syssignal.h lisp.h $(config_h) atimer.h systime.h 170sound.o: sound.c dispextern.h syssignal.h lisp.h $(config_h) atimer.h systime.h
171strftime.o: strftime.c $(config_h)
172syntax.o: syntax.c syntax.h buffer.h commands.h category.h character.h \ 171syntax.o: syntax.c syntax.h buffer.h commands.h category.h character.h \
173 keymap.h regex.h $(INTERVALS_H) lisp.h $(config_h) 172 keymap.h regex.h $(INTERVALS_H) lisp.h $(config_h)
174sysdep.o: sysdep.c syssignal.h systty.h systime.h syswait.h blockinput.h \ 173sysdep.o: sysdep.c syssignal.h systty.h systime.h syswait.h blockinput.h \
diff --git a/src/editfns.c b/src/editfns.c
index a5f39870000..7364a5bcf15 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -45,6 +45,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
45#endif 45#endif
46 46
47#include <ctype.h> 47#include <ctype.h>
48#include <strftime.h>
48 49
49#include "intervals.h" 50#include "intervals.h"
50#include "buffer.h" 51#include "buffer.h"
@@ -82,9 +83,6 @@ extern char **environ;
82 (1000 - TM_YEAR_BASE <= (tm_year) && (tm_year) <= 9999 - TM_YEAR_BASE) 83 (1000 - TM_YEAR_BASE <= (tm_year) && (tm_year) <= 9999 - TM_YEAR_BASE)
83#endif 84#endif
84 85
85extern size_t emacs_strftimeu (char *, size_t, const char *,
86 const struct tm *, int);
87
88#ifdef WINDOWSNT 86#ifdef WINDOWSNT
89extern Lisp_Object w32_get_internal_run_time (void); 87extern Lisp_Object w32_get_internal_run_time (void);
90#endif 88#endif
@@ -1556,8 +1554,8 @@ or (if you need time as a string) `format-time-string'. */)
1556 determine how many bytes would be written, use NULL for S and 1554 determine how many bytes would be written, use NULL for S and
1557 ((size_t) -1) for MAXSIZE. 1555 ((size_t) -1) for MAXSIZE.
1558 1556
1559 This function behaves like emacs_strftimeu, except it allows null 1557 This function behaves like nstrftime, except it allows null
1560 bytes in FORMAT. */ 1558 bytes in FORMAT and it does not support nanoseconds. */
1561static size_t 1559static size_t
1562emacs_memftimeu (char *s, size_t maxsize, const char *format, size_t format_len, const struct tm *tp, int ut) 1560emacs_memftimeu (char *s, size_t maxsize, const char *format, size_t format_len, const struct tm *tp, int ut)
1563{ 1561{
@@ -1566,7 +1564,7 @@ emacs_memftimeu (char *s, size_t maxsize, const char *format, size_t format_len,
1566 /* Loop through all the null-terminated strings in the format 1564 /* Loop through all the null-terminated strings in the format
1567 argument. Normally there's just one null-terminated string, but 1565 argument. Normally there's just one null-terminated string, but
1568 there can be arbitrarily many, concatenated together, if the 1566 there can be arbitrarily many, concatenated together, if the
1569 format contains '\0' bytes. emacs_strftimeu stops at the first 1567 format contains '\0' bytes. nstrftime stops at the first
1570 '\0' byte so we must invoke it separately for each such string. */ 1568 '\0' byte so we must invoke it separately for each such string. */
1571 for (;;) 1569 for (;;)
1572 { 1570 {
@@ -1576,7 +1574,7 @@ emacs_memftimeu (char *s, size_t maxsize, const char *format, size_t format_len,
1576 if (s) 1574 if (s)
1577 s[0] = '\1'; 1575 s[0] = '\1';
1578 1576
1579 result = emacs_strftimeu (s, maxsize, format, tp, ut); 1577 result = nstrftime (s, maxsize, format, tp, ut, 0);
1580 1578
1581 if (s) 1579 if (s)
1582 { 1580 {
diff --git a/src/strftime.c b/src/strftime.c
deleted file mode 100644
index 5a0923e3723..00000000000
--- a/src/strftime.c
+++ /dev/null
@@ -1,1444 +0,0 @@
1/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2 2001, 2002, 2003, 2004, 2005, 2006, 2007
3 Free Software Foundation, Inc.
4
5 NOTE: The canonical source of this file is maintained with gnulib.
6 Bugs can be reported to bug-gnulib@gnu.org.
7
8 This file is part of the GNU Emacs.
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public
21 License along with the GNU C Library; see the file COPYING. If not,
22 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA. */
24
25#ifdef HAVE_CONFIG_H
26# include <config.h>
27#endif
28
29#ifdef _LIBC
30# define HAVE_LIMITS_H 1
31# define HAVE_MBLEN 1
32# define HAVE_MBRLEN 1
33# define HAVE_STRUCT_ERA_ENTRY 1
34# define HAVE_TM_GMTOFF 1
35# define HAVE_TM_ZONE 1
36# define HAVE_TZNAME 1
37# define HAVE_TZSET 1
38# define MULTIBYTE_IS_FORMAT_SAFE 1
39# define STDC_HEADERS 1
40# include "../locale/localeinfo.h"
41#endif
42
43#include <ctype.h>
44#include <sys/types.h> /* Some systems define `time_t' here. */
45
46#ifdef TIME_WITH_SYS_TIME
47# include <sys/time.h>
48# include <time.h>
49#else
50# ifdef HAVE_SYS_TIME_H
51# include <sys/time.h>
52# else
53# include <time.h>
54# endif
55#endif
56#if HAVE_TZNAME
57#ifndef USE_CRT_DLL
58extern char *tzname[];
59#endif
60#endif
61
62/* Do multibyte processing if multibytes are supported, unless
63 multibyte sequences are safe in formats. Multibyte sequences are
64 safe if they cannot contain byte sequences that look like format
65 conversion specifications. The GNU C Library uses UTF8 multibyte
66 encoding, which is safe for formats, but strftime.c can be used
67 with other C libraries that use unsafe encodings. */
68#define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
69
70#if DO_MULTIBYTE
71# if HAVE_MBRLEN
72# include <wchar.h>
73# ifdef HAVE_SYS__MBSTATE_T_H /* previously tested __hpux */
74# include <sys/_mbstate_t.h>
75# endif
76# if !defined (mbsinit) && !defined (HAVE_MBSINIT)
77# define mbsinit(ps) 1
78# endif /* !defined (mbsinit) && !defined (HAVE_MBSINIT) */
79# else
80 /* Simulate mbrlen with mblen as best we can. */
81# define mbstate_t int
82# define mbrlen(s, n, ps) mblen (s, n)
83# define mbsinit(ps) (*(ps) == 0)
84# endif
85 static const mbstate_t mbstate_zero;
86#endif
87
88#ifdef HAVE_LIMITS_H
89# include <limits.h>
90#endif
91
92#ifdef STDC_HEADERS
93# include <stddef.h>
94# include <stdlib.h>
95# include <string.h>
96#else
97# ifndef HAVE_MEMCPY
98# define memcpy(d, s, n) bcopy ((s), (d), (n))
99# endif
100#endif
101
102#ifdef COMPILE_WIDE
103# include <endian.h>
104# define CHAR_T wchar_t
105# define UCHAR_T unsigned int
106# define L_(Str) L##Str
107# define NLW(Sym) _NL_W##Sym
108
109# define MEMCPY(d, s, n) __wmemcpy (d, s, n)
110# define STRLEN(s) __wcslen (s)
111
112#else
113# define CHAR_T char
114# define UCHAR_T unsigned char
115# define L_(Str) Str
116# define NLW(Sym) Sym
117
118# if !defined STDC_HEADERS && !defined HAVE_MEMCPY
119# define MEMCPY(d, s, n) bcopy ((s), (d), (n))
120# else
121# define MEMCPY(d, s, n) memcpy ((d), (s), (n))
122# endif
123# define STRLEN(s) strlen (s)
124
125# ifdef _LIBC
126# define MEMPCPY(d, s, n) __mempcpy (d, s, n)
127# else
128# ifndef HAVE_MEMPCPY
129# define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
130# endif
131# endif
132#endif
133
134#ifndef PTR
135# ifdef __STDC__
136# define PTR void *
137# else
138# define PTR char *
139# endif
140#endif
141
142#ifndef CHAR_BIT
143# define CHAR_BIT 8
144#endif
145
146#ifndef NULL
147# define NULL 0
148#endif
149
150#define TYPE_SIGNED(t) ((t) -1 < 0)
151
152/* Bound on length of the string representing an integer value of type t.
153 Subtract one for the sign bit if t is signed;
154 302 / 1000 is log10 (2) rounded up;
155 add one for integer division truncation;
156 add one more for a minus sign if t is signed. */
157#define INT_STRLEN_BOUND(t) \
158 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
159
160#define TM_YEAR_BASE 1900
161
162#ifndef __isleap
163/* Nonzero if YEAR is a leap year (every 4 years,
164 except every 100th isn't, and every 400th is). */
165# define __isleap(year) \
166 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
167#endif
168
169
170#ifdef _LIBC
171# define my_strftime_gmtime_r __gmtime_r
172# define my_strftime_localtime_r __localtime_r
173# define tzname __tzname
174# define tzset __tzset
175#else
176
177/* If we're a strftime substitute in a GNU program, then prefer gmtime
178 to gmtime_r, since many gmtime_r implementations are buggy.
179 Similarly for localtime_r. */
180
181# if ! HAVE_TM_GMTOFF
182static struct tm *
183my_strftime_gmtime_r (const time_t *t, struct tm *tp)
184{
185 struct tm *l = gmtime (t);
186 if (! l)
187 return 0;
188 *tp = *l;
189 return tp;
190}
191
192static struct tm *
193my_strftime_localtime_r (const time_t *t, struct tm *tp)
194{
195 struct tm *l = localtime (t);
196 if (! l)
197 return 0;
198 *tp = *l;
199 return tp;
200}
201# endif /* ! HAVE_TM_GMTOFF */
202#endif /* ! defined _LIBC */
203
204
205#if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
206/* Some systems lack the `memset' function and we don't want to
207 introduce additional dependencies. */
208/* The SGI compiler reportedly barfs on the trailing null
209 if we use a string constant as the initializer. 28 June 1997, rms. */
210static const CHAR_T spaces[16] = /* " " */
211{
212 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
213 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
214};
215static const CHAR_T zeroes[16] = /* "0000000000000000" */
216{
217 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
218 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
219};
220
221# define memset_space(P, Len) \
222 do { \
223 int _len = (Len); \
224 \
225 do \
226 { \
227 int _this = _len > 16 ? 16 : _len; \
228 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
229 _len -= _this; \
230 } \
231 while (_len > 0); \
232 } while (0)
233
234# define memset_zero(P, Len) \
235 do { \
236 int _len = (Len); \
237 \
238 do \
239 { \
240 int _this = _len > 16 ? 16 : _len; \
241 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
242 _len -= _this; \
243 } \
244 while (_len > 0); \
245 } while (0)
246#else
247# ifdef COMPILE_WIDE
248# define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
249# define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
250# else
251# define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
252# define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
253# endif
254#endif
255
256#define add(n, f) \
257 do \
258 { \
259 int _n = (n); \
260 int _delta = width - _n; \
261 int _incr = _n + (_delta > 0 ? _delta : 0); \
262 if ((size_t) _incr >= maxsize - i) \
263 return 0; \
264 if (p) \
265 { \
266 if (_delta > 0) \
267 { \
268 if (pad == L_('0')) \
269 memset_zero (p, _delta); \
270 else \
271 memset_space (p, _delta); \
272 } \
273 f; \
274 p += _n; \
275 } \
276 i += _incr; \
277 } while (0)
278
279#define cpy(n, s) \
280 add ((n), \
281 if (to_lowcase) \
282 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
283 else if (to_uppcase) \
284 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
285 else \
286 MEMCPY ((PTR) p, (const PTR) (s), _n))
287
288#ifdef COMPILE_WIDE
289# ifndef USE_IN_EXTENDED_LOCALE_MODEL
290# undef __mbsrtowcs_l
291# define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
292# endif
293# define widen(os, ws, l) \
294 { \
295 mbstate_t __st; \
296 const char *__s = os; \
297 memset (&__st, '\0', sizeof (__st)); \
298 l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
299 ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \
300 (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
301 }
302#endif
303
304
305#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
306/* We use this code also for the extended locale handling where the
307 function gets as an additional argument the locale which has to be
308 used. To access the values we have to redefine the _NL_CURRENT
309 macro. */
310# define strftime __strftime_l
311# define wcsftime __wcsftime_l
312# undef _NL_CURRENT
313# define _NL_CURRENT(category, item) \
314 (current->values[_NL_ITEM_INDEX (item)].string)
315# define LOCALE_ARG , loc
316# define LOCALE_PARAM_DECL , __locale_t loc
317# define HELPER_LOCALE_ARG , current
318#else
319# define LOCALE_ARG
320# define LOCALE_PARAM_DECL
321# ifdef _LIBC
322# define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
323# else
324# define HELPER_LOCALE_ARG
325# endif
326#endif
327
328#ifdef COMPILE_WIDE
329# ifdef USE_IN_EXTENDED_LOCALE_MODEL
330# define TOUPPER(Ch, L) __towupper_l (Ch, L)
331# define TOLOWER(Ch, L) __towlower_l (Ch, L)
332# else
333# define TOUPPER(Ch, L) towupper (Ch)
334# define TOLOWER(Ch, L) towlower (Ch)
335# endif
336#else
337# ifdef _LIBC
338# ifdef USE_IN_EXTENDED_LOCALE_MODEL
339# define TOUPPER(Ch, L) __toupper_l (Ch, L)
340# define TOLOWER(Ch, L) __tolower_l (Ch, L)
341# else
342# define TOUPPER(Ch, L) toupper (Ch)
343# define TOLOWER(Ch, L) tolower (Ch)
344# endif
345# else
346# define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
347# define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
348# endif
349#endif
350/* We don't use `isdigit' here since the locale dependent
351 interpretation is not what we want here. We only need to accept
352 the arabic digits in the ASCII range. One day there is perhaps a
353 more reliable way to accept other sets of digits. */
354#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
355
356static CHAR_T *
357memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM_DECL)
358{
359 while (len-- > 0)
360 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
361 return dest;
362}
363
364static CHAR_T *
365memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM_DECL)
366{
367 while (len-- > 0)
368 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
369 return dest;
370}
371
372
373#if ! HAVE_TM_GMTOFF
374/* Yield the difference between *A and *B,
375 measured in seconds, ignoring leap seconds. */
376# define tm_diff ftime_tm_diff
377static int
378tm_diff (const struct tm *a, const struct tm *b)
379{
380 /* Compute intervening leap days correctly even if year is negative.
381 Take care to avoid int overflow in leap day calculations,
382 but it's OK to assume that A and B are close to each other. */
383 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
384 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
385 int a100 = a4 / 25 - (a4 % 25 < 0);
386 int b100 = b4 / 25 - (b4 % 25 < 0);
387 int a400 = a100 >> 2;
388 int b400 = b100 >> 2;
389 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
390 int years = a->tm_year - b->tm_year;
391 int days = (365 * years + intervening_leap_days
392 + (a->tm_yday - b->tm_yday));
393 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
394 + (a->tm_min - b->tm_min))
395 + (a->tm_sec - b->tm_sec));
396}
397#endif /* ! HAVE_TM_GMTOFF */
398
399
400
401/* The number of days from the first day of the first ISO week of this
402 year to the year day YDAY with week day WDAY. ISO weeks start on
403 Monday; the first ISO week has the year's first Thursday. YDAY may
404 be as small as YDAY_MINIMUM. */
405#define ISO_WEEK_START_WDAY 1 /* Monday */
406#define ISO_WEEK1_WDAY 4 /* Thursday */
407#define YDAY_MINIMUM (-366)
408static int iso_week_days (int, int);
409#ifdef __GNUC__
410__inline__
411#endif
412static int
413iso_week_days (int yday, int wday)
414{
415 /* Add enough to the first operand of % to make it nonnegative. */
416 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
417 return (yday
418 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
419 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
420}
421
422
423#if !(defined _NL_CURRENT || HAVE_STRFTIME)
424static CHAR_T const weekday_name[][10] =
425 {
426 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
427 L_("Thursday"), L_("Friday"), L_("Saturday")
428 };
429static CHAR_T const month_name[][10] =
430 {
431 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
432 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
433 L_("November"), L_("December")
434 };
435#endif
436
437
438/* When compiling this file, GNU applications can #define my_strftime
439 to a symbol (typically nstrftime) to get an extended strftime with
440 extra arguments UT and NS. */
441
442#ifdef my_strftime
443# define extra_args , ut, ns
444# define extra_args_spec , int ut, int ns
445#else
446# ifdef COMPILE_WIDE
447# define my_strftime wcsftime
448# define nl_get_alt_digit _nl_get_walt_digit
449# else
450# define my_strftime strftime
451# define nl_get_alt_digit _nl_get_alt_digit
452# endif
453# define extra_args
454# define extra_args_spec
455/* We don't have this information in general. */
456# define ut 0
457# define ns 0
458#endif
459
460#if !defined _LIBC && !defined(WINDOWSNT) && HAVE_TZNAME && HAVE_TZSET
461 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
462 Work around this bug by copying *tp before it might be munged. */
463 size_t
464 _strftime_copytm (CHAR_T *s, size_t maxsize, const CHAR_T *format,
465 const struct tm *tp extra_args_spec LOCALE_PARAM_DECL);
466 size_t
467 my_strftime (CHAR_T *s, size_t maxsize, const CHAR_T *format,
468 const struct tm *tp extra_args_spec)
469 {
470 struct tm tmcopy;
471 tmcopy = *tp;
472 return _strftime_copytm (s, maxsize, format, &tmcopy extra_args);
473 }
474# undef my_strftime
475# define my_strftime _strftime_copytm
476#endif
477
478
479/* Write information from TP into S according to the format
480 string FORMAT, writing no more that MAXSIZE characters
481 (including the terminating '\0') and returning number of
482 characters written. If S is NULL, nothing will be written
483 anywhere, so to determine how many characters would be
484 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
485size_t
486my_strftime (CHAR_T *s, size_t maxsize, const CHAR_T *format,
487 const struct tm *tp extra_args_spec LOCALE_PARAM_DECL)
488{
489#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
490 struct locale_data *const current = loc->__locales[LC_TIME];
491#endif
492
493 int hour12 = tp->tm_hour;
494#ifdef _NL_CURRENT
495 /* We cannot make the following values variables since we must delay
496 the evaluation of these values until really needed since some
497 expressions might not be valid in every situation. The `struct tm'
498 might be generated by a strptime() call that initialized
499 only a few elements. Dereference the pointers only if the format
500 requires this. Then it is ok to fail if the pointers are invalid. */
501# define a_wkday \
502 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
503# define f_wkday \
504 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
505# define a_month \
506 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
507# define f_month \
508 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
509# define ampm \
510 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
511 ? NLW(PM_STR) : NLW(AM_STR)))
512
513# define aw_len STRLEN (a_wkday)
514# define am_len STRLEN (a_month)
515# define ap_len STRLEN (ampm)
516#else
517# if !HAVE_STRFTIME
518# define f_wkday (weekday_name[tp->tm_wday])
519# define f_month (month_name[tp->tm_mon])
520# define a_wkday f_wkday
521# define a_month f_month
522# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
523
524 size_t aw_len = 3;
525 size_t am_len = 3;
526 size_t ap_len = 2;
527# endif
528#endif
529 const char *zone;
530 size_t i = 0;
531 CHAR_T *p = s;
532 const CHAR_T *f;
533#if DO_MULTIBYTE && !defined COMPILE_WIDE
534 const char *format_end = NULL;
535#endif
536
537 zone = NULL;
538#if HAVE_TM_ZONE
539 /* The POSIX test suite assumes that setting
540 the environment variable TZ to a new value before calling strftime()
541 will influence the result (the %Z format) even if the information in
542 TP is computed with a totally different time zone.
543 This is bogus: though POSIX allows bad behavior like this,
544 POSIX does not require it. Do the right thing instead. */
545 zone = (const char *) tp->tm_zone;
546#endif
547#if HAVE_TZNAME
548 if (ut)
549 {
550 if (! (zone && *zone))
551 zone = "GMT";
552 }
553 else
554 {
555 /* POSIX.1 requires that local time zone information be used as
556 though strftime called tzset. */
557# if HAVE_TZSET
558 tzset ();
559# endif
560 }
561#endif
562
563 if (hour12 > 12)
564 hour12 -= 12;
565 else
566 if (hour12 == 0)
567 hour12 = 12;
568
569 for (f = format; *f != '\0'; ++f)
570 {
571 int pad = 0; /* Padding for number ('-', '_', or 0). */
572 int modifier; /* Field modifier ('E', 'O', or 0). */
573 int digits; /* Max digits for numeric format. */
574 int number_value; /* Numeric value to be printed. */
575 int negative_number; /* 1 if the number is negative. */
576 const CHAR_T *subfmt;
577 CHAR_T *bufp;
578 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
579 ? INT_STRLEN_BOUND (time_t)
580 : INT_STRLEN_BOUND (int))];
581 int width = -1;
582 int to_lowcase = 0;
583 int to_uppcase = 0;
584 int change_case = 0;
585 int format_char;
586
587#if DO_MULTIBYTE && !defined COMPILE_WIDE
588 switch (*f)
589 {
590 case L_('%'):
591 break;
592
593 case L_('\b'): case L_('\t'): case L_('\n'):
594 case L_('\v'): case L_('\f'): case L_('\r'):
595 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
596 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
597 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
598 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
599 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
600 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
601 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
602 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
603 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
604 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
605 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
606 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
607 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
608 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
609 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
610 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
611 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
612 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
613 case L_('~'):
614 /* The C Standard requires these 98 characters (plus '%') to
615 be in the basic execution character set. None of these
616 characters can start a multibyte sequence, so they need
617 not be analyzed further. */
618 add (1, *p = *f);
619 continue;
620
621 default:
622 /* Copy this multibyte sequence until we reach its end, find
623 an error, or come back to the initial shift state. */
624 {
625 mbstate_t mbstate = mbstate_zero;
626 size_t len = 0;
627 size_t fsize;
628
629 if (! format_end)
630 format_end = f + strlen (f) + 1;
631 fsize = format_end - f;
632
633 do
634 {
635 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
636
637 if (bytes == 0)
638 break;
639
640 if (bytes == (size_t) -2)
641 {
642 len += strlen (f + len);
643 break;
644 }
645
646 if (bytes == (size_t) -1)
647 {
648 len++;
649 break;
650 }
651
652 len += bytes;
653 }
654 while (! mbsinit (&mbstate));
655
656 cpy (len, f);
657 f += len - 1;
658 continue;
659 }
660 }
661
662#else /* ! DO_MULTIBYTE */
663
664 /* Either multibyte encodings are not supported, they are
665 safe for formats, so any non-'%' byte can be copied through,
666 or this is the wide character version. */
667 if (*f != L_('%'))
668 {
669 add (1, *p = *f);
670 continue;
671 }
672
673#endif /* ! DO_MULTIBYTE */
674
675 /* Check for flags that can modify a format. */
676 while (1)
677 {
678 switch (*++f)
679 {
680 /* This influences the number formats. */
681 case L_('_'):
682 case L_('-'):
683 case L_('0'):
684 pad = *f;
685 continue;
686
687 /* This changes textual output. */
688 case L_('^'):
689 to_uppcase = 1;
690 continue;
691 case L_('#'):
692 change_case = 1;
693 continue;
694
695 default:
696 break;
697 }
698 break;
699 }
700
701 /* As a GNU extension we allow to specify the field width. */
702 if (ISDIGIT (*f))
703 {
704 width = 0;
705 do
706 {
707 if (width > INT_MAX / 10
708 || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
709 /* Avoid overflow. */
710 width = INT_MAX;
711 else
712 {
713 width *= 10;
714 width += *f - L_('0');
715 }
716 ++f;
717 }
718 while (ISDIGIT (*f));
719 }
720
721 /* Check for modifiers. */
722 switch (*f)
723 {
724 case L_('E'):
725 case L_('O'):
726 modifier = *f++;
727 break;
728
729 default:
730 modifier = 0;
731 break;
732 }
733
734 /* Now do the specified format. */
735 format_char = *f;
736 switch (format_char)
737 {
738#define DO_NUMBER(d, v) \
739 digits = d > width ? d : width; \
740 number_value = v; goto do_number
741#define DO_NUMBER_SPACEPAD(d, v) \
742 digits = d > width ? d : width; \
743 number_value = v; goto do_number_spacepad
744
745 case L_('%'):
746 if (modifier != 0)
747 goto bad_format;
748 add (1, *p = *f);
749 break;
750
751 case L_('a'):
752 if (modifier != 0)
753 goto bad_format;
754 if (change_case)
755 {
756 to_uppcase = 1;
757 to_lowcase = 0;
758 }
759#if defined _NL_CURRENT || !HAVE_STRFTIME
760 cpy (aw_len, a_wkday);
761 break;
762#else
763 goto underlying_strftime;
764#endif
765
766 case 'A':
767 if (modifier != 0)
768 goto bad_format;
769 if (change_case)
770 {
771 to_uppcase = 1;
772 to_lowcase = 0;
773 }
774#if defined _NL_CURRENT || !HAVE_STRFTIME
775 cpy (STRLEN (f_wkday), f_wkday);
776 break;
777#else
778 goto underlying_strftime;
779#endif
780
781 case L_('b'):
782 case L_('h'):
783 if (change_case)
784 {
785 to_uppcase = 1;
786 to_lowcase = 0;
787 }
788 if (modifier != 0)
789 goto bad_format;
790#if defined _NL_CURRENT || !HAVE_STRFTIME
791 cpy (am_len, a_month);
792 break;
793#else
794 goto underlying_strftime;
795#endif
796
797 case L_('B'):
798 if (modifier != 0)
799 goto bad_format;
800 if (change_case)
801 {
802 to_uppcase = 1;
803 to_lowcase = 0;
804 }
805#if defined _NL_CURRENT || !HAVE_STRFTIME
806 cpy (STRLEN (f_month), f_month);
807 break;
808#else
809 goto underlying_strftime;
810#endif
811
812 case L_('c'):
813 if (modifier == L_('O'))
814 goto bad_format;
815#ifdef _NL_CURRENT
816 if (! (modifier == 'E'
817 && (*(subfmt =
818 (const CHAR_T *) _NL_CURRENT (LC_TIME,
819 NLW(ERA_D_T_FMT)))
820 != '\0')))
821 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
822#else
823# if HAVE_STRFTIME
824 goto underlying_strftime;
825# else
826 subfmt = L_("%a %b %e %H:%M:%S %Y");
827# endif
828#endif
829
830 subformat:
831 {
832 CHAR_T *old_start = p;
833 size_t len = my_strftime (NULL, (size_t) -1, subfmt,
834 tp extra_args LOCALE_ARG);
835 add (len, my_strftime (p, maxsize - i, subfmt,
836 tp extra_args LOCALE_ARG));
837
838 if (to_uppcase)
839 while (old_start < p)
840 {
841 *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
842 ++old_start;
843 }
844 }
845 break;
846
847#if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
848 underlying_strftime:
849 {
850 /* The relevant information is available only via the
851 underlying strftime implementation, so use that. */
852 char ufmt[4];
853 char *u = ufmt;
854 char ubuf[1024]; /* enough for any single format in practice */
855 size_t len;
856 /* Make sure we're calling the actual underlying strftime.
857 In some cases, config.h contains something like
858 "#define strftime rpl_strftime". */
859# ifdef strftime
860# undef strftime
861 size_t strftime ();
862# endif
863
864#ifdef STRFTIME_NO_POSIX2
865 /* Some system libraries do not support the POSIX.2 extensions.
866 In those cases, convert %h to %b, and strip modifiers. */
867 modifier = 0;
868 if (format_char == 'h')
869 format_char = 'b';
870#endif
871 *u++ = '%';
872 if (modifier != 0)
873 *u++ = modifier;
874 *u++ = format_char;
875 *u = '\0';
876 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
877 if (len == 0 && ubuf[0] != '\0')
878 return 0;
879 cpy (len, ubuf);
880 }
881 break;
882#endif
883
884 case L_('C'):
885 if (modifier == L_('O'))
886 goto bad_format;
887 if (modifier == L_('E'))
888 {
889#if HAVE_STRUCT_ERA_ENTRY
890 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
891 if (era)
892 {
893# ifdef COMPILE_WIDE
894 size_t len = __wcslen (era->era_wname);
895 cpy (len, era->era_wname);
896# else
897 size_t len = strlen (era->era_name);
898 cpy (len, era->era_name);
899# endif
900 break;
901 }
902#else
903# if HAVE_STRFTIME
904 goto underlying_strftime;
905# endif
906#endif
907 }
908
909 {
910 int year = tp->tm_year + TM_YEAR_BASE;
911 DO_NUMBER (1, year / 100 - (year % 100 < 0));
912 }
913
914 case L_('x'):
915 if (modifier == L_('O'))
916 goto bad_format;
917#ifdef _NL_CURRENT
918 if (! (modifier == L_('E')
919 && (*(subfmt =
920 (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
921 != L_('\0'))))
922 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
923 goto subformat;
924#else
925# if HAVE_STRFTIME
926 goto underlying_strftime;
927# else
928 /* Fall through. */
929# endif
930#endif
931 case L_('D'):
932 if (modifier != 0)
933 goto bad_format;
934 subfmt = L_("%m/%d/%y");
935 goto subformat;
936
937 case L_('d'):
938 if (modifier == L_('E'))
939 goto bad_format;
940
941 DO_NUMBER (2, tp->tm_mday);
942
943 case L_('e'):
944 if (modifier == L_('E'))
945 goto bad_format;
946
947 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
948
949 /* All numeric formats set DIGITS and NUMBER_VALUE and then
950 jump to one of these two labels. */
951
952 do_number_spacepad:
953 /* Force `_' flag unless overridden by `0' or `-' flag. */
954 if (pad != L_('0') && pad != L_('-'))
955 pad = L_('_');
956
957 do_number:
958 /* Format the number according to the MODIFIER flag. */
959
960 if (modifier == L_('O') && 0 <= number_value)
961 {
962#ifdef _NL_CURRENT
963 /* Get the locale specific alternate representation of
964 the number NUMBER_VALUE. If none exist NULL is returned. */
965 const CHAR_T *cp = nl_get_alt_digit (number_value
966 HELPER_LOCALE_ARG);
967
968 if (cp != NULL)
969 {
970 size_t digitlen = STRLEN (cp);
971 if (digitlen != 0)
972 {
973 cpy (digitlen, cp);
974 break;
975 }
976 }
977#else
978# if HAVE_STRFTIME
979 goto underlying_strftime;
980# endif
981#endif
982 }
983 {
984 unsigned int u = number_value;
985
986 bufp = buf + sizeof (buf) / sizeof (buf[0]);
987 negative_number = number_value < 0;
988
989 if (negative_number)
990 u = -u;
991
992 do
993 *--bufp = u % 10 + L_('0');
994 while ((u /= 10) != 0);
995 }
996
997 do_number_sign_and_padding:
998 if (negative_number)
999 *--bufp = L_('-');
1000
1001 if (pad != L_('-'))
1002 {
1003 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
1004 - bufp);
1005
1006 if (padding > 0)
1007 {
1008 if (pad == L_('_'))
1009 {
1010 if ((size_t) padding >= maxsize - i)
1011 return 0;
1012
1013 if (p)
1014 memset_space (p, padding);
1015 i += padding;
1016 width = width > padding ? width - padding : 0;
1017 }
1018 else
1019 {
1020 if ((size_t) digits >= maxsize - i)
1021 return 0;
1022
1023 if (negative_number)
1024 {
1025 ++bufp;
1026
1027 if (p)
1028 *p++ = L_('-');
1029 ++i;
1030 }
1031
1032 if (p)
1033 memset_zero (p, padding);
1034 i += padding;
1035 width = 0;
1036 }
1037 }
1038 }
1039
1040 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1041 break;
1042
1043 case L_('F'):
1044 if (modifier != 0)
1045 goto bad_format;
1046 subfmt = L_("%Y-%m-%d");
1047 goto subformat;
1048
1049 case L_('H'):
1050 if (modifier == L_('E'))
1051 goto bad_format;
1052
1053 DO_NUMBER (2, tp->tm_hour);
1054
1055 case L_('I'):
1056 if (modifier == L_('E'))
1057 goto bad_format;
1058
1059 DO_NUMBER (2, hour12);
1060
1061 case L_('k'): /* GNU extension. */
1062 if (modifier == L_('E'))
1063 goto bad_format;
1064
1065 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1066
1067 case L_('l'): /* GNU extension. */
1068 if (modifier == L_('E'))
1069 goto bad_format;
1070
1071 DO_NUMBER_SPACEPAD (2, hour12);
1072
1073 case L_('j'):
1074 if (modifier == L_('E'))
1075 goto bad_format;
1076
1077 DO_NUMBER (3, 1 + tp->tm_yday);
1078
1079 case L_('M'):
1080 if (modifier == L_('E'))
1081 goto bad_format;
1082
1083 DO_NUMBER (2, tp->tm_min);
1084
1085 case L_('m'):
1086 if (modifier == L_('E'))
1087 goto bad_format;
1088
1089 DO_NUMBER (2, tp->tm_mon + 1);
1090
1091#ifndef _LIBC
1092 case L_('N'): /* GNU extension. */
1093 if (modifier == L_('E'))
1094 goto bad_format;
1095
1096 number_value = ns;
1097 if (width != -1)
1098 {
1099 /* Take an explicit width less than 9 as a precision. */
1100 int j;
1101 for (j = width; j < 9; j++)
1102 number_value /= 10;
1103 }
1104
1105 DO_NUMBER (9, number_value);
1106#endif
1107
1108 case L_('n'):
1109 add (1, *p = L_('\n'));
1110 break;
1111
1112 case L_('P'):
1113 to_lowcase = 1;
1114#if !defined _NL_CURRENT && HAVE_STRFTIME
1115 format_char = L_('p');
1116#endif
1117 /* FALLTHROUGH */
1118
1119 case L_('p'):
1120 if (change_case)
1121 {
1122 to_uppcase = 0;
1123 to_lowcase = 1;
1124 }
1125#if defined _NL_CURRENT || !HAVE_STRFTIME
1126 cpy (ap_len, ampm);
1127 break;
1128#else
1129 goto underlying_strftime;
1130#endif
1131
1132 case L_('R'):
1133 subfmt = L_("%H:%M");
1134 goto subformat;
1135
1136 case L_('r'):
1137#ifdef _NL_CURRENT
1138 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1139 NLW(T_FMT_AMPM)))
1140 == L_('\0'))
1141#endif
1142 subfmt = L_("%I:%M:%S %p");
1143 goto subformat;
1144
1145 case L_('S'):
1146 if (modifier == L_('E'))
1147 goto bad_format;
1148
1149 DO_NUMBER (2, tp->tm_sec);
1150
1151 case L_('s'): /* GNU extension. */
1152 {
1153 struct tm ltm;
1154 time_t t;
1155
1156 ltm = *tp;
1157 t = mktime (&ltm);
1158
1159 /* Generate string value for T using time_t arithmetic;
1160 this works even if sizeof (long) < sizeof (time_t). */
1161
1162 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1163 negative_number = t < 0;
1164
1165 do
1166 {
1167 int d = t % 10;
1168 t /= 10;
1169
1170 if (negative_number)
1171 {
1172 d = -d;
1173
1174 /* Adjust if division truncates to minus infinity. */
1175 if (0 < -1 % 10 && d < 0)
1176 {
1177 t++;
1178 d += 10;
1179 }
1180 }
1181
1182 *--bufp = d + L_('0');
1183 }
1184 while (t != 0);
1185
1186 digits = 1;
1187 goto do_number_sign_and_padding;
1188 }
1189
1190 case L_('X'):
1191 if (modifier == L_('O'))
1192 goto bad_format;
1193#ifdef _NL_CURRENT
1194 if (! (modifier == L_('E')
1195 && (*(subfmt =
1196 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1197 != L_('\0'))))
1198 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1199 goto subformat;
1200#else
1201# if HAVE_STRFTIME
1202 goto underlying_strftime;
1203# else
1204 /* Fall through. */
1205# endif
1206#endif
1207 case L_('T'):
1208 subfmt = L_("%H:%M:%S");
1209 goto subformat;
1210
1211 case L_('t'):
1212 add (1, *p = L_('\t'));
1213 break;
1214
1215 case L_('u'):
1216 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1217
1218 case L_('U'):
1219 if (modifier == L_('E'))
1220 goto bad_format;
1221
1222 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1223
1224 case L_('V'):
1225 case L_('g'):
1226 case L_('G'):
1227 if (modifier == L_('E'))
1228 goto bad_format;
1229 {
1230 int year = tp->tm_year + TM_YEAR_BASE;
1231 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1232
1233 if (days < 0)
1234 {
1235 /* This ISO week belongs to the previous year. */
1236 year--;
1237 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1238 tp->tm_wday);
1239 }
1240 else
1241 {
1242 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1243 tp->tm_wday);
1244 if (0 <= d)
1245 {
1246 /* This ISO week belongs to the next year. */
1247 year++;
1248 days = d;
1249 }
1250 }
1251
1252 switch (*f)
1253 {
1254 case L_('g'):
1255 DO_NUMBER (2, (year % 100 + 100) % 100);
1256
1257 case L_('G'):
1258 DO_NUMBER (1, year);
1259
1260 default:
1261 DO_NUMBER (2, days / 7 + 1);
1262 }
1263 }
1264
1265 case L_('W'):
1266 if (modifier == L_('E'))
1267 goto bad_format;
1268
1269 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1270
1271 case L_('w'):
1272 if (modifier == L_('E'))
1273 goto bad_format;
1274
1275 DO_NUMBER (1, tp->tm_wday);
1276
1277 case L_('Y'):
1278 if (modifier == 'E')
1279 {
1280#if HAVE_STRUCT_ERA_ENTRY
1281 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1282 if (era)
1283 {
1284# ifdef COMPILE_WIDE
1285 subfmt = era->era_wformat;
1286# else
1287 subfmt = era->era_format;
1288# endif
1289 goto subformat;
1290 }
1291#else
1292# if HAVE_STRFTIME
1293 goto underlying_strftime;
1294# endif
1295#endif
1296 }
1297 if (modifier == L_('O'))
1298 goto bad_format;
1299 else
1300 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1301
1302 case L_('y'):
1303 if (modifier == L_('E'))
1304 {
1305#if HAVE_STRUCT_ERA_ENTRY
1306 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1307 if (era)
1308 {
1309 int delta = tp->tm_year - era->start_date[0];
1310 DO_NUMBER (1, (era->offset
1311 + delta * era->absolute_direction));
1312 }
1313#else
1314# if HAVE_STRFTIME
1315 goto underlying_strftime;
1316# endif
1317#endif
1318 }
1319 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1320
1321 case L_('Z'):
1322 if (change_case)
1323 {
1324 to_uppcase = 0;
1325 to_lowcase = 1;
1326 }
1327
1328#if HAVE_TZNAME
1329 /* The tzset() call might have changed the value. */
1330 if (!(zone && *zone) && tp->tm_isdst >= 0)
1331 zone = tzname[tp->tm_isdst];
1332#endif
1333 if (! zone)
1334 zone = "";
1335
1336#ifdef COMPILE_WIDE
1337 {
1338 /* The zone string is always given in multibyte form. We have
1339 to transform it first. */
1340 wchar_t *wczone;
1341 size_t len;
1342 widen (zone, wczone, len);
1343 cpy (len, wczone);
1344 }
1345#else
1346 cpy (strlen (zone), zone);
1347#endif
1348 break;
1349
1350 case L_('z'):
1351 if (tp->tm_isdst < 0)
1352 break;
1353
1354 {
1355 int diff;
1356#if HAVE_TM_GMTOFF
1357 diff = tp->tm_gmtoff;
1358#else
1359 if (ut)
1360 diff = 0;
1361 else
1362 {
1363 struct tm gtm;
1364 struct tm ltm;
1365 time_t lt;
1366
1367 ltm = *tp;
1368 lt = mktime (&ltm);
1369
1370 if (lt == (time_t) -1)
1371 {
1372 /* mktime returns -1 for errors, but -1 is also a
1373 valid time_t value. Check whether an error really
1374 occurred. */
1375 struct tm tm;
1376
1377 if (! my_strftime_localtime_r (&lt, &tm)
1378 || ((ltm.tm_sec ^ tm.tm_sec)
1379 | (ltm.tm_min ^ tm.tm_min)
1380 | (ltm.tm_hour ^ tm.tm_hour)
1381 | (ltm.tm_mday ^ tm.tm_mday)
1382 | (ltm.tm_mon ^ tm.tm_mon)
1383 | (ltm.tm_year ^ tm.tm_year)))
1384 break;
1385 }
1386
1387 if (! my_strftime_gmtime_r (&lt, &gtm))
1388 break;
1389
1390 diff = tm_diff (&ltm, &gtm);
1391 }
1392#endif
1393
1394 if (diff < 0)
1395 {
1396 add (1, *p = L_('-'));
1397 diff = -diff;
1398 }
1399 else
1400 add (1, *p = L_('+'));
1401
1402 diff /= 60;
1403 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1404 }
1405
1406 case L_('\0'): /* GNU extension: % at end of format. */
1407 --f;
1408 /* Fall through. */
1409 default:
1410 /* Unknown format; output the format, including the '%',
1411 since this is most likely the right thing to do if a
1412 multibyte string has been misparsed. */
1413 bad_format:
1414 {
1415 int flen;
1416 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1417 continue;
1418 cpy (flen, &f[1 - flen]);
1419 }
1420 break;
1421 }
1422 }
1423
1424 if (p && maxsize != 0)
1425 *p = L_('\0');
1426 return i;
1427}
1428#ifdef _LIBC
1429libc_hidden_def (my_strftime)
1430#endif
1431
1432
1433#ifdef emacs
1434#undef ut
1435/* For Emacs we have a separate interface which corresponds to the normal
1436 strftime function plus the ut argument, but without the ns argument. */
1437size_t
1438emacs_strftimeu (char *s, size_t maxsize, const char *format,
1439 const struct tm *tp, int ut)
1440{
1441 return my_strftime (s, maxsize, format, tp, ut, 0);
1442}
1443#endif
1444