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