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 = ©
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, <m);
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, <m);
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, <, &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, <, >m))
1440 break;
1441
1442 diff = tm_diff (<m, >m);
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