(my_strftime): Prepend space to format so that we can
[pspp] / lib / strftime.c
1 /* Copyright (C) 1991-1999, 2000, 2001, 2003, 2004, 2005 Free Software
2    Foundation, Inc.
3
4    NOTE: The canonical source of this file is maintained with the GNU C Library.
5    Bugs can be reported to bug-glibc@prep.ai.mit.edu.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License along
18    with this program; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #ifdef _LIBC
26 # define HAVE_MBLEN 1
27 # define HAVE_MBRLEN 1
28 # define HAVE_STRUCT_ERA_ENTRY 1
29 # define HAVE_TM_GMTOFF 1
30 # define HAVE_TM_ZONE 1
31 # define HAVE_TZNAME 1
32 # define HAVE_TZSET 1
33 # define MULTIBYTE_IS_FORMAT_SAFE 1
34 # include "../locale/localeinfo.h"
35 #endif
36
37 #include <ctype.h>
38 #include <sys/types.h>          /* Some systems define `time_t' here.  */
39
40 #ifdef TIME_WITH_SYS_TIME
41 # include <sys/time.h>
42 # include <time.h>
43 #else
44 # ifdef HAVE_SYS_TIME_H
45 #  include <sys/time.h>
46 # else
47 #  include <time.h>
48 # endif
49 #endif
50 #if HAVE_TZNAME
51 extern char *tzname[];
52 #endif
53
54 /* Do multibyte processing if multibytes are supported, unless
55    multibyte sequences are safe in formats.  Multibyte sequences are
56    safe if they cannot contain byte sequences that look like format
57    conversion specifications.  The GNU C Library uses UTF8 multibyte
58    encoding, which is safe for formats, but strftime.c can be used
59    with other C libraries that use unsafe encodings.  */
60 #define DO_MULTIBYTE (HAVE_MBLEN && HAVE_WCHAR_H && ! MULTIBYTE_IS_FORMAT_SAFE)
61
62 #if DO_MULTIBYTE
63 # if HAVE_MBRLEN
64 #  include <wchar.h>
65 # else
66    /* Simulate mbrlen with mblen as best we can.  */
67 #  define mbstate_t int
68 #  define mbrlen(s, n, ps) mblen (s, n)
69 #  define mbsinit(ps) (*(ps) == 0)
70 # endif
71   static const mbstate_t mbstate_zero;
72 #endif
73
74 #include <limits.h>
75 #include <stdbool.h>
76 #include <stddef.h>
77 #include <stdlib.h>
78 #include <string.h>
79
80 #ifdef COMPILE_WIDE
81 # include <endian.h>
82 # define CHAR_T wchar_t
83 # define UCHAR_T unsigned int
84 # define L_(Str) L##Str
85 # define NLW(Sym) _NL_W##Sym
86
87 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
88 # define STRLEN(s) __wcslen (s)
89
90 #else
91 # define CHAR_T char
92 # define UCHAR_T unsigned char
93 # define L_(Str) Str
94 # define NLW(Sym) Sym
95
96 # define MEMCPY(d, s, n) memcpy (d, s, n)
97 # define STRLEN(s) strlen (s)
98
99 # ifdef _LIBC
100 #  define MEMPCPY(d, s, n) __mempcpy (d, s, n)
101 # else
102 #  ifndef HAVE_MEMPCPY
103 #   define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
104 #  endif
105 # endif
106 #endif
107
108 /* Shift A right by B bits portably, by dividing A by 2**B and
109    truncating towards minus infinity.  A and B should be free of side
110    effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
111    INT_BITS is the number of useful bits in an int.  GNU code can
112    assume that INT_BITS is at least 32.
113
114    ISO C99 says that A >> B is implementation-defined if A < 0.  Some
115    implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
116    right in the usual way when A < 0, so SHR falls back on division if
117    ordinary A >> B doesn't seem to be the usual signed shift.  */
118 #define SHR(a, b)       \
119   (-1 >> 1 == -1        \
120    ? (a) >> (b)         \
121    : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
122
123 /* Bound on length of the string representing an integer value or type T.
124    Subtract 1 for the sign bit if t is signed; log10 (2.0) < 146/485;
125    add 1 for integer division truncation; add 1 more for a minus sign
126    if needed.  */
127 #define INT_STRLEN_BOUND(t) \
128   ((sizeof (t) * CHAR_BIT - 1) * 146 / 485 + 2)
129
130 #define TM_YEAR_BASE 1900
131
132 #ifndef __isleap
133 /* Nonzero if YEAR is a leap year (every 4 years,
134    except every 100th isn't, and every 400th is).  */
135 # define __isleap(year) \
136   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
137 #endif
138
139
140 #ifdef _LIBC
141 # define tzname __tzname
142 # define tzset __tzset
143 #endif
144
145 #if !HAVE_TM_GMTOFF
146 /* Portable standalone applications should supply a "time_r.h" that
147    declares a POSIX-compliant localtime_r, for the benefit of older
148    implementations that lack localtime_r or have a nonstandard one.
149    See the gnulib time_r module for one way to implement this.  */
150 # include "time_r.h"
151 # undef __gmtime_r
152 # undef __localtime_r
153 # define __gmtime_r gmtime_r
154 # define __localtime_r localtime_r
155 #endif
156
157
158 #ifdef COMPILE_WIDE
159 # define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
160 # define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
161 #else
162 # define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
163 # define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
164 #endif
165
166 #define add(n, f)                                                             \
167   do                                                                          \
168     {                                                                         \
169       int _n = (n);                                                           \
170       int _delta = width - _n;                                                \
171       int _incr = _n + (_delta > 0 ? _delta : 0);                             \
172       if ((size_t) _incr >= maxsize - i)                                      \
173         return 0;                                                             \
174       if (p)                                                                  \
175         {                                                                     \
176           if (_delta > 0)                                                     \
177             {                                                                 \
178               if (pad == L_('0'))                                             \
179                 memset_zero (p, _delta);                                      \
180               else                                                            \
181                 memset_space (p, _delta);                                     \
182             }                                                                 \
183           f;                                                                  \
184           p += _n;                                                            \
185         }                                                                     \
186       i += _incr;                                                             \
187     } while (0)
188
189 #define cpy(n, s) \
190     add ((n),                                                                 \
191          if (to_lowcase)                                                      \
192            memcpy_lowcase (p, (s), _n LOCALE_ARG);                            \
193          else if (to_uppcase)                                                 \
194            memcpy_uppcase (p, (s), _n LOCALE_ARG);                            \
195          else                                                                 \
196            MEMCPY ((void *) p, (void const *) (s), _n))
197
198 #ifdef COMPILE_WIDE
199 # ifndef USE_IN_EXTENDED_LOCALE_MODEL
200 #  undef __mbsrtowcs_l
201 #  define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
202 # endif
203 # define widen(os, ws, l) \
204   {                                                                           \
205     mbstate_t __st;                                                           \
206     const char *__s = os;                                                     \
207     memset (&__st, '\0', sizeof (__st));                                      \
208     l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc);                            \
209     ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t));                     \
210     (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc);                           \
211   }
212 #endif
213
214
215 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
216 /* We use this code also for the extended locale handling where the
217    function gets as an additional argument the locale which has to be
218    used.  To access the values we have to redefine the _NL_CURRENT
219    macro.  */
220 # define strftime               __strftime_l
221 # define wcsftime               __wcsftime_l
222 # undef _NL_CURRENT
223 # define _NL_CURRENT(category, item) \
224   (current->values[_NL_ITEM_INDEX (item)].string)
225 # define LOCALE_ARG , loc
226 # define LOCALE_PARAM_PROTO , __locale_t loc
227 # define HELPER_LOCALE_ARG  , current
228 #else
229 # define LOCALE_PARAM_PROTO
230 # define LOCALE_ARG
231 # ifdef _LIBC
232 #  define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
233 # else
234 #  define HELPER_LOCALE_ARG
235 # endif
236 #endif
237
238 #ifdef COMPILE_WIDE
239 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
240 #  define TOUPPER(Ch, L) __towupper_l (Ch, L)
241 #  define TOLOWER(Ch, L) __towlower_l (Ch, L)
242 # else
243 #  define TOUPPER(Ch, L) towupper (Ch)
244 #  define TOLOWER(Ch, L) towlower (Ch)
245 # endif
246 #else
247 # ifdef _LIBC
248 #  ifdef USE_IN_EXTENDED_LOCALE_MODEL
249 #   define TOUPPER(Ch, L) __toupper_l (Ch, L)
250 #   define TOLOWER(Ch, L) __tolower_l (Ch, L)
251 #  else
252 #   define TOUPPER(Ch, L) toupper (Ch)
253 #   define TOLOWER(Ch, L) tolower (Ch)
254 #  endif
255 # else
256 #  define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
257 #  define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
258 # endif
259 #endif
260 /* We don't use `isdigit' here since the locale dependent
261    interpretation is not what we want here.  We only need to accept
262    the arabic digits in the ASCII range.  One day there is perhaps a
263    more reliable way to accept other sets of digits.  */
264 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
265
266 static CHAR_T *
267 memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
268                 size_t len LOCALE_PARAM_PROTO)
269 {
270   while (len-- > 0)
271     dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
272   return dest;
273 }
274
275 static CHAR_T *
276 memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
277                 size_t len LOCALE_PARAM_PROTO)
278 {
279   while (len-- > 0)
280     dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
281   return dest;
282 }
283
284
285 #if ! HAVE_TM_GMTOFF
286 /* Yield the difference between *A and *B,
287    measured in seconds, ignoring leap seconds.  */
288 # define tm_diff ftime_tm_diff
289 static int
290 tm_diff (const struct tm *a, const struct tm *b)
291 {
292   /* Compute intervening leap days correctly even if year is negative.
293      Take care to avoid int overflow in leap day calculations,
294      but it's OK to assume that A and B are close to each other.  */
295   int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
296   int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
297   int a100 = a4 / 25 - (a4 % 25 < 0);
298   int b100 = b4 / 25 - (b4 % 25 < 0);
299   int a400 = SHR (a100, 2);
300   int b400 = SHR (b100, 2);
301   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
302   int years = a->tm_year - b->tm_year;
303   int days = (365 * years + intervening_leap_days
304               + (a->tm_yday - b->tm_yday));
305   return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
306                 + (a->tm_min - b->tm_min))
307           + (a->tm_sec - b->tm_sec));
308 }
309 #endif /* ! HAVE_TM_GMTOFF */
310
311
312
313 /* The number of days from the first day of the first ISO week of this
314    year to the year day YDAY with week day WDAY.  ISO weeks start on
315    Monday; the first ISO week has the year's first Thursday.  YDAY may
316    be as small as YDAY_MINIMUM.  */
317 #define ISO_WEEK_START_WDAY 1 /* Monday */
318 #define ISO_WEEK1_WDAY 4 /* Thursday */
319 #define YDAY_MINIMUM (-366)
320 #ifdef __GNUC__
321 __inline__
322 #endif
323 static int
324 iso_week_days (int yday, int wday)
325 {
326   /* Add enough to the first operand of % to make it nonnegative.  */
327   int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
328   return (yday
329           - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
330           + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
331 }
332
333
334 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
335 static CHAR_T const weekday_name[][10] =
336   {
337     L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
338     L_("Thursday"), L_("Friday"), L_("Saturday")
339   };
340 static CHAR_T const month_name[][10] =
341   {
342     L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
343     L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
344     L_("November"), L_("December")
345   };
346 #endif
347
348
349 /* When compiling this file, GNU applications can #define my_strftime
350    to a symbol (typically nstrftime) to get an extended strftime with
351    extra arguments UT and NS.  Emacs is a special case for now, but
352    this Emacs-specific code can be removed once Emacs's config.h
353    defines my_strftime.  */
354 #if defined emacs && !defined my_strftime
355 # define my_strftime nstrftime
356 #endif
357
358 #ifdef my_strftime
359 # define extra_args , ut, ns
360 # define extra_args_spec , int ut, int ns
361 #else
362 # ifdef COMPILE_WIDE
363 #  define my_strftime wcsftime
364 #  define nl_get_alt_digit _nl_get_walt_digit
365 # else
366 #  define my_strftime strftime
367 #  define nl_get_alt_digit _nl_get_alt_digit
368 # endif
369 # define extra_args
370 # define extra_args_spec
371 /* We don't have this information in general.  */
372 # define ut 0
373 # define ns 0
374 #endif
375
376 #if ! defined _LIBC && ! HAVE_RUN_TZSET_TEST
377 /* Solaris 2.5.x and 2.6 tzset sometimes modify the storage returned
378    by localtime.  On such systems, we must use the tzset and localtime
379    wrappers to work around the bug.  */
380 "you must run the autoconf test for a working tzset function"
381 #endif
382
383
384 /* Write information from TP into S according to the format
385    string FORMAT, writing no more that MAXSIZE characters
386    (including the terminating '\0') and returning number of
387    characters written.  If S is NULL, nothing will be written
388    anywhere, so to determine how many characters would be
389    written, use NULL for S and (size_t) -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               return 0;
785             cpy (len - 1, ubuf + 1);
786           }
787           break;
788 #endif
789
790         case L_('C'):
791           if (modifier == L_('O'))
792             goto bad_format;
793           if (modifier == L_('E'))
794             {
795 #if HAVE_STRUCT_ERA_ENTRY
796               struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
797               if (era)
798                 {
799 # ifdef COMPILE_WIDE
800                   size_t len = __wcslen (era->era_wname);
801                   cpy (len, era->era_wname);
802 # else
803                   size_t len = strlen (era->era_name);
804                   cpy (len, era->era_name);
805 # endif
806                   break;
807                 }
808 #else
809 # if HAVE_STRFTIME
810               goto underlying_strftime;
811 # endif
812 #endif
813             }
814
815           {
816             int century = tp->tm_year / 100 + TM_YEAR_BASE / 100;
817             century -= tp->tm_year % 100 < 0 && 0 < century;
818             DO_SIGNED_NUMBER (2, tp->tm_year < - TM_YEAR_BASE, century);
819           }
820
821         case L_('x'):
822           if (modifier == L_('O'))
823             goto bad_format;
824 #ifdef _NL_CURRENT
825           if (! (modifier == L_('E')
826                  && (*(subfmt =
827                        (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
828                      != L_('\0'))))
829             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
830           goto subformat;
831 #else
832 # if HAVE_STRFTIME
833           goto underlying_strftime;
834 # else
835           /* Fall through.  */
836 # endif
837 #endif
838         case L_('D'):
839           if (modifier != 0)
840             goto bad_format;
841           subfmt = L_("%m/%d/%y");
842           goto subformat;
843
844         case L_('d'):
845           if (modifier == L_('E'))
846             goto bad_format;
847
848           DO_NUMBER (2, tp->tm_mday);
849
850         case L_('e'):
851           if (modifier == L_('E'))
852             goto bad_format;
853
854           DO_NUMBER_SPACEPAD (2, tp->tm_mday);
855
856           /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
857              and then jump to one of these three labels.  */
858
859         do_number_spacepad:
860           /* Force `_' flag unless overridden by `0' or `-' flag.  */
861           if (pad != L_('0') && pad != L_('-'))
862             pad = L_('_');
863
864         do_number:
865           /* Format NUMBER_VALUE according to the MODIFIER flag.  */
866           negative_number = number_value < 0;
867           u_number_value = number_value;
868
869         do_signed_number:
870           /* Format U_NUMBER_VALUE according to the MODIFIER flag.
871              NEGATIVE_NUMBER is nonzero if the original number was
872              negative; in this case it was converted directly to
873              unsigned int (i.e., modulo (UINT_MAX + 1)) without
874              negating it.  */
875           if (modifier == L_('O') && !negative_number)
876             {
877 #ifdef _NL_CURRENT
878               /* Get the locale specific alternate representation of
879                  the number.  If none exist NULL is returned.  */
880               const CHAR_T *cp = nl_get_alt_digit (u_number_value
881                                                    HELPER_LOCALE_ARG);
882
883               if (cp != NULL)
884                 {
885                   size_t digitlen = STRLEN (cp);
886                   if (digitlen != 0)
887                     {
888                       cpy (digitlen, cp);
889                       break;
890                     }
891                 }
892 #else
893 # if HAVE_STRFTIME
894               goto underlying_strftime;
895 # endif
896 #endif
897             }
898
899           bufp = buf + sizeof (buf) / sizeof (buf[0]);
900
901           if (negative_number)
902             u_number_value = - u_number_value;
903
904           do
905             {
906               *--bufp = u_number_value % 10 + L_('0');
907               u_number_value /= 10;
908             }
909           while (u_number_value != 0);
910
911           if (digits < width)
912             digits = width;
913
914         do_number_sign_and_padding:
915           if (negative_number)
916             *--bufp = L_('-');
917
918           if (pad != L_('-'))
919             {
920               int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
921                                       - bufp);
922
923               if (padding > 0)
924                 {
925                   if (pad == L_('_'))
926                     {
927                       if ((size_t) padding >= maxsize - i)
928                         return 0;
929
930                       if (p)
931                         memset_space (p, padding);
932                       i += padding;
933                       width = width > padding ? width - padding : 0;
934                     }
935                   else
936                     {
937                       if ((size_t) digits >= maxsize - i)
938                         return 0;
939
940                       if (negative_number)
941                         {
942                           ++bufp;
943
944                           if (p)
945                             *p++ = L_('-');
946                           ++i;
947                         }
948
949                       if (p)
950                         memset_zero (p, padding);
951                       i += padding;
952                       width = 0;
953                     }
954                 }
955             }
956
957           cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
958           break;
959
960         case L_('F'):
961           if (modifier != 0)
962             goto bad_format;
963           subfmt = L_("%Y-%m-%d");
964           goto subformat;
965
966         case L_('H'):
967           if (modifier == L_('E'))
968             goto bad_format;
969
970           DO_NUMBER (2, tp->tm_hour);
971
972         case L_('I'):
973           if (modifier == L_('E'))
974             goto bad_format;
975
976           DO_NUMBER (2, hour12);
977
978         case L_('k'):           /* GNU extension.  */
979           if (modifier == L_('E'))
980             goto bad_format;
981
982           DO_NUMBER_SPACEPAD (2, tp->tm_hour);
983
984         case L_('l'):           /* GNU extension.  */
985           if (modifier == L_('E'))
986             goto bad_format;
987
988           DO_NUMBER_SPACEPAD (2, hour12);
989
990         case L_('j'):
991           if (modifier == L_('E'))
992             goto bad_format;
993
994           DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
995
996         case L_('M'):
997           if (modifier == L_('E'))
998             goto bad_format;
999
1000           DO_NUMBER (2, tp->tm_min);
1001
1002         case L_('m'):
1003           if (modifier == L_('E'))
1004             goto bad_format;
1005
1006           DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
1007
1008 #ifndef _LIBC
1009         case L_('N'):           /* GNU extension.  */
1010           if (modifier == L_('E'))
1011             goto bad_format;
1012
1013           number_value = ns;
1014           if (width != -1)
1015             {
1016               /* Take an explicit width less than 9 as a precision.  */
1017               int j;
1018               for (j = width; j < 9; j++)
1019                 number_value /= 10;
1020             }
1021
1022           DO_NUMBER (9, number_value);
1023 #endif
1024
1025         case L_('n'):
1026           add (1, *p = L_('\n'));
1027           break;
1028
1029         case L_('P'):
1030           to_lowcase = true;
1031 #if !defined _NL_CURRENT && HAVE_STRFTIME
1032           format_char = L_('p');
1033 #endif
1034           /* FALLTHROUGH */
1035
1036         case L_('p'):
1037           if (change_case)
1038             {
1039               to_uppcase = false;
1040               to_lowcase = true;
1041             }
1042 #if defined _NL_CURRENT || !HAVE_STRFTIME
1043           cpy (ap_len, ampm);
1044           break;
1045 #else
1046           goto underlying_strftime;
1047 #endif
1048
1049         case L_('R'):
1050           subfmt = L_("%H:%M");
1051           goto subformat;
1052
1053         case L_('r'):
1054 #if !defined _NL_CURRENT && HAVE_STRFTIME
1055           goto underlying_strftime;
1056 #else
1057 # ifdef _NL_CURRENT
1058           if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1059                                                        NLW(T_FMT_AMPM)))
1060               == L_('\0'))
1061 # endif
1062             subfmt = L_("%I:%M:%S %p");
1063           goto subformat;
1064 #endif
1065
1066         case L_('S'):
1067           if (modifier == L_('E'))
1068             goto bad_format;
1069
1070           DO_NUMBER (2, tp->tm_sec);
1071
1072         case L_('s'):           /* GNU extension.  */
1073           {
1074             struct tm ltm;
1075             time_t t;
1076
1077             ltm = *tp;
1078             t = mktime (&ltm);
1079
1080             /* Generate string value for T using time_t arithmetic;
1081                this works even if sizeof (long) < sizeof (time_t).  */
1082
1083             bufp = buf + sizeof (buf) / sizeof (buf[0]);
1084             negative_number = t < 0;
1085
1086             do
1087               {
1088                 int d = t % 10;
1089                 t /= 10;
1090                 *--bufp = (negative_number ? -d : d) + L_('0');
1091               }
1092             while (t != 0);
1093
1094             digits = 1;
1095             goto do_number_sign_and_padding;
1096           }
1097
1098         case L_('X'):
1099           if (modifier == L_('O'))
1100             goto bad_format;
1101 #ifdef _NL_CURRENT
1102           if (! (modifier == L_('E')
1103                  && (*(subfmt =
1104                        (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1105                      != L_('\0'))))
1106             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1107           goto subformat;
1108 #else
1109 # if HAVE_STRFTIME
1110           goto underlying_strftime;
1111 # else
1112           /* Fall through.  */
1113 # endif
1114 #endif
1115         case L_('T'):
1116           subfmt = L_("%H:%M:%S");
1117           goto subformat;
1118
1119         case L_('t'):
1120           add (1, *p = L_('\t'));
1121           break;
1122
1123         case L_('u'):
1124           DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1125
1126         case L_('U'):
1127           if (modifier == L_('E'))
1128             goto bad_format;
1129
1130           DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1131
1132         case L_('V'):
1133         case L_('g'):
1134         case L_('G'):
1135           if (modifier == L_('E'))
1136             goto bad_format;
1137           {
1138             /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
1139                is a leap year, except that YEAR and YEAR - 1 both work
1140                correctly even when (tp->tm_year + TM_YEAR_BASE) would
1141                overflow.  */
1142             int year = (tp->tm_year
1143                         + (tp->tm_year < 0
1144                            ? TM_YEAR_BASE % 400
1145                            : TM_YEAR_BASE % 400 - 400));
1146             int year_adjust = 0;
1147             int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1148
1149             if (days < 0)
1150               {
1151                 /* This ISO week belongs to the previous year.  */
1152                 year_adjust = -1;
1153                 days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
1154                                       tp->tm_wday);
1155               }
1156             else
1157               {
1158                 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1159                                        tp->tm_wday);
1160                 if (0 <= d)
1161                   {
1162                     /* This ISO week belongs to the next year.  */
1163                     year_adjust = 1;
1164                     days = d;
1165                   }
1166               }
1167
1168             switch (*f)
1169               {
1170               case L_('g'):
1171                 {
1172                   int yy = (tp->tm_year % 100 + year_adjust) % 100;
1173                   DO_NUMBER (2, (0 <= yy
1174                                  ? yy
1175                                  : tp->tm_year < -TM_YEAR_BASE - year_adjust
1176                                  ? -yy
1177                                  : yy + 100));
1178                 }
1179
1180               case L_('G'):
1181                 DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
1182                                   (tp->tm_year + (unsigned int) TM_YEAR_BASE
1183                                    + year_adjust));
1184
1185               default:
1186                 DO_NUMBER (2, days / 7 + 1);
1187               }
1188           }
1189
1190         case L_('W'):
1191           if (modifier == L_('E'))
1192             goto bad_format;
1193
1194           DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1195
1196         case L_('w'):
1197           if (modifier == L_('E'))
1198             goto bad_format;
1199
1200           DO_NUMBER (1, tp->tm_wday);
1201
1202         case L_('Y'):
1203           if (modifier == 'E')
1204             {
1205 #if HAVE_STRUCT_ERA_ENTRY
1206               struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1207               if (era)
1208                 {
1209 # ifdef COMPILE_WIDE
1210                   subfmt = era->era_wformat;
1211 # else
1212                   subfmt = era->era_format;
1213 # endif
1214                   goto subformat;
1215                 }
1216 #else
1217 # if HAVE_STRFTIME
1218               goto underlying_strftime;
1219 # endif
1220 #endif
1221             }
1222           if (modifier == L_('O'))
1223             goto bad_format;
1224           else
1225             DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE,
1226                               tp->tm_year + (unsigned int) TM_YEAR_BASE);
1227
1228         case L_('y'):
1229           if (modifier == L_('E'))
1230             {
1231 #if HAVE_STRUCT_ERA_ENTRY
1232               struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1233               if (era)
1234                 {
1235                   int delta = tp->tm_year - era->start_date[0];
1236                   DO_NUMBER (1, (era->offset
1237                                  + delta * era->absolute_direction));
1238                 }
1239 #else
1240 # if HAVE_STRFTIME
1241               goto underlying_strftime;
1242 # endif
1243 #endif
1244             }
1245
1246           {
1247             int yy = tp->tm_year % 100;
1248             if (yy < 0)
1249               yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
1250             DO_NUMBER (2, yy);
1251           }
1252
1253         case L_('Z'):
1254           if (change_case)
1255             {
1256               to_uppcase = false;
1257               to_lowcase = true;
1258             }
1259
1260 #if HAVE_TZNAME
1261           /* The tzset() call might have changed the value.  */
1262           if (!(zone && *zone) && tp->tm_isdst >= 0)
1263             zone = tzname[tp->tm_isdst != 0];
1264 #endif
1265           if (! zone)
1266             zone = "";
1267
1268 #ifdef COMPILE_WIDE
1269           {
1270             /* The zone string is always given in multibyte form.  We have
1271                to transform it first.  */
1272             wchar_t *wczone;
1273             size_t len;
1274             widen (zone, wczone, len);
1275             cpy (len, wczone);
1276           }
1277 #else
1278           cpy (strlen (zone), zone);
1279 #endif
1280           break;
1281
1282         case L_('z'):
1283           if (tp->tm_isdst < 0)
1284             break;
1285
1286           {
1287             int diff;
1288 #if HAVE_TM_GMTOFF
1289             diff = tp->tm_gmtoff;
1290 #else
1291             if (ut)
1292               diff = 0;
1293             else
1294               {
1295                 struct tm gtm;
1296                 struct tm ltm;
1297                 time_t lt;
1298
1299                 ltm = *tp;
1300                 lt = mktime (&ltm);
1301
1302                 if (lt == (time_t) -1)
1303                   {
1304                     /* mktime returns -1 for errors, but -1 is also a
1305                        valid time_t value.  Check whether an error really
1306                        occurred.  */
1307                     struct tm tm;
1308
1309                     if (! __localtime_r (&lt, &tm)
1310                         || ((ltm.tm_sec ^ tm.tm_sec)
1311                             | (ltm.tm_min ^ tm.tm_min)
1312                             | (ltm.tm_hour ^ tm.tm_hour)
1313                             | (ltm.tm_mday ^ tm.tm_mday)
1314                             | (ltm.tm_mon ^ tm.tm_mon)
1315                             | (ltm.tm_year ^ tm.tm_year)))
1316                       break;
1317                   }
1318
1319                 if (! __gmtime_r (&lt, &gtm))
1320                   break;
1321
1322                 diff = tm_diff (&ltm, &gtm);
1323               }
1324 #endif
1325
1326             if (diff < 0)
1327               {
1328                 add (1, *p = L_('-'));
1329                 diff = -diff;
1330               }
1331             else
1332               add (1, *p = L_('+'));
1333
1334             diff /= 60;
1335             DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1336           }
1337
1338         case L_('\0'):          /* GNU extension: % at end of format.  */
1339             --f;
1340             /* Fall through.  */
1341         default:
1342           /* Unknown format; output the format, including the '%',
1343              since this is most likely the right thing to do if a
1344              multibyte string has been misparsed.  */
1345         bad_format:
1346           {
1347             int flen;
1348             for (flen = 1; f[1 - flen] != L_('%'); flen++)
1349               continue;
1350             cpy (flen, &f[1 - flen]);
1351           }
1352           break;
1353         }
1354     }
1355
1356   if (p && maxsize != 0)
1357     *p = L_('\0');
1358   return i;
1359 }
1360 #ifdef _LIBC
1361 libc_hidden_def (my_strftime)
1362 #endif
1363
1364
1365 #ifdef emacs
1366 /* For Emacs we have a separate interface which corresponds to the normal
1367    strftime function plus the ut argument, but without the ns argument.  */
1368 size_t
1369 emacs_strftimeu (char *s, size_t maxsize, const char *format,
1370                  const struct tm *tp, int ut)
1371 {
1372   return my_strftime (s, maxsize, format, tp, ut, 0);
1373 }
1374 #endif