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