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