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