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