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