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