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