Update copyright notices with scripts/update-copyrights.
[external/glibc.git] / time / strftime_l.c
1 /* Copyright (C) 2002-2013 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library 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 GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <http://www.gnu.org/licenses/>.  */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #ifdef _LIBC
23 # define USE_IN_EXTENDED_LOCALE_MODEL 1
24 # define HAVE_LIMITS_H 1
25 # define HAVE_MBLEN 1
26 # define HAVE_MBRLEN 1
27 # define HAVE_STRUCT_ERA_ENTRY 1
28 # define HAVE_TM_GMTOFF 1
29 # define HAVE_TM_ZONE 1
30 # define HAVE_TZNAME 1
31 # define HAVE_TZSET 1
32 # define MULTIBYTE_IS_FORMAT_SAFE 1
33 # define STDC_HEADERS 1
34 # include "../locale/localeinfo.h"
35 #endif
36
37 #if defined emacs && !defined HAVE_BCOPY
38 # define HAVE_MEMCPY 1
39 #endif
40
41 #include <ctype.h>
42 #include <sys/types.h>          /* Some systems define `time_t' here.  */
43
44 #ifdef TIME_WITH_SYS_TIME
45 # include <sys/time.h>
46 # include <time.h>
47 #else
48 # ifdef HAVE_SYS_TIME_H
49 #  include <sys/time.h>
50 # else
51 #  include <time.h>
52 # endif
53 #endif
54 #if HAVE_TZNAME
55 extern char *tzname[];
56 #endif
57
58 /* Do multibyte processing if multibytes are supported, unless
59    multibyte sequences are safe in formats.  Multibyte sequences are
60    safe if they cannot contain byte sequences that look like format
61    conversion specifications.  The GNU C Library uses UTF8 multibyte
62    encoding, which is safe for formats, but strftime.c can be used
63    with other C libraries that use unsafe encodings.  */
64 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
65
66 #if DO_MULTIBYTE
67 # if HAVE_MBRLEN
68 #  include <wchar.h>
69 # else
70    /* Simulate mbrlen with mblen as best we can.  */
71 #  define mbstate_t int
72 #  define mbrlen(s, n, ps) mblen (s, n)
73 #  define mbsinit(ps) (*(ps) == 0)
74 # endif
75   static const mbstate_t mbstate_zero;
76 #endif
77
78 #if HAVE_LIMITS_H
79 # include <limits.h>
80 #endif
81
82 #if STDC_HEADERS
83 # include <stddef.h>
84 # include <stdlib.h>
85 # include <string.h>
86 # include <stdbool.h>
87 #else
88 # ifndef HAVE_MEMCPY
89 #  define memcpy(d, s, n) bcopy ((s), (d), (n))
90 # endif
91 #endif
92
93 #ifdef COMPILE_WIDE
94 # include <endian.h>
95 # define CHAR_T wchar_t
96 # define UCHAR_T unsigned int
97 # define L_(Str) L##Str
98 # define NLW(Sym) _NL_W##Sym
99
100 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
101 # define STRLEN(s) __wcslen (s)
102
103 #else
104 # define CHAR_T char
105 # define UCHAR_T unsigned char
106 # define L_(Str) Str
107 # define NLW(Sym) Sym
108
109 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
110 #  define MEMCPY(d, s, n) bcopy ((s), (d), (n))
111 # else
112 #  define MEMCPY(d, s, n) memcpy ((d), (s), (n))
113 # endif
114 # define STRLEN(s) strlen (s)
115
116 # ifdef _LIBC
117 #  define MEMPCPY(d, s, n) __mempcpy (d, s, n)
118 # else
119 #  ifndef HAVE_MEMPCPY
120 #   define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
121 #  endif
122 # endif
123 #endif
124
125 #ifndef PTR
126 # define PTR void *
127 #endif
128
129 #ifndef CHAR_BIT
130 # define CHAR_BIT 8
131 #endif
132
133 #ifndef NULL
134 # define NULL 0
135 #endif
136
137 #define TYPE_SIGNED(t) ((t) -1 < 0)
138
139 /* Bound on length of the string representing an integer value of type t.
140    Subtract one for the sign bit if t is signed;
141    302 / 1000 is log10 (2) rounded up;
142    add one for integer division truncation;
143    add one more for a minus sign if t is signed.  */
144 #define INT_STRLEN_BOUND(t) \
145  ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
146
147 #define TM_YEAR_BASE 1900
148
149 #ifndef __isleap
150 /* Nonzero if YEAR is a leap year (every 4 years,
151    except every 100th isn't, and every 400th is).  */
152 # define __isleap(year) \
153   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
154 #endif
155
156
157 #ifdef _LIBC
158 # define tzname __tzname
159 # define tzset __tzset
160 #endif
161
162 #if !HAVE_TM_GMTOFF
163 /* Portable standalone applications should supply a "time_r.h" that
164    declares a POSIX-compliant localtime_r, for the benefit of older
165    implementations that lack localtime_r or have a nonstandard one.
166    Similarly for gmtime_r.  See the gnulib time_r module for one way
167    to implement this.  */
168 # include "time_r.h"
169 # undef __gmtime_r
170 # undef __localtime_r
171 # define __gmtime_r gmtime_r
172 # define __localtime_r localtime_r
173 #endif
174
175
176 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
177 /* Some systems lack the `memset' function and we don't want to
178    introduce additional dependencies.  */
179 /* The SGI compiler reportedly barfs on the trailing null
180    if we use a string constant as the initializer.  28 June 1997, rms.  */
181 static const CHAR_T spaces[16] = /* "                " */
182 {
183   L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
184   L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
185 };
186 static const CHAR_T zeroes[16] = /* "0000000000000000" */
187 {
188   L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
189   L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
190 };
191
192 # define memset_space(P, Len) \
193   do {                                                                        \
194     int _len = (Len);                                                         \
195                                                                               \
196     do                                                                        \
197       {                                                                       \
198         int _this = _len > 16 ? 16 : _len;                                    \
199         (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T));                 \
200         _len -= _this;                                                        \
201       }                                                                       \
202     while (_len > 0);                                                         \
203   } while (0)
204
205 # define memset_zero(P, Len) \
206   do {                                                                        \
207     int _len = (Len);                                                         \
208                                                                               \
209     do                                                                        \
210       {                                                                       \
211         int _this = _len > 16 ? 16 : _len;                                    \
212         (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T));                 \
213         _len -= _this;                                                        \
214       }                                                                       \
215     while (_len > 0);                                                         \
216   } while (0)
217 #else
218 # ifdef COMPILE_WIDE
219 #  define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
220 #  define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
221 # else
222 #  define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
223 #  define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
224 # endif
225 #endif
226
227 #define add(n, f)                                                             \
228   do                                                                          \
229     {                                                                         \
230       int _n = (n);                                                           \
231       int _delta = width - _n;                                                \
232       int _incr = _n + (_delta > 0 ? _delta : 0);                             \
233       if ((size_t) _incr >= maxsize - i)                                      \
234         return 0;                                                             \
235       if (p)                                                                  \
236         {                                                                     \
237           if (_delta > 0)                                                     \
238             {                                                                 \
239               if (pad == L_('0'))                                             \
240                 memset_zero (p, _delta);                                      \
241               else                                                            \
242                 memset_space (p, _delta);                                     \
243             }                                                                 \
244           f;                                                                  \
245           p += _n;                                                            \
246         }                                                                     \
247       i += _incr;                                                             \
248     } while (0)
249
250 #define cpy(n, s) \
251     add ((n),                                                                 \
252          if (to_lowcase)                                                      \
253            memcpy_lowcase (p, (s), _n LOCALE_ARG);                            \
254          else if (to_uppcase)                                                 \
255            memcpy_uppcase (p, (s), _n LOCALE_ARG);                            \
256          else                                                                 \
257            MEMCPY ((PTR) p, (const PTR) (s), _n))
258
259 #ifdef COMPILE_WIDE
260 # ifndef USE_IN_EXTENDED_LOCALE_MODEL
261 #  undef __mbsrtowcs_l
262 #  define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
263 # endif
264 # define widen(os, ws, l) \
265   {                                                                           \
266     mbstate_t __st;                                                           \
267     const char *__s = os;                                                     \
268     memset (&__st, '\0', sizeof (__st));                                      \
269     l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc);                            \
270     ws = alloca ((l + 1) * sizeof (wchar_t));                                 \
271     (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc);                           \
272   }
273 #endif
274
275
276 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
277 /* We use this code also for the extended locale handling where the
278    function gets as an additional argument the locale which has to be
279    used.  To access the values we have to redefine the _NL_CURRENT
280    macro.  */
281 # define strftime               __strftime_l
282 # define wcsftime               __wcsftime_l
283 # undef _NL_CURRENT
284 # define _NL_CURRENT(category, item) \
285   (current->values[_NL_ITEM_INDEX (item)].string)
286 # define LOCALE_PARAM , loc
287 # define LOCALE_ARG , loc
288 # define LOCALE_PARAM_DECL  __locale_t loc;
289 # define LOCALE_PARAM_PROTO , __locale_t loc
290 # define HELPER_LOCALE_ARG  , current
291 #else
292 # define LOCALE_PARAM
293 # define LOCALE_PARAM_PROTO
294 # define LOCALE_ARG
295 # define LOCALE_PARAM_DECL
296 # ifdef _LIBC
297 #  define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
298 # else
299 #  define HELPER_LOCALE_ARG
300 # endif
301 #endif
302
303 #ifdef COMPILE_WIDE
304 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
305 #  define TOUPPER(Ch, L) __towupper_l (Ch, L)
306 #  define TOLOWER(Ch, L) __towlower_l (Ch, L)
307 # else
308 #  define TOUPPER(Ch, L) towupper (Ch)
309 #  define TOLOWER(Ch, L) towlower (Ch)
310 # endif
311 #else
312 # ifdef _LIBC
313 #  ifdef USE_IN_EXTENDED_LOCALE_MODEL
314 #   define TOUPPER(Ch, L) __toupper_l (Ch, L)
315 #   define TOLOWER(Ch, L) __tolower_l (Ch, L)
316 #  else
317 #   define TOUPPER(Ch, L) toupper (Ch)
318 #   define TOLOWER(Ch, L) tolower (Ch)
319 #  endif
320 # else
321 #  define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
322 #  define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
323 # endif
324 #endif
325 /* We don't use `isdigit' here since the locale dependent
326    interpretation is not what we want here.  We only need to accept
327    the arabic digits in the ASCII range.  One day there is perhaps a
328    more reliable way to accept other sets of digits.  */
329 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
330
331 static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
332                                size_t len LOCALE_PARAM_PROTO) __THROW;
333
334 static CHAR_T *
335 memcpy_lowcase (dest, src, len LOCALE_PARAM)
336      CHAR_T *dest;
337      const CHAR_T *src;
338      size_t len;
339      LOCALE_PARAM_DECL
340 {
341   while (len-- > 0)
342     dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
343   return dest;
344 }
345
346 static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
347                                size_t len LOCALE_PARAM_PROTO) __THROW;
348
349 static CHAR_T *
350 memcpy_uppcase (dest, src, len LOCALE_PARAM)
351      CHAR_T *dest;
352      const CHAR_T *src;
353      size_t len;
354      LOCALE_PARAM_DECL
355 {
356   while (len-- > 0)
357     dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
358   return dest;
359 }
360
361
362 #if ! HAVE_TM_GMTOFF
363 /* Yield the difference between *A and *B,
364    measured in seconds, ignoring leap seconds.  */
365 # define tm_diff ftime_tm_diff
366 static int tm_diff (const struct tm *, const struct tm *) __THROW;
367 static int
368 tm_diff (a, b)
369      const struct tm *a;
370      const struct tm *b;
371 {
372   /* Compute intervening leap days correctly even if year is negative.
373      Take care to avoid int overflow in leap day calculations,
374      but it's OK to assume that A and B are close to each other.  */
375   int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
376   int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
377   int a100 = a4 / 25 - (a4 % 25 < 0);
378   int b100 = b4 / 25 - (b4 % 25 < 0);
379   int a400 = a100 >> 2;
380   int b400 = b100 >> 2;
381   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
382   int years = a->tm_year - b->tm_year;
383   int days = (365 * years + intervening_leap_days
384               + (a->tm_yday - b->tm_yday));
385   return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
386                 + (a->tm_min - b->tm_min))
387           + (a->tm_sec - b->tm_sec));
388 }
389 #endif /* ! HAVE_TM_GMTOFF */
390
391
392
393 /* The number of days from the first day of the first ISO week of this
394    year to the year day YDAY with week day WDAY.  ISO weeks start on
395    Monday; the first ISO week has the year's first Thursday.  YDAY may
396    be as small as YDAY_MINIMUM.  */
397 #define ISO_WEEK_START_WDAY 1 /* Monday */
398 #define ISO_WEEK1_WDAY 4 /* Thursday */
399 #define YDAY_MINIMUM (-366)
400 static int iso_week_days (int, int) __THROW;
401 #ifdef __GNUC__
402 __inline__
403 #endif
404 static int
405 iso_week_days (yday, wday)
406      int yday;
407      int wday;
408 {
409   /* Add enough to the first operand of % to make it nonnegative.  */
410   int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
411   return (yday
412           - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
413           + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
414 }
415
416
417 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
418 static CHAR_T const weekday_name[][10] =
419   {
420     L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
421     L_("Thursday"), L_("Friday"), L_("Saturday")
422   };
423 static CHAR_T const month_name[][10] =
424   {
425     L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
426     L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
427     L_("November"), L_("December")
428   };
429 #endif
430
431
432 #ifdef emacs
433 # define my_strftime emacs_strftimeu
434 # define ut_argument , ut
435 # define ut_argument_spec int ut;
436 # define ut_argument_spec_iso , int ut
437 #else
438 # ifdef COMPILE_WIDE
439 #  define my_strftime wcsftime
440 #  define nl_get_alt_digit _nl_get_walt_digit
441 # else
442 #  define my_strftime strftime
443 #  define nl_get_alt_digit _nl_get_alt_digit
444 # endif
445 # define ut_argument
446 # define ut_argument_spec
447 # define ut_argument_spec_iso
448 /* We don't have this information in general.  */
449 # define ut 0
450 #endif
451
452 static size_t __strftime_internal (CHAR_T *, size_t, const CHAR_T *,
453                                    const struct tm *, bool *
454                                    ut_argument_spec_iso
455                                    LOCALE_PARAM_PROTO) __THROW;
456
457 /* Write information from TP into S according to the format
458    string FORMAT, writing no more that MAXSIZE characters
459    (including the terminating '\0') and returning number of
460    characters written.  If S is NULL, nothing will be written
461    anywhere, so to determine how many characters would be
462    written, use NULL for S and (size_t) UINT_MAX for MAXSIZE.  */
463
464 size_t
465 my_strftime (s, maxsize, format, tp ut_argument LOCALE_PARAM)
466      CHAR_T *s;
467      size_t maxsize;
468      const CHAR_T *format;
469      const struct tm *tp;
470      ut_argument_spec
471      LOCALE_PARAM_DECL
472 {
473 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
474   /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
475      Work around this bug by copying *tp before it might be munged.  */
476   struct tm tmcopy;
477   tmcopy = *tp;
478   tp = &tmcopy;
479 #endif
480   bool tzset_called = false;
481   return __strftime_internal (s, maxsize, format, tp, &tzset_called
482                               ut_argument LOCALE_ARG);
483 }
484 #ifdef _LIBC
485 libc_hidden_def (my_strftime)
486 #endif
487
488 static size_t
489 __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
490                      LOCALE_PARAM)
491       CHAR_T *s;
492       size_t maxsize;
493       const CHAR_T *format;
494       const struct tm *tp;
495       bool *tzset_called;
496       ut_argument_spec
497       LOCALE_PARAM_DECL
498 {
499 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
500   struct __locale_data *const current = loc->__locales[LC_TIME];
501 #endif
502
503   int hour12 = tp->tm_hour;
504 #ifdef _NL_CURRENT
505   /* We cannot make the following values variables since we must delay
506      the evaluation of these values until really needed since some
507      expressions might not be valid in every situation.  The `struct tm'
508      might be generated by a strptime() call that initialized
509      only a few elements.  Dereference the pointers only if the format
510      requires this.  Then it is ok to fail if the pointers are invalid.  */
511 # define a_wkday \
512   ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
513 # define f_wkday \
514   ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
515 # define a_month \
516   ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
517 # define f_month \
518   ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
519 # define ampm \
520   ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11                    \
521                                  ? NLW(PM_STR) : NLW(AM_STR)))
522
523 # define aw_len STRLEN (a_wkday)
524 # define am_len STRLEN (a_month)
525 # define ap_len STRLEN (ampm)
526 #else
527 # if !HAVE_STRFTIME
528 #  define f_wkday (weekday_name[tp->tm_wday])
529 #  define f_month (month_name[tp->tm_mon])
530 #  define a_wkday f_wkday
531 #  define a_month f_month
532 #  define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
533
534   size_t aw_len = 3;
535   size_t am_len = 3;
536   size_t ap_len = 2;
537 # endif
538 #endif
539   const char *zone;
540   size_t i = 0;
541   CHAR_T *p = s;
542   const CHAR_T *f;
543 #if DO_MULTIBYTE && !defined COMPILE_WIDE
544   const char *format_end = NULL;
545 #endif
546
547   zone = NULL;
548 #if HAVE_TM_ZONE
549   /* The POSIX test suite assumes that setting
550      the environment variable TZ to a new value before calling strftime()
551      will influence the result (the %Z format) even if the information in
552      TP is computed with a totally different time zone.
553      This is bogus: though POSIX allows bad behavior like this,
554      POSIX does not require it.  Do the right thing instead.  */
555   zone = (const char *) tp->tm_zone;
556 #endif
557 #if HAVE_TZNAME
558   if (ut)
559     {
560       if (! (zone && *zone))
561         zone = "GMT";
562     }
563 #endif
564
565   if (hour12 > 12)
566     hour12 -= 12;
567   else
568     if (hour12 == 0)
569       hour12 = 12;
570
571   for (f = format; *f != '\0'; ++f)
572     {
573       int pad = 0;              /* Padding for number ('-', '_', or 0).  */
574       int modifier;             /* Field modifier ('E', 'O', or 0).  */
575       int digits;               /* Max digits for numeric format.  */
576       int number_value;         /* Numeric value to be printed.  */
577       int negative_number;      /* 1 if the number is negative.  */
578       const CHAR_T *subfmt;
579       CHAR_T *bufp;
580       CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
581                       ? INT_STRLEN_BOUND (time_t)
582                       : INT_STRLEN_BOUND (int))];
583       int width = -1;
584       int to_lowcase = 0;
585       int to_uppcase = 0;
586       int change_case = 0;
587       int format_char;
588
589 #if DO_MULTIBYTE && !defined COMPILE_WIDE
590       switch (*f)
591         {
592         case L_('%'):
593           break;
594
595         case L_('\b'): case L_('\t'): case L_('\n'):
596         case L_('\v'): case L_('\f'): case L_('\r'):
597         case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
598         case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
599         case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
600         case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
601         case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
602         case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
603         case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
604         case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
605         case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
606         case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
607         case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
608         case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
609         case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
610         case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
611         case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
612         case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
613         case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
614         case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
615         case L_('~'):
616           /* The C Standard requires these 98 characters (plus '%') to
617              be in the basic execution character set.  None of these
618              characters can start a multibyte sequence, so they need
619              not be analyzed further.  */
620           add (1, *p = *f);
621           continue;
622
623         default:
624           /* Copy this multibyte sequence until we reach its end, find
625              an error, or come back to the initial shift state.  */
626           {
627             mbstate_t mbstate = mbstate_zero;
628             size_t len = 0;
629             size_t fsize;
630
631             if (! format_end)
632               format_end = f + strlen (f) + 1;
633             fsize = format_end - f;
634
635             do
636               {
637                 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
638
639                 if (bytes == 0)
640                   break;
641
642                 if (bytes == (size_t) -2)
643                   {
644                     len += strlen (f + len);
645                     break;
646                   }
647
648                 if (bytes == (size_t) -1)
649                   {
650                     len++;
651                     break;
652                   }
653
654                 len += bytes;
655               }
656             while (! mbsinit (&mbstate));
657
658             cpy (len, f);
659             f += len - 1;
660             continue;
661           }
662         }
663
664 #else /* ! DO_MULTIBYTE */
665
666       /* Either multibyte encodings are not supported, they are
667          safe for formats, so any non-'%' byte can be copied through,
668          or this is the wide character version.  */
669       if (*f != L_('%'))
670         {
671           add (1, *p = *f);
672           continue;
673         }
674
675 #endif /* ! DO_MULTIBYTE */
676
677       /* Check for flags that can modify a format.  */
678       while (1)
679         {
680           switch (*++f)
681             {
682               /* This influences the number formats.  */
683             case L_('_'):
684             case L_('-'):
685             case L_('0'):
686               pad = *f;
687               continue;
688
689               /* This changes textual output.  */
690             case L_('^'):
691               to_uppcase = 1;
692               continue;
693             case L_('#'):
694               change_case = 1;
695               continue;
696
697             default:
698               break;
699             }
700           break;
701         }
702
703       /* As a GNU extension we allow to specify the field width.  */
704       if (ISDIGIT (*f))
705         {
706           width = 0;
707           do
708             {
709               if (width > INT_MAX / 10
710                   || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
711                 /* Avoid overflow.  */
712                 width = INT_MAX;
713               else
714                 {
715                   width *= 10;
716                   width += *f - L_('0');
717                 }
718               ++f;
719             }
720           while (ISDIGIT (*f));
721         }
722
723       /* Check for modifiers.  */
724       switch (*f)
725         {
726         case L_('E'):
727         case L_('O'):
728           modifier = *f++;
729           break;
730
731         default:
732           modifier = 0;
733           break;
734         }
735
736       /* Now do the specified format.  */
737       format_char = *f;
738       switch (format_char)
739         {
740 #define DO_NUMBER(d, v) \
741           digits = d > width ? d : width;                                     \
742           number_value = v; goto do_number
743 #define DO_NUMBER_SPACEPAD(d, v) \
744           digits = d > width ? d : width;                                     \
745           number_value = v; goto do_number_spacepad
746
747         case L_('%'):
748           if (modifier != 0)
749             goto bad_format;
750           add (1, *p = *f);
751           break;
752
753         case L_('a'):
754           if (modifier != 0)
755             goto bad_format;
756           if (change_case)
757             {
758               to_uppcase = 1;
759               to_lowcase = 0;
760             }
761 #if defined _NL_CURRENT || !HAVE_STRFTIME
762           cpy (aw_len, a_wkday);
763           break;
764 #else
765           goto underlying_strftime;
766 #endif
767
768         case 'A':
769           if (modifier != 0)
770             goto bad_format;
771           if (change_case)
772             {
773               to_uppcase = 1;
774               to_lowcase = 0;
775             }
776 #if defined _NL_CURRENT || !HAVE_STRFTIME
777           cpy (STRLEN (f_wkday), f_wkday);
778           break;
779 #else
780           goto underlying_strftime;
781 #endif
782
783         case L_('b'):
784         case L_('h'):
785           if (change_case)
786             {
787               to_uppcase = 1;
788               to_lowcase = 0;
789             }
790           if (modifier != 0)
791             goto bad_format;
792 #if defined _NL_CURRENT || !HAVE_STRFTIME
793           cpy (am_len, a_month);
794           break;
795 #else
796           goto underlying_strftime;
797 #endif
798
799         case L_('B'):
800           if (modifier != 0)
801             goto bad_format;
802           if (change_case)
803             {
804               to_uppcase = 1;
805               to_lowcase = 0;
806             }
807 #if defined _NL_CURRENT || !HAVE_STRFTIME
808           cpy (STRLEN (f_month), f_month);
809           break;
810 #else
811           goto underlying_strftime;
812 #endif
813
814         case L_('c'):
815           if (modifier == L_('O'))
816             goto bad_format;
817 #ifdef _NL_CURRENT
818           if (! (modifier == 'E'
819                  && (*(subfmt =
820                        (const CHAR_T *) _NL_CURRENT (LC_TIME,
821                                                      NLW(ERA_D_T_FMT)))
822                      != '\0')))
823             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
824 #else
825 # if HAVE_STRFTIME
826           goto underlying_strftime;
827 # else
828           subfmt = L_("%a %b %e %H:%M:%S %Y");
829 # endif
830 #endif
831
832         subformat:
833           {
834             CHAR_T *old_start = p;
835             size_t len = __strftime_internal (NULL, (size_t) -1, subfmt,
836                                               tp, tzset_called ut_argument
837                                               LOCALE_ARG);
838             add (len, __strftime_internal (p, maxsize - i, subfmt,
839                                            tp, tzset_called ut_argument
840                                            LOCALE_ARG));
841
842             if (to_uppcase)
843               while (old_start < p)
844                 {
845                   *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
846                   ++old_start;
847                 }
848           }
849           break;
850
851 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
852         underlying_strftime:
853           {
854             /* The relevant information is available only via the
855                underlying strftime implementation, so use that.  */
856             char ufmt[4];
857             char *u = ufmt;
858             char ubuf[1024]; /* enough for any single format in practice */
859             size_t len;
860             /* Make sure we're calling the actual underlying strftime.
861                In some cases, config.h contains something like
862                "#define strftime rpl_strftime".  */
863 # ifdef strftime
864 #  undef strftime
865             size_t strftime ();
866 # endif
867
868             *u++ = '%';
869             if (modifier != 0)
870               *u++ = modifier;
871             *u++ = format_char;
872             *u = '\0';
873             len = strftime (ubuf, sizeof ubuf, ufmt, tp);
874             if (len == 0 && ubuf[0] != '\0')
875               return 0;
876             cpy (len, ubuf);
877           }
878           break;
879 #endif
880
881         case L_('C'):
882           if (modifier == L_('E'))
883             {
884 #if HAVE_STRUCT_ERA_ENTRY
885               struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
886               if (era)
887                 {
888 # ifdef COMPILE_WIDE
889                   size_t len = __wcslen (era->era_wname);
890                   cpy (len, era->era_wname);
891 # else
892                   size_t len = strlen (era->era_name);
893                   cpy (len, era->era_name);
894 # endif
895                   break;
896                 }
897 #else
898 # if HAVE_STRFTIME
899               goto underlying_strftime;
900 # endif
901 #endif
902             }
903
904           {
905             int year = tp->tm_year + TM_YEAR_BASE;
906             DO_NUMBER (1, year / 100 - (year % 100 < 0));
907           }
908
909         case L_('x'):
910           if (modifier == L_('O'))
911             goto bad_format;
912 #ifdef _NL_CURRENT
913           if (! (modifier == L_('E')
914                  && (*(subfmt =
915                        (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
916                      != L_('\0'))))
917             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
918           goto subformat;
919 #else
920 # if HAVE_STRFTIME
921           goto underlying_strftime;
922 # else
923           /* Fall through.  */
924 # endif
925 #endif
926         case L_('D'):
927           if (modifier != 0)
928             goto bad_format;
929           subfmt = L_("%m/%d/%y");
930           goto subformat;
931
932         case L_('d'):
933           if (modifier == L_('E'))
934             goto bad_format;
935
936           DO_NUMBER (2, tp->tm_mday);
937
938         case L_('e'):
939           if (modifier == L_('E'))
940             goto bad_format;
941
942           DO_NUMBER_SPACEPAD (2, tp->tm_mday);
943
944           /* All numeric formats set DIGITS and NUMBER_VALUE and then
945              jump to one of these two labels.  */
946
947         do_number_spacepad:
948           /* Force `_' flag unless overwritten by `0' or '-' flag.  */
949           if (pad != L_('0') && pad != L_('-'))
950             pad = L_('_');
951
952         do_number:
953           /* Format the number according to the MODIFIER flag.  */
954
955           if (modifier == L_('O') && 0 <= number_value)
956             {
957 #ifdef _NL_CURRENT
958               /* Get the locale specific alternate representation of
959                  the number NUMBER_VALUE.  If none exist NULL is returned.  */
960               const CHAR_T *cp = nl_get_alt_digit (number_value
961                                                    HELPER_LOCALE_ARG);
962
963               if (cp != NULL)
964                 {
965                   size_t digitlen = STRLEN (cp);
966                   if (digitlen != 0)
967                     {
968                       cpy (digitlen, cp);
969                       break;
970                     }
971                 }
972 #else
973 # if HAVE_STRFTIME
974               goto underlying_strftime;
975 # endif
976 #endif
977             }
978           {
979             unsigned int u = number_value;
980
981             bufp = buf + sizeof (buf) / sizeof (buf[0]);
982             negative_number = number_value < 0;
983
984             if (negative_number)
985               u = -u;
986
987             do
988               *--bufp = u % 10 + L_('0');
989             while ((u /= 10) != 0);
990           }
991
992         do_number_sign_and_padding:
993           if (negative_number)
994             *--bufp = L_('-');
995
996           if (pad != L_('-'))
997             {
998               int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
999                                       - bufp);
1000
1001               if (padding > 0)
1002                 {
1003                   if (pad == L_('_'))
1004                     {
1005                       if ((size_t) padding >= maxsize - i)
1006                         return 0;
1007
1008                       if (p)
1009                         memset_space (p, padding);
1010                       i += padding;
1011                       width = width > padding ? width - padding : 0;
1012                     }
1013                   else
1014                     {
1015                       if ((size_t) digits >= maxsize - i)
1016                         return 0;
1017
1018                       if (negative_number)
1019                         {
1020                           ++bufp;
1021
1022                           if (p)
1023                             *p++ = L_('-');
1024                           ++i;
1025                         }
1026
1027                       if (p)
1028                         memset_zero (p, padding);
1029                       i += padding;
1030                       width = 0;
1031                     }
1032                 }
1033             }
1034
1035           cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1036           break;
1037
1038         case L_('F'):
1039           if (modifier != 0)
1040             goto bad_format;
1041           subfmt = L_("%Y-%m-%d");
1042           goto subformat;
1043
1044         case L_('H'):
1045           if (modifier == L_('E'))
1046             goto bad_format;
1047
1048           DO_NUMBER (2, tp->tm_hour);
1049
1050         case L_('I'):
1051           if (modifier == L_('E'))
1052             goto bad_format;
1053
1054           DO_NUMBER (2, hour12);
1055
1056         case L_('k'):           /* GNU extension.  */
1057           if (modifier == L_('E'))
1058             goto bad_format;
1059
1060           DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1061
1062         case L_('l'):           /* GNU extension.  */
1063           if (modifier == L_('E'))
1064             goto bad_format;
1065
1066           DO_NUMBER_SPACEPAD (2, hour12);
1067
1068         case L_('j'):
1069           if (modifier == L_('E'))
1070             goto bad_format;
1071
1072           DO_NUMBER (3, 1 + tp->tm_yday);
1073
1074         case L_('M'):
1075           if (modifier == L_('E'))
1076             goto bad_format;
1077
1078           DO_NUMBER (2, tp->tm_min);
1079
1080         case L_('m'):
1081           if (modifier == L_('E'))
1082             goto bad_format;
1083
1084           DO_NUMBER (2, tp->tm_mon + 1);
1085
1086         case L_('n'):
1087           add (1, *p = L_('\n'));
1088           break;
1089
1090         case L_('P'):
1091           to_lowcase = 1;
1092 #if !defined _NL_CURRENT && HAVE_STRFTIME
1093           format_char = L_('p');
1094 #endif
1095           /* FALLTHROUGH */
1096
1097         case L_('p'):
1098           if (change_case)
1099             {
1100               to_uppcase = 0;
1101               to_lowcase = 1;
1102             }
1103 #if defined _NL_CURRENT || !HAVE_STRFTIME
1104           cpy (ap_len, ampm);
1105           break;
1106 #else
1107           goto underlying_strftime;
1108 #endif
1109
1110         case L_('R'):
1111           subfmt = L_("%H:%M");
1112           goto subformat;
1113
1114         case L_('r'):
1115 #if !defined _NL_CURRENT && HAVE_STRFTIME
1116           goto underlying_strftime;
1117 #else
1118 # ifdef _NL_CURRENT
1119           if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1120                                                        NLW(T_FMT_AMPM)))
1121               == L_('\0'))
1122 # endif
1123             subfmt = L_("%I:%M:%S %p");
1124           goto subformat;
1125 #endif
1126
1127         case L_('S'):
1128           if (modifier == L_('E'))
1129             goto bad_format;
1130
1131           DO_NUMBER (2, tp->tm_sec);
1132
1133         case L_('s'):           /* GNU extension.  */
1134           {
1135             struct tm ltm;
1136             time_t t;
1137
1138             ltm = *tp;
1139             t = mktime (&ltm);
1140
1141             /* Generate string value for T using time_t arithmetic;
1142                this works even if sizeof (long) < sizeof (time_t).  */
1143
1144             bufp = buf + sizeof (buf) / sizeof (buf[0]);
1145             negative_number = t < 0;
1146
1147             do
1148               {
1149                 int d = t % 10;
1150                 t /= 10;
1151
1152                 if (negative_number)
1153                   {
1154                     d = -d;
1155
1156                     /* Adjust if division truncates to minus infinity.  */
1157                     if (0 < -1 % 10 && d < 0)
1158                       {
1159                         t++;
1160                         d += 10;
1161                       }
1162                   }
1163
1164                 *--bufp = d + L_('0');
1165               }
1166             while (t != 0);
1167
1168             digits = 1;
1169             goto do_number_sign_and_padding;
1170           }
1171
1172         case L_('X'):
1173           if (modifier == L_('O'))
1174             goto bad_format;
1175 #ifdef _NL_CURRENT
1176           if (! (modifier == L_('E')
1177                  && (*(subfmt =
1178                        (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1179                      != L_('\0'))))
1180             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1181           goto subformat;
1182 #else
1183 # if HAVE_STRFTIME
1184           goto underlying_strftime;
1185 # else
1186           /* Fall through.  */
1187 # endif
1188 #endif
1189         case L_('T'):
1190           subfmt = L_("%H:%M:%S");
1191           goto subformat;
1192
1193         case L_('t'):
1194           add (1, *p = L_('\t'));
1195           break;
1196
1197         case L_('u'):
1198           DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1199
1200         case L_('U'):
1201           if (modifier == L_('E'))
1202             goto bad_format;
1203
1204           DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1205
1206         case L_('V'):
1207         case L_('g'):
1208         case L_('G'):
1209           if (modifier == L_('E'))
1210             goto bad_format;
1211           {
1212             int year = tp->tm_year + TM_YEAR_BASE;
1213             int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1214
1215             if (days < 0)
1216               {
1217                 /* This ISO week belongs to the previous year.  */
1218                 year--;
1219                 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1220                                       tp->tm_wday);
1221               }
1222             else
1223               {
1224                 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1225                                        tp->tm_wday);
1226                 if (0 <= d)
1227                   {
1228                     /* This ISO week belongs to the next year.  */
1229                     year++;
1230                     days = d;
1231                   }
1232               }
1233
1234             switch (*f)
1235               {
1236               case L_('g'):
1237                 DO_NUMBER (2, (year % 100 + 100) % 100);
1238
1239               case L_('G'):
1240                 DO_NUMBER (1, year);
1241
1242               default:
1243                 DO_NUMBER (2, days / 7 + 1);
1244               }
1245           }
1246
1247         case L_('W'):
1248           if (modifier == L_('E'))
1249             goto bad_format;
1250
1251           DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1252
1253         case L_('w'):
1254           if (modifier == L_('E'))
1255             goto bad_format;
1256
1257           DO_NUMBER (1, tp->tm_wday);
1258
1259         case L_('Y'):
1260           if (modifier == 'E')
1261             {
1262 #if HAVE_STRUCT_ERA_ENTRY
1263               struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1264               if (era)
1265                 {
1266 # ifdef COMPILE_WIDE
1267                   subfmt = era->era_wformat;
1268 # else
1269                   subfmt = era->era_format;
1270 # endif
1271                   goto subformat;
1272                 }
1273 #else
1274 # if HAVE_STRFTIME
1275               goto underlying_strftime;
1276 # endif
1277 #endif
1278             }
1279           if (modifier == L_('O'))
1280             goto bad_format;
1281           else
1282             DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1283
1284         case L_('y'):
1285           if (modifier == L_('E'))
1286             {
1287 #if HAVE_STRUCT_ERA_ENTRY
1288               struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1289               if (era)
1290                 {
1291                   int delta = tp->tm_year - era->start_date[0];
1292                   DO_NUMBER (1, (era->offset
1293                                  + delta * era->absolute_direction));
1294                 }
1295 #else
1296 # if HAVE_STRFTIME
1297               goto underlying_strftime;
1298 # endif
1299 #endif
1300             }
1301           DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1302
1303         case L_('Z'):
1304           if (change_case)
1305             {
1306               to_uppcase = 0;
1307               to_lowcase = 1;
1308             }
1309
1310 #if HAVE_TZNAME
1311           /* The tzset() call might have changed the value.  */
1312           if (!(zone && *zone) && tp->tm_isdst >= 0)
1313             {
1314               /* POSIX.1 requires that local time zone information is used as
1315                  though strftime called tzset.  */
1316 # if HAVE_TZSET
1317               if (!*tzset_called)
1318                 {
1319                   tzset ();
1320                   *tzset_called = true;
1321                 }
1322 # endif
1323               zone = tzname[tp->tm_isdst];
1324             }
1325 #endif
1326           if (! zone)
1327             zone = "";
1328
1329 #ifdef COMPILE_WIDE
1330           {
1331             /* The zone string is always given in multibyte form.  We have
1332                to transform it first.  */
1333             wchar_t *wczone;
1334             size_t len;
1335             widen (zone, wczone, len);
1336             cpy (len, wczone);
1337           }
1338 #else
1339           cpy (strlen (zone), zone);
1340 #endif
1341           break;
1342
1343         case L_('z'):
1344           if (tp->tm_isdst < 0)
1345             break;
1346
1347           {
1348             int diff;
1349 #if HAVE_TM_GMTOFF
1350             diff = tp->tm_gmtoff;
1351 #else
1352             if (ut)
1353               diff = 0;
1354             else
1355               {
1356                 struct tm gtm;
1357                 struct tm ltm;
1358                 time_t lt;
1359
1360                 /* POSIX.1 requires that local time zone information is used as
1361                    though strftime called tzset.  */
1362 # if HAVE_TZSET
1363                 if (!*tzset_called)
1364                   {
1365                     tzset ();
1366                     *tzset_called = true;
1367                   }
1368 # endif
1369
1370                 ltm = *tp;
1371                 lt = mktime (&ltm);
1372
1373                 if (lt == (time_t) -1)
1374                   {
1375                     /* mktime returns -1 for errors, but -1 is also a
1376                        valid time_t value.  Check whether an error really
1377                        occurred.  */
1378                     struct tm tm;
1379
1380                     if (! __localtime_r (&lt, &tm)
1381                         || ((ltm.tm_sec ^ tm.tm_sec)
1382                             | (ltm.tm_min ^ tm.tm_min)
1383                             | (ltm.tm_hour ^ tm.tm_hour)
1384                             | (ltm.tm_mday ^ tm.tm_mday)
1385                             | (ltm.tm_mon ^ tm.tm_mon)
1386                             | (ltm.tm_year ^ tm.tm_year)))
1387                       break;
1388                   }
1389
1390                 if (! __gmtime_r (&lt, &gtm))
1391                   break;
1392
1393                 diff = tm_diff (&ltm, &gtm);
1394               }
1395 #endif
1396
1397             if (diff < 0)
1398               {
1399                 add (1, *p = L_('-'));
1400                 diff = -diff;
1401               }
1402             else
1403               add (1, *p = L_('+'));
1404
1405             diff /= 60;
1406             DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1407           }
1408
1409         case L_('\0'):          /* GNU extension: % at end of format.  */
1410             --f;
1411             /* Fall through.  */
1412         default:
1413           /* Unknown format; output the format, including the '%',
1414              since this is most likely the right thing to do if a
1415              multibyte string has been misparsed.  */
1416         bad_format:
1417           {
1418             int flen;
1419             for (flen = 1; f[1 - flen] != L_('%'); flen++)
1420               continue;
1421             cpy (flen, &f[1 - flen]);
1422           }
1423           break;
1424         }
1425     }
1426
1427   if (p && maxsize != 0)
1428     *p = L_('\0');
1429   return i;
1430 }
1431
1432
1433 #ifdef emacs
1434 /* For Emacs we have a separate interface which corresponds to the normal
1435    strftime function and does not have the extra information whether the
1436    TP arguments comes from a `gmtime' call or not.  */
1437 size_t
1438 emacs_strftime (s, maxsize, format, tp)
1439       char *s;
1440       size_t maxsize;
1441       const char *format;
1442       const struct tm *tp;
1443 {
1444   return my_strftime (s, maxsize, format, tp, 0);
1445 }
1446 #endif
1447
1448 #if defined _LIBC && !defined COMPILE_WIDE
1449 weak_alias (__strftime_l, strftime_l)
1450 #endif