* strftime.c (my_strftime) [HAVE_STRFTIME && ! (_NL_CURRENT
[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             ubuf[0] = '\1';
780             len = strftime (ubuf, sizeof ubuf, ufmt, tp);
781             if (len == 0 && ubuf[0] != '\0')
782               return 0;
783             cpy (len, ubuf);
784           }
785           break;
786 #endif
787
788         case L_('C'):
789           if (modifier == L_('O'))
790             goto bad_format;
791           if (modifier == L_('E'))
792             {
793 #if HAVE_STRUCT_ERA_ENTRY
794               struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
795               if (era)
796                 {
797 # ifdef COMPILE_WIDE
798                   size_t len = __wcslen (era->era_wname);
799                   cpy (len, era->era_wname);
800 # else
801                   size_t len = strlen (era->era_name);
802                   cpy (len, era->era_name);
803 # endif
804                   break;
805                 }
806 #else
807 # if HAVE_STRFTIME
808               goto underlying_strftime;
809 # endif
810 #endif
811             }
812
813           {
814             int century = tp->tm_year / 100 + TM_YEAR_BASE / 100;
815             century -= tp->tm_year % 100 < 0 && 0 < century;
816             DO_SIGNED_NUMBER (2, tp->tm_year < - TM_YEAR_BASE, century);
817           }
818
819         case L_('x'):
820           if (modifier == L_('O'))
821             goto bad_format;
822 #ifdef _NL_CURRENT
823           if (! (modifier == L_('E')
824                  && (*(subfmt =
825                        (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
826                      != L_('\0'))))
827             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
828           goto subformat;
829 #else
830 # if HAVE_STRFTIME
831           goto underlying_strftime;
832 # else
833           /* Fall through.  */
834 # endif
835 #endif
836         case L_('D'):
837           if (modifier != 0)
838             goto bad_format;
839           subfmt = L_("%m/%d/%y");
840           goto subformat;
841
842         case L_('d'):
843           if (modifier == L_('E'))
844             goto bad_format;
845
846           DO_NUMBER (2, tp->tm_mday);
847
848         case L_('e'):
849           if (modifier == L_('E'))
850             goto bad_format;
851
852           DO_NUMBER_SPACEPAD (2, tp->tm_mday);
853
854           /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
855              and then jump to one of these three labels.  */
856
857         do_number_spacepad:
858           /* Force `_' flag unless overridden by `0' or `-' flag.  */
859           if (pad != L_('0') && pad != L_('-'))
860             pad = L_('_');
861
862         do_number:
863           /* Format NUMBER_VALUE according to the MODIFIER flag.  */
864           negative_number = number_value < 0;
865           u_number_value = number_value;
866
867         do_signed_number:
868           /* Format U_NUMBER_VALUE according to the MODIFIER flag.
869              NEGATIVE_NUMBER is nonzero if the original number was
870              negative; in this case it was converted directly to
871              unsigned int (i.e., modulo (UINT_MAX + 1)) without
872              negating it.  */
873           if (modifier == L_('O') && !negative_number)
874             {
875 #ifdef _NL_CURRENT
876               /* Get the locale specific alternate representation of
877                  the number.  If none exist NULL is returned.  */
878               const CHAR_T *cp = nl_get_alt_digit (u_number_value
879                                                    HELPER_LOCALE_ARG);
880
881               if (cp != NULL)
882                 {
883                   size_t digitlen = STRLEN (cp);
884                   if (digitlen != 0)
885                     {
886                       cpy (digitlen, cp);
887                       break;
888                     }
889                 }
890 #else
891 # if HAVE_STRFTIME
892               goto underlying_strftime;
893 # endif
894 #endif
895             }
896
897           bufp = buf + sizeof (buf) / sizeof (buf[0]);
898
899           if (negative_number)
900             u_number_value = - u_number_value;
901
902           do
903             {
904               *--bufp = u_number_value % 10 + L_('0');
905               u_number_value /= 10;
906             }
907           while (u_number_value != 0);
908
909           if (digits < width)
910             digits = width;
911
912         do_number_sign_and_padding:
913           if (negative_number)
914             *--bufp = L_('-');
915
916           if (pad != L_('-'))
917             {
918               int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
919                                       - bufp);
920
921               if (padding > 0)
922                 {
923                   if (pad == L_('_'))
924                     {
925                       if ((size_t) padding >= maxsize - i)
926                         return 0;
927
928                       if (p)
929                         memset_space (p, padding);
930                       i += padding;
931                       width = width > padding ? width - padding : 0;
932                     }
933                   else
934                     {
935                       if ((size_t) digits >= maxsize - i)
936                         return 0;
937
938                       if (negative_number)
939                         {
940                           ++bufp;
941
942                           if (p)
943                             *p++ = L_('-');
944                           ++i;
945                         }
946
947                       if (p)
948                         memset_zero (p, padding);
949                       i += padding;
950                       width = 0;
951                     }
952                 }
953             }
954
955           cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
956           break;
957
958         case L_('F'):
959           if (modifier != 0)
960             goto bad_format;
961           subfmt = L_("%Y-%m-%d");
962           goto subformat;
963
964         case L_('H'):
965           if (modifier == L_('E'))
966             goto bad_format;
967
968           DO_NUMBER (2, tp->tm_hour);
969
970         case L_('I'):
971           if (modifier == L_('E'))
972             goto bad_format;
973
974           DO_NUMBER (2, hour12);
975
976         case L_('k'):           /* GNU extension.  */
977           if (modifier == L_('E'))
978             goto bad_format;
979
980           DO_NUMBER_SPACEPAD (2, tp->tm_hour);
981
982         case L_('l'):           /* GNU extension.  */
983           if (modifier == L_('E'))
984             goto bad_format;
985
986           DO_NUMBER_SPACEPAD (2, hour12);
987
988         case L_('j'):
989           if (modifier == L_('E'))
990             goto bad_format;
991
992           DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
993
994         case L_('M'):
995           if (modifier == L_('E'))
996             goto bad_format;
997
998           DO_NUMBER (2, tp->tm_min);
999
1000         case L_('m'):
1001           if (modifier == L_('E'))
1002             goto bad_format;
1003
1004           DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
1005
1006 #ifndef _LIBC
1007         case L_('N'):           /* GNU extension.  */
1008           if (modifier == L_('E'))
1009             goto bad_format;
1010
1011           number_value = ns;
1012           if (width != -1)
1013             {
1014               /* Take an explicit width less than 9 as a precision.  */
1015               int j;
1016               for (j = width; j < 9; j++)
1017                 number_value /= 10;
1018             }
1019
1020           DO_NUMBER (9, number_value);
1021 #endif
1022
1023         case L_('n'):
1024           add (1, *p = L_('\n'));
1025           break;
1026
1027         case L_('P'):
1028           to_lowcase = true;
1029 #if !defined _NL_CURRENT && HAVE_STRFTIME
1030           format_char = L_('p');
1031 #endif
1032           /* FALLTHROUGH */
1033
1034         case L_('p'):
1035           if (change_case)
1036             {
1037               to_uppcase = false;
1038               to_lowcase = true;
1039             }
1040 #if defined _NL_CURRENT || !HAVE_STRFTIME
1041           cpy (ap_len, ampm);
1042           break;
1043 #else
1044           goto underlying_strftime;
1045 #endif
1046
1047         case L_('R'):
1048           subfmt = L_("%H:%M");
1049           goto subformat;
1050
1051         case L_('r'):
1052 #if !defined _NL_CURRENT && HAVE_STRFTIME
1053           goto underlying_strftime;
1054 #else
1055 # ifdef _NL_CURRENT
1056           if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1057                                                        NLW(T_FMT_AMPM)))
1058               == L_('\0'))
1059 # endif
1060             subfmt = L_("%I:%M:%S %p");
1061           goto subformat;
1062 #endif
1063
1064         case L_('S'):
1065           if (modifier == L_('E'))
1066             goto bad_format;
1067
1068           DO_NUMBER (2, tp->tm_sec);
1069
1070         case L_('s'):           /* GNU extension.  */
1071           {
1072             struct tm ltm;
1073             time_t t;
1074
1075             ltm = *tp;
1076             t = mktime (&ltm);
1077
1078             /* Generate string value for T using time_t arithmetic;
1079                this works even if sizeof (long) < sizeof (time_t).  */
1080
1081             bufp = buf + sizeof (buf) / sizeof (buf[0]);
1082             negative_number = t < 0;
1083
1084             do
1085               {
1086                 int d = t % 10;
1087                 t /= 10;
1088                 *--bufp = (negative_number ? -d : d) + L_('0');
1089               }
1090             while (t != 0);
1091
1092             digits = 1;
1093             goto do_number_sign_and_padding;
1094           }
1095
1096         case L_('X'):
1097           if (modifier == L_('O'))
1098             goto bad_format;
1099 #ifdef _NL_CURRENT
1100           if (! (modifier == L_('E')
1101                  && (*(subfmt =
1102                        (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1103                      != L_('\0'))))
1104             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1105           goto subformat;
1106 #else
1107 # if HAVE_STRFTIME
1108           goto underlying_strftime;
1109 # else
1110           /* Fall through.  */
1111 # endif
1112 #endif
1113         case L_('T'):
1114           subfmt = L_("%H:%M:%S");
1115           goto subformat;
1116
1117         case L_('t'):
1118           add (1, *p = L_('\t'));
1119           break;
1120
1121         case L_('u'):
1122           DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1123
1124         case L_('U'):
1125           if (modifier == L_('E'))
1126             goto bad_format;
1127
1128           DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1129
1130         case L_('V'):
1131         case L_('g'):
1132         case L_('G'):
1133           if (modifier == L_('E'))
1134             goto bad_format;
1135           {
1136             /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
1137                is a leap year, except that YEAR and YEAR - 1 both work
1138                correctly even when (tp->tm_year + TM_YEAR_BASE) would
1139                overflow.  */
1140             int year = (tp->tm_year
1141                         + (tp->tm_year < 0
1142                            ? TM_YEAR_BASE % 400
1143                            : TM_YEAR_BASE % 400 - 400));
1144             int year_adjust = 0;
1145             int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1146
1147             if (days < 0)
1148               {
1149                 /* This ISO week belongs to the previous year.  */
1150                 year_adjust = -1;
1151                 days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
1152                                       tp->tm_wday);
1153               }
1154             else
1155               {
1156                 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1157                                        tp->tm_wday);
1158                 if (0 <= d)
1159                   {
1160                     /* This ISO week belongs to the next year.  */
1161                     year_adjust = 1;
1162                     days = d;
1163                   }
1164               }
1165
1166             switch (*f)
1167               {
1168               case L_('g'):
1169                 {
1170                   int yy = (tp->tm_year % 100 + year_adjust) % 100;
1171                   DO_NUMBER (2, (0 <= yy
1172                                  ? yy
1173                                  : tp->tm_year < -TM_YEAR_BASE - year_adjust
1174                                  ? -yy
1175                                  : yy + 100));
1176                 }
1177
1178               case L_('G'):
1179                 DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
1180                                   (tp->tm_year + (unsigned int) TM_YEAR_BASE
1181                                    + year_adjust));
1182
1183               default:
1184                 DO_NUMBER (2, days / 7 + 1);
1185               }
1186           }
1187
1188         case L_('W'):
1189           if (modifier == L_('E'))
1190             goto bad_format;
1191
1192           DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1193
1194         case L_('w'):
1195           if (modifier == L_('E'))
1196             goto bad_format;
1197
1198           DO_NUMBER (1, tp->tm_wday);
1199
1200         case L_('Y'):
1201           if (modifier == 'E')
1202             {
1203 #if HAVE_STRUCT_ERA_ENTRY
1204               struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1205               if (era)
1206                 {
1207 # ifdef COMPILE_WIDE
1208                   subfmt = era->era_wformat;
1209 # else
1210                   subfmt = era->era_format;
1211 # endif
1212                   goto subformat;
1213                 }
1214 #else
1215 # if HAVE_STRFTIME
1216               goto underlying_strftime;
1217 # endif
1218 #endif
1219             }
1220           if (modifier == L_('O'))
1221             goto bad_format;
1222           else
1223             DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE,
1224                               tp->tm_year + (unsigned int) TM_YEAR_BASE);
1225
1226         case L_('y'):
1227           if (modifier == L_('E'))
1228             {
1229 #if HAVE_STRUCT_ERA_ENTRY
1230               struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1231               if (era)
1232                 {
1233                   int delta = tp->tm_year - era->start_date[0];
1234                   DO_NUMBER (1, (era->offset
1235                                  + delta * era->absolute_direction));
1236                 }
1237 #else
1238 # if HAVE_STRFTIME
1239               goto underlying_strftime;
1240 # endif
1241 #endif
1242             }
1243
1244           {
1245             int yy = tp->tm_year % 100;
1246             if (yy < 0)
1247               yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
1248             DO_NUMBER (2, yy);
1249           }
1250
1251         case L_('Z'):
1252           if (change_case)
1253             {
1254               to_uppcase = false;
1255               to_lowcase = true;
1256             }
1257
1258 #if HAVE_TZNAME
1259           /* The tzset() call might have changed the value.  */
1260           if (!(zone && *zone) && tp->tm_isdst >= 0)
1261             zone = tzname[tp->tm_isdst != 0];
1262 #endif
1263           if (! zone)
1264             zone = "";
1265
1266 #ifdef COMPILE_WIDE
1267           {
1268             /* The zone string is always given in multibyte form.  We have
1269                to transform it first.  */
1270             wchar_t *wczone;
1271             size_t len;
1272             widen (zone, wczone, len);
1273             cpy (len, wczone);
1274           }
1275 #else
1276           cpy (strlen (zone), zone);
1277 #endif
1278           break;
1279
1280         case L_('z'):
1281           if (tp->tm_isdst < 0)
1282             break;
1283
1284           {
1285             int diff;
1286 #if HAVE_TM_GMTOFF
1287             diff = tp->tm_gmtoff;
1288 #else
1289             if (ut)
1290               diff = 0;
1291             else
1292               {
1293                 struct tm gtm;
1294                 struct tm ltm;
1295                 time_t lt;
1296
1297                 ltm = *tp;
1298                 lt = mktime (&ltm);
1299
1300                 if (lt == (time_t) -1)
1301                   {
1302                     /* mktime returns -1 for errors, but -1 is also a
1303                        valid time_t value.  Check whether an error really
1304                        occurred.  */
1305                     struct tm tm;
1306
1307                     if (! __localtime_r (&lt, &tm)
1308                         || ((ltm.tm_sec ^ tm.tm_sec)
1309                             | (ltm.tm_min ^ tm.tm_min)
1310                             | (ltm.tm_hour ^ tm.tm_hour)
1311                             | (ltm.tm_mday ^ tm.tm_mday)
1312                             | (ltm.tm_mon ^ tm.tm_mon)
1313                             | (ltm.tm_year ^ tm.tm_year)))
1314                       break;
1315                   }
1316
1317                 if (! __gmtime_r (&lt, &gtm))
1318                   break;
1319
1320                 diff = tm_diff (&ltm, &gtm);
1321               }
1322 #endif
1323
1324             if (diff < 0)
1325               {
1326                 add (1, *p = L_('-'));
1327                 diff = -diff;
1328               }
1329             else
1330               add (1, *p = L_('+'));
1331
1332             diff /= 60;
1333             DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1334           }
1335
1336         case L_('\0'):          /* GNU extension: % at end of format.  */
1337             --f;
1338             /* Fall through.  */
1339         default:
1340           /* Unknown format; output the format, including the '%',
1341              since this is most likely the right thing to do if a
1342              multibyte string has been misparsed.  */
1343         bad_format:
1344           {
1345             int flen;
1346             for (flen = 1; f[1 - flen] != L_('%'); flen++)
1347               continue;
1348             cpy (flen, &f[1 - flen]);
1349           }
1350           break;
1351         }
1352     }
1353
1354   if (p && maxsize != 0)
1355     *p = L_('\0');
1356   return i;
1357 }
1358 #ifdef _LIBC
1359 libc_hidden_def (my_strftime)
1360 #endif
1361
1362
1363 #ifdef emacs
1364 /* For Emacs we have a separate interface which corresponds to the normal
1365    strftime function plus the ut argument, but without the ns argument.  */
1366 size_t
1367 emacs_strftimeu (char *s, size_t maxsize, const char *format,
1368                  const struct tm *tp, int ut)
1369 {
1370   return my_strftime (s, maxsize, format, tp, ut, 0);
1371 }
1372 #endif