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