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