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