1 /* Copyright (C) 1991-2021 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 3 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 # define USE_IN_EXTENDED_LOCALE_MODEL 1
19 # define HAVE_STRUCT_ERA_ENTRY 1
20 # define HAVE_TM_GMTOFF 1
21 # define HAVE_STRUCT_TM_TM_ZONE 1
22 # define HAVE_TZNAME 1
23 # include "../locale/localeinfo.h"
27 # include "fprintftime.h"
29 # include "strftime.h"
31 # include "time-internal.h"
38 #if HAVE_TZNAME && !HAVE_DECL_TZNAME
39 extern char *tzname[];
42 /* Do multibyte processing if multibyte encodings are supported, unless
43 multibyte sequences are safe in formats. Multibyte sequences are
44 safe if they cannot contain byte sequences that look like format
45 conversion specifications. The multibyte encodings used by the
46 C library on the various platforms (UTF-8, GB2312, GBK, CP936,
47 GB18030, EUC-TW, BIG5, BIG5-HKSCS, CP950, EUC-JP, EUC-KR, CP949,
48 SHIFT_JIS, CP932, JOHAB) are safe for formats, because the byte '%'
49 cannot occur in a multibyte character except in the first byte.
51 The DEC-HANYU encoding used on OSF/1 is not safe for formats, but
52 this encoding has never been seen in real-life use, so we ignore
54 #if !(defined __osf__ && 0)
55 # define MULTIBYTE_IS_FORMAT_SAFE 1
57 #define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE)
61 static const mbstate_t mbstate_zero;
70 #include "attribute.h"
75 # define CHAR_T wchar_t
76 # define UCHAR_T unsigned int
77 # define L_(Str) L##Str
78 # define NLW(Sym) _NL_W##Sym
80 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
81 # define STRLEN(s) __wcslen (s)
85 # define UCHAR_T unsigned char
88 # define ABALTMON_1 _NL_ABALTMON_1
90 # define MEMCPY(d, s, n) memcpy (d, s, n)
91 # define STRLEN(s) strlen (s)
95 /* Shift A right by B bits portably, by dividing A by 2**B and
96 truncating towards minus infinity. A and B should be free of side
97 effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
98 INT_BITS is the number of useful bits in an int. GNU code can
99 assume that INT_BITS is at least 32.
101 ISO C99 says that A >> B is implementation-defined if A < 0. Some
102 implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
103 right in the usual way when A < 0, so SHR falls back on division if
104 ordinary A >> B doesn't seem to be the usual signed shift. */
108 : ((a) + ((a) < 0)) / (1 << (b)) - ((a) < 0))
110 #define TM_YEAR_BASE 1900
113 /* Nonzero if YEAR is a leap year (every 4 years,
114 except every 100th isn't, and every 400th is). */
115 # define __isleap(year) \
116 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
121 # define mktime_z(tz, tm) mktime (tm)
122 # define tzname __tzname
123 # define tzset __tzset
127 # define FPRINTFTIME 0
131 # define STREAM_OR_CHAR_T FILE
132 # define STRFTIME_ARG(x) /* empty */
134 # define STREAM_OR_CHAR_T CHAR_T
135 # define STRFTIME_ARG(x) x,
139 # define memset_byte(P, Len, Byte) \
140 do { size_t _i; for (_i = 0; _i < Len; _i++) fputc (Byte, P); } while (0)
141 # define memset_space(P, Len) memset_byte (P, Len, ' ')
142 # define memset_zero(P, Len) memset_byte (P, Len, '0')
143 #elif defined COMPILE_WIDE
144 # define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
145 # define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
147 # define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
148 # define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
152 # define advance(P, N)
154 # define advance(P, N) ((P) += (N))
157 #define add(n, f) width_add (width, n, f)
158 #define width_add(width, n, f) \
162 size_t _w = pad == L_('-') || width < 0 ? 0 : width; \
163 size_t _incr = _n < _w ? _w : _n; \
164 if (_incr >= maxsize - i) \
173 size_t _delta = _w - _n; \
174 if (pad == L_('0') || pad == L_('+')) \
175 memset_zero (p, _delta); \
177 memset_space (p, _delta); \
185 #define add1(c) width_add1 (width, c)
187 # define width_add1(width, c) width_add (width, 1, fputc (c, p))
189 # define width_add1(width, c) width_add (width, 1, *p = c)
192 #define cpy(n, s) width_cpy (width, n, s)
194 # define width_cpy(width, n, s) \
195 width_add (width, n, \
199 fwrite_lowcase (p, (s), _n); \
200 else if (to_uppcase) \
201 fwrite_uppcase (p, (s), _n); \
204 /* Ignore the value of fwrite. The caller can determine whether \
205 an error occurred by inspecting ferror (P). All known fwrite \
206 implementations set the stream's error indicator when they \
207 fail due to ENOMEM etc., even though C11 and POSIX.1-2008 do \
208 not require this. */ \
209 fwrite (s, _n, 1, p); \
215 # define width_cpy(width, n, s) \
216 width_add (width, n, \
218 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
219 else if (to_uppcase) \
220 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
222 MEMCPY ((void *) p, (void const *) (s), _n))
226 # ifndef USE_IN_EXTENDED_LOCALE_MODEL
227 # undef __mbsrtowcs_l
228 # define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
230 # define widen(os, ws, l) \
233 const char *__s = os; \
234 memset (&__st, '\0', sizeof (__st)); \
235 l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
236 ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \
237 (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
242 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
243 /* We use this code also for the extended locale handling where the
244 function gets as an additional argument the locale which has to be
245 used. To access the values we have to redefine the _NL_CURRENT
247 # define strftime __strftime_l
248 # define wcsftime __wcsftime_l
250 # define _NL_CURRENT(category, item) \
251 (current->values[_NL_ITEM_INDEX (item)].string)
252 # define LOCALE_PARAM , locale_t loc
253 # define LOCALE_ARG , loc
254 # define HELPER_LOCALE_ARG , current
256 # define LOCALE_PARAM
259 # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
261 # define HELPER_LOCALE_ARG
266 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
267 # define TOUPPER(Ch, L) __towupper_l (Ch, L)
268 # define TOLOWER(Ch, L) __towlower_l (Ch, L)
270 # define TOUPPER(Ch, L) towupper (Ch)
271 # define TOLOWER(Ch, L) towlower (Ch)
274 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
275 # define TOUPPER(Ch, L) __toupper_l (Ch, L)
276 # define TOLOWER(Ch, L) __tolower_l (Ch, L)
278 # define TOUPPER(Ch, L) toupper (Ch)
279 # define TOLOWER(Ch, L) tolower (Ch)
282 /* We don't use 'isdigit' here since the locale dependent
283 interpretation is not what we want here. We only need to accept
284 the arabic digits in the ASCII range. One day there is perhaps a
285 more reliable way to accept other sets of digits. */
286 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
290 fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len)
294 fputc (TOLOWER ((UCHAR_T) *src, loc), fp);
300 fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len)
304 fputc (TOUPPER ((UCHAR_T) *src, loc), fp);
309 static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
310 size_t len LOCALE_PARAM);
313 memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
316 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
320 static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
321 size_t len LOCALE_PARAM);
324 memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
327 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
334 /* Yield the difference between *A and *B,
335 measured in seconds, ignoring leap seconds. */
336 # define tm_diff ftime_tm_diff
337 static int tm_diff (const struct tm *, const struct tm *);
339 tm_diff (const struct tm *a, const struct tm *b)
341 /* Compute intervening leap days correctly even if year is negative.
342 Take care to avoid int overflow in leap day calculations,
343 but it's OK to assume that A and B are close to each other. */
344 int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
345 int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
346 int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
347 int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
348 int a400 = SHR (a100, 2);
349 int b400 = SHR (b100, 2);
350 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
351 int years = a->tm_year - b->tm_year;
352 int days = (365 * years + intervening_leap_days
353 + (a->tm_yday - b->tm_yday));
354 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
355 + (a->tm_min - b->tm_min))
356 + (a->tm_sec - b->tm_sec));
358 #endif /* ! HAVE_TM_GMTOFF */
362 /* The number of days from the first day of the first ISO week of this
363 year to the year day YDAY with week day WDAY. ISO weeks start on
364 Monday; the first ISO week has the year's first Thursday. YDAY may
365 be as small as YDAY_MINIMUM. */
366 #define ISO_WEEK_START_WDAY 1 /* Monday */
367 #define ISO_WEEK1_WDAY 4 /* Thursday */
368 #define YDAY_MINIMUM (-366)
369 static int iso_week_days (int, int);
370 #if defined __GNUC__ || defined __clang__
374 iso_week_days (int yday, int wday)
376 /* Add enough to the first operand of % to make it nonnegative. */
377 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
379 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
380 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
384 /* When compiling this file, GNU applications can #define my_strftime
385 to a symbol (typically nstrftime) to get an extended strftime with
386 extra arguments TZ and NS. */
390 # define my_strftime fprintftime
394 # define extra_args , tz, ns
395 # define extra_args_spec , timezone_t tz, int ns
397 # if defined COMPILE_WIDE
398 # define my_strftime wcsftime
399 # define nl_get_alt_digit _nl_get_walt_digit
401 # define my_strftime strftime
402 # define nl_get_alt_digit _nl_get_alt_digit
405 # define extra_args_spec
406 /* We don't have this information in general. */
411 static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t)
412 const CHAR_T *, const struct tm *,
413 bool, int, int, bool *
414 extra_args_spec LOCALE_PARAM);
416 /* Write information from TP into S according to the format
417 string FORMAT, writing no more that MAXSIZE characters
418 (including the terminating '\0') and returning number of
419 characters written. If S is NULL, nothing will be written
420 anywhere, so to determine how many characters would be
421 written, use NULL for S and (size_t) -1 for MAXSIZE. */
423 my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
424 const CHAR_T *format,
425 const struct tm *tp extra_args_spec LOCALE_PARAM)
427 bool tzset_called = false;
428 return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, false,
429 0, -1, &tzset_called extra_args LOCALE_ARG);
431 #if defined _LIBC && ! FPRINTFTIME
432 libc_hidden_def (my_strftime)
435 /* Just like my_strftime, above, but with more parameters.
436 UPCASE indicates that the result should be converted to upper case.
437 YR_SPEC and WIDTH specify the padding and width for the year.
438 *TZSET_CALLED indicates whether tzset has been called here. */
440 __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
441 const CHAR_T *format,
442 const struct tm *tp, bool upcase,
443 int yr_spec, int width, bool *tzset_called
444 extra_args_spec LOCALE_PARAM)
446 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
447 struct __locale_data *const current = loc->__locales[LC_TIME];
450 size_t maxsize = (size_t) -1;
453 int saved_errno = errno;
454 int hour12 = tp->tm_hour;
456 /* We cannot make the following values variables since we must delay
457 the evaluation of these values until really needed since some
458 expressions might not be valid in every situation. The 'struct tm'
459 might be generated by a strptime() call that initialized
460 only a few elements. Dereference the pointers only if the format
461 requires this. Then it is ok to fail if the pointers are invalid. */
463 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
464 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
466 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
467 ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
469 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
470 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
472 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
473 ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
474 # define a_altmonth \
475 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
476 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABALTMON_1) + tp->tm_mon)))
477 # define f_altmonth \
478 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
479 ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon)))
481 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
482 ? NLW(PM_STR) : NLW(AM_STR)))
484 # define aw_len STRLEN (a_wkday)
485 # define am_len STRLEN (a_month)
486 # define aam_len STRLEN (a_altmonth)
487 # define ap_len STRLEN (ampm)
490 char **tzname_vec = tzname;
494 STREAM_OR_CHAR_T *p = s;
496 #if DO_MULTIBYTE && !defined COMPILE_WIDE
497 const char *format_end = NULL;
501 #if HAVE_STRUCT_TM_TM_ZONE
502 /* The POSIX test suite assumes that setting
503 the environment variable TZ to a new value before calling strftime()
504 will influence the result (the %Z format) even if the information in
505 TP is computed with a totally different time zone.
506 This is bogus: though POSIX allows bad behavior like this,
507 POSIX does not require it. Do the right thing instead. */
508 zone = (const char *) tp->tm_zone;
513 if (! (zone && *zone))
518 # if !HAVE_STRUCT_TM_TM_ZONE
519 /* Infer the zone name from *TZ instead of from TZNAME. */
520 tzname_vec = tz->tzname_copy;
523 /* The tzset() call might have changed the value. */
524 if (!(zone && *zone) && tp->tm_isdst >= 0)
526 /* POSIX.1 requires that local time zone information be used as
527 though strftime called tzset. */
532 *tzset_called = true;
535 zone = tzname_vec[tp->tm_isdst != 0];
547 for (f = format; *f != '\0'; width = -1, f++)
549 int pad = 0; /* Padding for number ('_', '-', '+', '0', or 0). */
550 int modifier; /* Field modifier ('E', 'O', or 0). */
551 int digits = 0; /* Max digits for numeric format. */
552 int number_value; /* Numeric value to be printed. */
553 unsigned int u_number_value; /* (unsigned int) number_value. */
554 bool negative_number; /* The number is negative. */
555 bool always_output_a_sign; /* +/- should always be output. */
556 int tz_colon_mask; /* Bitmask of where ':' should appear. */
557 const CHAR_T *subfmt;
560 + 2 /* for the two colons in a %::z or %:::z time zone */
561 + (sizeof (int) < sizeof (time_t)
562 ? INT_STRLEN_BOUND (time_t)
563 : INT_STRLEN_BOUND (int))];
564 bool to_lowcase = false;
565 bool to_uppcase = upcase;
567 bool change_case = false;
571 #if DO_MULTIBYTE && !defined COMPILE_WIDE
577 case L_('\b'): case L_('\t'): case L_('\n'):
578 case L_('\v'): case L_('\f'): case L_('\r'):
579 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
580 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
581 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
582 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
583 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
584 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
585 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
586 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
587 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
588 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
589 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
590 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
591 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
592 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
593 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
594 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
595 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
596 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
598 /* The C Standard requires these 98 characters (plus '%') to
599 be in the basic execution character set. None of these
600 characters can start a multibyte sequence, so they need
601 not be analyzed further. */
606 /* Copy this multibyte sequence until we reach its end, find
607 an error, or come back to the initial shift state. */
609 mbstate_t mbstate = mbstate_zero;
614 format_end = f + strlen (f) + 1;
615 fsize = format_end - f;
619 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
624 if (bytes == (size_t) -2)
626 len += strlen (f + len);
630 if (bytes == (size_t) -1)
638 while (! mbsinit (&mbstate));
646 #else /* ! DO_MULTIBYTE */
648 /* Either multibyte encodings are not supported, they are
649 safe for formats, so any non-'%' byte can be copied through,
650 or this is the wide character version. */
657 #endif /* ! DO_MULTIBYTE */
659 /* Check for flags that can modify a format. */
664 /* This influences the number formats. */
672 /* This changes textual output. */
691 if (INT_MULTIPLY_WRAPV (width, 10, &width)
692 || INT_ADD_WRAPV (width, *f - L_('0'), &width))
696 while (ISDIGIT (*f));
699 /* Check for modifiers. */
712 /* Now do the specified format. */
716 #define DO_NUMBER(d, v) \
724 #define DO_SIGNED_NUMBER(d, negative, v) \
725 DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_signed_number)
726 #define DO_YEARISH(d, negative, v) \
727 DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_yearish)
728 #define DO_MAYBE_SIGNED_NUMBER(d, negative, v, label) \
732 negative_number = negative; \
733 u_number_value = v; \
738 /* The mask is not what you might think.
739 When the ordinal i'th bit is set, insert a colon
740 before the i'th digit of the time zone representation. */
741 #define DO_TZ_OFFSET(d, mask, v) \
745 tz_colon_mask = mask; \
746 u_number_value = v; \
750 #define DO_NUMBER_SPACEPAD(d, v) \
755 goto do_number_spacepad; \
774 cpy (aw_len, a_wkday);
777 goto underlying_strftime;
789 cpy (STRLEN (f_wkday), f_wkday);
792 goto underlying_strftime;
802 if (modifier == L_('E'))
805 if (modifier == L_('O'))
806 cpy (aam_len, a_altmonth);
808 cpy (am_len, a_month);
811 goto underlying_strftime;
815 if (modifier == L_('E'))
823 if (modifier == L_('O'))
824 cpy (STRLEN (f_altmonth), f_altmonth);
826 cpy (STRLEN (f_month), f_month);
829 goto underlying_strftime;
833 if (modifier == L_('O'))
836 if (! (modifier == L_('E')
838 (const CHAR_T *) _NL_CURRENT (LC_TIME,
841 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
843 goto underlying_strftime;
850 size_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1)
851 subfmt, tp, to_uppcase,
852 pad, subwidth, tzset_called
853 extra_args LOCALE_ARG);
854 add (len, __strftime_internal (p,
855 STRFTIME_ARG (maxsize - i)
856 subfmt, tp, to_uppcase,
857 pad, subwidth, tzset_called
858 extra_args LOCALE_ARG));
862 #if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
865 /* The relevant information is available only via the
866 underlying strftime implementation, so use that. */
869 char ubuf[1024]; /* enough for any single format in practice */
871 /* Make sure we're calling the actual underlying strftime.
872 In some cases, config.h contains something like
873 "#define strftime rpl_strftime". */
879 /* The space helps distinguish strftime failure from empty
887 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
889 cpy (len - 1, ubuf + 1);
895 if (modifier == L_('E'))
897 #if HAVE_STRUCT_ERA_ENTRY
898 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
902 size_t len = __wcslen (era->era_wname);
903 cpy (len, era->era_wname);
905 size_t len = strlen (era->era_name);
906 cpy (len, era->era_name);
911 goto underlying_strftime;
916 bool negative_year = tp->tm_year < - TM_YEAR_BASE;
917 bool zero_thru_1899 = !negative_year & (tp->tm_year < 0);
918 int century = ((tp->tm_year - 99 * zero_thru_1899) / 100
919 + TM_YEAR_BASE / 100);
920 DO_YEARISH (2, negative_year, century);
924 if (modifier == L_('O'))
927 if (! (modifier == L_('E')
929 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
931 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
934 goto underlying_strftime;
939 subfmt = L_("%m/%d/%y");
943 if (modifier == L_('E'))
946 DO_NUMBER (2, tp->tm_mday);
949 if (modifier == L_('E'))
952 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
954 /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
955 and then jump to one of these labels. */
958 always_output_a_sign = true;
966 && ((digits == 2 ? 99 : 9999) < u_number_value
968 goto do_maybe_signed_number;
975 /* Format NUMBER_VALUE according to the MODIFIER flag. */
976 negative_number = number_value < 0;
977 u_number_value = number_value;
980 always_output_a_sign = false;
982 do_maybe_signed_number:
986 /* Format U_NUMBER_VALUE according to the MODIFIER flag.
987 NEGATIVE_NUMBER is nonzero if the original number was
988 negative; in this case it was converted directly to
989 unsigned int (i.e., modulo (UINT_MAX + 1)) without
991 if (modifier == L_('O') && !negative_number)
994 /* Get the locale specific alternate representation of
995 the number. If none exist NULL is returned. */
996 const CHAR_T *cp = nl_get_alt_digit (u_number_value
1001 size_t digitlen = STRLEN (cp);
1009 goto underlying_strftime;
1013 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1015 if (negative_number)
1016 u_number_value = - u_number_value;
1020 if (tz_colon_mask & 1)
1022 tz_colon_mask >>= 1;
1023 *--bufp = u_number_value % 10 + L_('0');
1024 u_number_value /= 10;
1026 while (u_number_value != 0 || tz_colon_mask != 0);
1028 do_number_sign_and_padding:
1035 CHAR_T sign_char = (negative_number ? L_('-')
1036 : always_output_a_sign ? L_('+')
1038 int numlen = buf + sizeof buf / sizeof buf[0] - bufp;
1039 int shortage = width - !!sign_char - numlen;
1040 int padding = pad == L_('-') || shortage <= 0 ? 0 : shortage;
1047 memset_space (p, padding);
1051 width_add1 (0, sign_char);
1062 if (pad == 0 && width < 0)
1069 subwidth = width - 6;
1073 subfmt = L_("%Y-%m-%d");
1074 goto subformat_width;
1077 if (modifier == L_('E'))
1080 DO_NUMBER (2, tp->tm_hour);
1083 if (modifier == L_('E'))
1086 DO_NUMBER (2, hour12);
1088 case L_('k'): /* GNU extension. */
1089 if (modifier == L_('E'))
1092 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1094 case L_('l'): /* GNU extension. */
1095 if (modifier == L_('E'))
1098 DO_NUMBER_SPACEPAD (2, hour12);
1101 if (modifier == L_('E'))
1104 DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
1107 if (modifier == L_('E'))
1110 DO_NUMBER (2, tp->tm_min);
1113 if (modifier == L_('E'))
1116 DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
1119 case L_('N'): /* GNU extension. */
1120 if (modifier == L_('E'))
1123 int n = ns, ns_digits = 9;
1126 int ndigs = ns_digits;
1127 while (width < ndigs || (1 < ndigs && n % 10 == 0))
1129 for (int j = ndigs; 0 < j; j--)
1130 buf[j - 1] = n % 10 + L_('0'), n /= 10;
1133 width_cpy (0, ndigs, buf);
1134 width_add (width - ndigs, 0, (void) 0);
1146 format_char = L_('p');
1159 goto underlying_strftime;
1162 case L_('q'): /* GNU extension. */
1163 DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1);
1167 subfmt = L_("%H:%M");
1172 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1175 subfmt = L_("%I:%M:%S %p");
1178 goto underlying_strftime;
1182 if (modifier == L_('E'))
1185 DO_NUMBER (2, tp->tm_sec);
1187 case L_('s'): /* GNU extension. */
1194 t = mktime_z (tz, <m);
1195 if (ltm.tm_yday < 0)
1201 /* Generate string value for T using time_t arithmetic;
1202 this works even if sizeof (long) < sizeof (time_t). */
1204 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1205 negative_number = t < 0;
1211 *--bufp = (negative_number ? -d : d) + L_('0');
1216 always_output_a_sign = false;
1217 goto do_number_sign_and_padding;
1221 if (modifier == L_('O'))
1224 if (! (modifier == L_('E')
1226 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1228 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1231 goto underlying_strftime;
1234 subfmt = L_("%H:%M:%S");
1242 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1245 if (modifier == L_('E'))
1248 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1253 if (modifier == L_('E'))
1256 /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
1257 is a leap year, except that YEAR and YEAR - 1 both work
1258 correctly even when (tp->tm_year + TM_YEAR_BASE) would
1260 int year = (tp->tm_year
1262 ? TM_YEAR_BASE % 400
1263 : TM_YEAR_BASE % 400 - 400));
1264 int year_adjust = 0;
1265 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1269 /* This ISO week belongs to the previous year. */
1271 days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
1276 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1280 /* This ISO week belongs to the next year. */
1290 int yy = (tp->tm_year % 100 + year_adjust) % 100;
1291 DO_YEARISH (2, false,
1294 : tp->tm_year < -TM_YEAR_BASE - year_adjust
1300 DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
1301 (tp->tm_year + (unsigned int) TM_YEAR_BASE
1305 DO_NUMBER (2, days / 7 + 1);
1310 if (modifier == L_('E'))
1313 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1316 if (modifier == L_('E'))
1319 DO_NUMBER (1, tp->tm_wday);
1322 if (modifier == L_('E'))
1324 #if HAVE_STRUCT_ERA_ENTRY
1325 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1328 # ifdef COMPILE_WIDE
1329 subfmt = era->era_wformat;
1331 subfmt = era->era_format;
1338 goto underlying_strftime;
1341 if (modifier == L_('O'))
1344 DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE,
1345 tp->tm_year + (unsigned int) TM_YEAR_BASE);
1348 if (modifier == L_('E'))
1350 #if HAVE_STRUCT_ERA_ENTRY
1351 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1354 int delta = tp->tm_year - era->start_date[0];
1357 DO_NUMBER (2, (era->offset
1358 + delta * era->absolute_direction));
1361 goto underlying_strftime;
1366 int yy = tp->tm_year % 100;
1368 yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
1369 DO_YEARISH (2, false, yy);
1381 /* The zone string is always given in multibyte form. We have
1382 to transform it first. */
1385 widen (zone, wczone, len);
1389 cpy (strlen (zone), zone);
1394 /* :, ::, and ::: are valid only just before 'z'.
1395 :::: etc. are rejected later. */
1396 for (colons = 1; f[colons] == L_(':'); colons++)
1398 if (f[colons] != L_('z'))
1401 goto do_z_conversion;
1407 if (tp->tm_isdst < 0)
1416 diff = tp->tm_gmtoff;
1426 /* POSIX.1 requires that local time zone information be used as
1427 though strftime called tzset. */
1428 # ifndef my_strftime
1432 *tzset_called = true;
1438 lt = mktime_z (tz, <m);
1439 if (ltm.tm_wday < 0 || ! localtime_rz (0, <, >m))
1441 diff = tm_diff (<m, >m);
1445 negative_number = diff < 0 || (diff == 0 && *zone == '-');
1446 hour_diff = diff / 60 / 60;
1447 min_diff = diff / 60 % 60;
1448 sec_diff = diff % 60;
1453 DO_TZ_OFFSET (5, 0, hour_diff * 100 + min_diff);
1455 case 1: tz_hh_mm: /* +hh:mm */
1456 DO_TZ_OFFSET (6, 04, hour_diff * 100 + min_diff);
1458 case 2: tz_hh_mm_ss: /* +hh:mm:ss */
1459 DO_TZ_OFFSET (9, 024,
1460 hour_diff * 10000 + min_diff * 100 + sec_diff);
1462 case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */
1467 DO_TZ_OFFSET (3, 0, hour_diff);
1474 case L_('\0'): /* GNU extension: % at end of format. */
1478 /* Unknown format; output the format, including the '%',
1479 since this is most likely the right thing to do if a
1480 multibyte string has been misparsed. */
1484 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1486 cpy (flen, &f[1 - flen]);
1493 if (p && maxsize != 0)
1497 errno = saved_errno;