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