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