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