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