1 /* Copyright (C) 1991-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
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 <https://www.gnu.org/licenses/>. */
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 # include "../locale/localeinfo.h"
28 # include "fprintftime.h"
30 # include "strftime.h"
32 # include "time-internal.h"
39 #if HAVE_TZNAME && !HAVE_DECL_TZNAME
40 extern char *tzname
[];
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.
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
55 #if !(defined __osf__ && 0)
56 # define MULTIBYTE_IS_FORMAT_SAFE 1
58 #define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE)
62 static const mbstate_t mbstate_zero
;
71 #include "attribute.h"
76 # define CHAR_T wchar_t
77 # define UCHAR_T unsigned int
78 # define L_(Str) L##Str
79 # define NLW(Sym) _NL_W##Sym
81 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
82 # define STRLEN(s) __wcslen (s)
86 # define UCHAR_T unsigned char
89 # define ABALTMON_1 _NL_ABALTMON_1
91 # define MEMCPY(d, s, n) memcpy (d, s, n)
92 # define STRLEN(s) strlen (s)
96 /* Shift A right by B bits portably, by dividing A by 2**B and
97 truncating towards minus infinity. A and B should be free of side
98 effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
99 INT_BITS is the number of useful bits in an int. GNU code can
100 assume that INT_BITS is at least 32.
102 ISO C99 says that A >> B is implementation-defined if A < 0. Some
103 implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
104 right in the usual way when A < 0, so SHR falls back on division if
105 ordinary A >> B doesn't seem to be the usual signed shift. */
109 : ((a) + ((a) < 0)) / (1 << (b)) - ((a) < 0))
111 #define TM_YEAR_BASE 1900
114 /* Nonzero if YEAR is a leap year (every 4 years,
115 except every 100th isn't, and every 400th is). */
116 # define __isleap(year) \
117 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
122 # define mktime_z(tz, tm) mktime (tm)
123 # define tzname __tzname
124 # define tzset __tzset
128 # define FPRINTFTIME 0
132 # define STREAM_OR_CHAR_T FILE
133 # define STRFTIME_ARG(x) /* empty */
135 # define STREAM_OR_CHAR_T CHAR_T
136 # define STRFTIME_ARG(x) x,
140 # define memset_byte(P, Len, Byte) \
141 do { size_t _i; for (_i = 0; _i < Len; _i++) fputc (Byte, P); } while (0)
142 # define memset_space(P, Len) memset_byte (P, Len, ' ')
143 # define memset_zero(P, Len) memset_byte (P, Len, '0')
144 #elif defined COMPILE_WIDE
145 # define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
146 # define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
148 # define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
149 # define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
153 # define advance(P, N)
155 # define advance(P, N) ((P) += (N))
158 #define add(n, f) width_add (width, n, f)
159 #define width_add(width, n, f) \
163 size_t _w = pad == L_('-') || width < 0 ? 0 : width; \
164 size_t _incr = _n < _w ? _w : _n; \
165 if (_incr >= maxsize - i) \
174 size_t _delta = _w - _n; \
175 if (pad == L_('0') || pad == L_('+')) \
176 memset_zero (p, _delta); \
178 memset_space (p, _delta); \
186 #define add1(c) width_add1 (width, c)
188 # define width_add1(width, c) width_add (width, 1, fputc (c, p))
190 # define width_add1(width, c) width_add (width, 1, *p = c)
193 #define cpy(n, s) width_cpy (width, n, s)
195 # define width_cpy(width, n, s) \
196 width_add (width, n, \
200 fwrite_lowcase (p, (s), _n); \
201 else if (to_uppcase) \
202 fwrite_uppcase (p, (s), _n); \
205 /* Ignore the value of fwrite. The caller can determine whether \
206 an error occurred by inspecting ferror (P). All known fwrite \
207 implementations set the stream's error indicator when they \
208 fail due to ENOMEM etc., even though C11 and POSIX.1-2008 do \
209 not require this. */ \
210 fwrite (s, _n, 1, p); \
216 # define width_cpy(width, n, s) \
217 width_add (width, n, \
219 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
220 else if (to_uppcase) \
221 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
223 MEMCPY ((void *) p, (void const *) (s), _n))
227 # ifndef USE_IN_EXTENDED_LOCALE_MODEL
228 # undef __mbsrtowcs_l
229 # define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
231 # define widen(os, ws, l) \
234 const char *__s = os; \
235 memset (&__st, '\0', sizeof (__st)); \
236 l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
237 ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \
238 (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
243 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
244 /* We use this code also for the extended locale handling where the
245 function gets as an additional argument the locale which has to be
246 used. To access the values we have to redefine the _NL_CURRENT
248 # define strftime __strftime_l
249 # define wcsftime __wcsftime_l
251 # define _NL_CURRENT(category, item) \
252 (current->values[_NL_ITEM_INDEX (item)].string)
253 # define LOCALE_PARAM , locale_t loc
254 # define LOCALE_ARG , loc
255 # define HELPER_LOCALE_ARG , current
257 # define LOCALE_PARAM
260 # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
262 # define HELPER_LOCALE_ARG
267 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
268 # define TOUPPER(Ch, L) __towupper_l (Ch, L)
269 # define TOLOWER(Ch, L) __towlower_l (Ch, L)
271 # define TOUPPER(Ch, L) towupper (Ch)
272 # define TOLOWER(Ch, L) towlower (Ch)
275 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
276 # define TOUPPER(Ch, L) __toupper_l (Ch, L)
277 # define TOLOWER(Ch, L) __tolower_l (Ch, L)
279 # define TOUPPER(Ch, L) toupper (Ch)
280 # define TOLOWER(Ch, L) tolower (Ch)
283 /* We don't use 'isdigit' here since the locale dependent
284 interpretation is not what we want here. We only need to accept
285 the arabic digits in the ASCII range. One day there is perhaps a
286 more reliable way to accept other sets of digits. */
287 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
291 fwrite_lowcase (FILE *fp
, const CHAR_T
*src
, size_t len
)
295 fputc (TOLOWER ((UCHAR_T
) *src
, loc
), fp
);
301 fwrite_uppcase (FILE *fp
, const CHAR_T
*src
, size_t len
)
305 fputc (TOUPPER ((UCHAR_T
) *src
, loc
), fp
);
310 static CHAR_T
*memcpy_lowcase (CHAR_T
*dest
, const CHAR_T
*src
,
311 size_t len LOCALE_PARAM
);
314 memcpy_lowcase (CHAR_T
*dest
, const CHAR_T
*src
, size_t len LOCALE_PARAM
)
317 dest
[len
] = TOLOWER ((UCHAR_T
) src
[len
], loc
);
321 static CHAR_T
*memcpy_uppcase (CHAR_T
*dest
, const CHAR_T
*src
,
322 size_t len LOCALE_PARAM
);
325 memcpy_uppcase (CHAR_T
*dest
, const CHAR_T
*src
, size_t len LOCALE_PARAM
)
328 dest
[len
] = TOUPPER ((UCHAR_T
) src
[len
], loc
);
335 /* Yield the difference between *A and *B,
336 measured in seconds, ignoring leap seconds. */
337 # define tm_diff ftime_tm_diff
338 static int tm_diff (const struct tm
*, const struct tm
*);
340 tm_diff (const struct tm
*a
, const struct tm
*b
)
342 /* Compute intervening leap days correctly even if year is negative.
343 Take care to avoid int overflow in leap day calculations,
344 but it's OK to assume that A and B are close to each other. */
345 int a4
= SHR (a
->tm_year
, 2) + SHR (TM_YEAR_BASE
, 2) - ! (a
->tm_year
& 3);
346 int b4
= SHR (b
->tm_year
, 2) + SHR (TM_YEAR_BASE
, 2) - ! (b
->tm_year
& 3);
347 int a100
= (a4
+ (a4
< 0)) / 25 - (a4
< 0);
348 int b100
= (b4
+ (b4
< 0)) / 25 - (b4
< 0);
349 int a400
= SHR (a100
, 2);
350 int b400
= SHR (b100
, 2);
351 int intervening_leap_days
= (a4
- b4
) - (a100
- b100
) + (a400
- b400
);
352 int years
= a
->tm_year
- b
->tm_year
;
353 int days
= (365 * years
+ intervening_leap_days
354 + (a
->tm_yday
- b
->tm_yday
));
355 return (60 * (60 * (24 * days
+ (a
->tm_hour
- b
->tm_hour
))
356 + (a
->tm_min
- b
->tm_min
))
357 + (a
->tm_sec
- b
->tm_sec
));
359 #endif /* ! HAVE_TM_GMTOFF */
363 /* The number of days from the first day of the first ISO week of this
364 year to the year day YDAY with week day WDAY. ISO weeks start on
365 Monday; the first ISO week has the year's first Thursday. YDAY may
366 be as small as YDAY_MINIMUM. */
367 #define ISO_WEEK_START_WDAY 1 /* Monday */
368 #define ISO_WEEK1_WDAY 4 /* Thursday */
369 #define YDAY_MINIMUM (-366)
370 static int iso_week_days (int, int);
371 #if defined __GNUC__ || defined __clang__
375 iso_week_days (int yday
, int wday
)
377 /* Add enough to the first operand of % to make it nonnegative. */
378 int big_enough_multiple_of_7
= (-YDAY_MINIMUM
/ 7 + 2) * 7;
380 - (yday
- wday
+ ISO_WEEK1_WDAY
+ big_enough_multiple_of_7
) % 7
381 + ISO_WEEK1_WDAY
- ISO_WEEK_START_WDAY
);
385 /* When compiling this file, GNU applications can #define my_strftime
386 to a symbol (typically nstrftime) to get an extended strftime with
387 extra arguments TZ and NS. */
391 # define my_strftime fprintftime
395 # define extra_args , tz, ns
396 # define extra_args_spec , timezone_t tz, int ns
398 # if defined COMPILE_WIDE
399 # define my_strftime wcsftime
400 # define nl_get_alt_digit _nl_get_walt_digit
402 # define my_strftime strftime
403 # define nl_get_alt_digit _nl_get_alt_digit
406 # define extra_args_spec
407 /* We don't have this information in general. */
412 static size_t __strftime_internal (STREAM_OR_CHAR_T
*, STRFTIME_ARG (size_t)
413 const CHAR_T
*, const struct tm
*,
414 bool, int, int, bool *
415 extra_args_spec LOCALE_PARAM
);
417 /* Write information from TP into S according to the format
418 string FORMAT, writing no more that MAXSIZE characters
419 (including the terminating '\0') and returning number of
420 characters written. If S is NULL, nothing will be written
421 anywhere, so to determine how many characters would be
422 written, use NULL for S and (size_t) -1 for MAXSIZE. */
424 my_strftime (STREAM_OR_CHAR_T
*s
, STRFTIME_ARG (size_t maxsize
)
425 const CHAR_T
*format
,
426 const struct tm
*tp extra_args_spec LOCALE_PARAM
)
428 bool tzset_called
= false;
429 return __strftime_internal (s
, STRFTIME_ARG (maxsize
) format
, tp
, false,
430 0, -1, &tzset_called extra_args LOCALE_ARG
);
432 #if defined _LIBC && ! FPRINTFTIME
433 libc_hidden_def (my_strftime
)
436 /* Just like my_strftime, above, but with more parameters.
437 UPCASE indicates that the result should be converted to upper case.
438 YR_SPEC and WIDTH specify the padding and width for the year.
439 *TZSET_CALLED indicates whether tzset has been called here. */
441 __strftime_internal (STREAM_OR_CHAR_T
*s
, STRFTIME_ARG (size_t maxsize
)
442 const CHAR_T
*format
,
443 const struct tm
*tp
, bool upcase
,
444 int yr_spec
, int width
, bool *tzset_called
445 extra_args_spec LOCALE_PARAM
)
447 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
448 struct __locale_data
*const current
= loc
->__locales
[LC_TIME
];
451 size_t maxsize
= (size_t) -1;
454 int saved_errno
= errno
;
455 int hour12
= tp
->tm_hour
;
457 /* We cannot make the following values variables since we must delay
458 the evaluation of these values until really needed since some
459 expressions might not be valid in every situation. The 'struct tm'
460 might be generated by a strptime() call that initialized
461 only a few elements. Dereference the pointers only if the format
462 requires this. Then it is ok to fail if the pointers are invalid. */
464 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
465 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
467 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
468 ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
470 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
471 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
473 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
474 ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
475 # define a_altmonth \
476 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
477 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABALTMON_1) + tp->tm_mon)))
478 # define f_altmonth \
479 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
480 ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon)))
482 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
483 ? NLW(PM_STR) : NLW(AM_STR)))
485 # define aw_len STRLEN (a_wkday)
486 # define am_len STRLEN (a_month)
487 # define aam_len STRLEN (a_altmonth)
488 # define ap_len STRLEN (ampm)
491 char **tzname_vec
= tzname
;
495 STREAM_OR_CHAR_T
*p
= s
;
497 #if DO_MULTIBYTE && !defined COMPILE_WIDE
498 const char *format_end
= NULL
;
503 /* The POSIX test suite assumes that setting
504 the environment variable TZ to a new value before calling strftime()
505 will influence the result (the %Z format) even if the information in
506 TP is computed with a totally different time zone.
507 This is bogus: though POSIX allows bad behavior like this,
508 POSIX does not require it. Do the right thing instead. */
509 zone
= (const char *) tp
->tm_zone
;
514 if (! (zone
&& *zone
))
520 /* Infer the zone name from *TZ instead of from TZNAME. */
521 tzname_vec
= tz
->tzname_copy
;
524 /* The tzset() call might have changed the value. */
525 if (!(zone
&& *zone
) && tp
->tm_isdst
>= 0)
527 /* POSIX.1 requires that local time zone information be used as
528 though strftime called tzset. */
533 *tzset_called
= true;
536 zone
= tzname_vec
[tp
->tm_isdst
!= 0];
548 for (f
= format
; *f
!= '\0'; width
= -1, f
++)
550 int pad
= 0; /* Padding for number ('_', '-', '+', '0', or 0). */
551 int modifier
; /* Field modifier ('E', 'O', or 0). */
552 int digits
= 0; /* Max digits for numeric format. */
553 int number_value
; /* Numeric value to be printed. */
554 unsigned int u_number_value
; /* (unsigned int) number_value. */
555 bool negative_number
; /* The number is negative. */
556 bool always_output_a_sign
; /* +/- should always be output. */
557 int tz_colon_mask
; /* Bitmask of where ':' should appear. */
558 const CHAR_T
*subfmt
;
561 + 2 /* for the two colons in a %::z or %:::z time zone */
562 + (sizeof (int) < sizeof (time_t)
563 ? INT_STRLEN_BOUND (time_t)
564 : INT_STRLEN_BOUND (int))];
565 bool to_lowcase
= false;
566 bool to_uppcase
= upcase
;
568 bool change_case
= false;
572 #if DO_MULTIBYTE && !defined COMPILE_WIDE
578 case L_('\b'): case L_('\t'): case L_('\n'):
579 case L_('\v'): case L_('\f'): case L_('\r'):
580 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
581 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
582 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
583 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
584 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
585 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
586 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
587 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
588 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
589 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
590 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
591 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
592 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
593 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
594 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
595 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
596 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
597 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
599 /* The C Standard requires these 98 characters (plus '%') to
600 be in the basic execution character set. None of these
601 characters can start a multibyte sequence, so they need
602 not be analyzed further. */
607 /* Copy this multibyte sequence until we reach its end, find
608 an error, or come back to the initial shift state. */
610 mbstate_t mbstate
= mbstate_zero
;
615 format_end
= f
+ strlen (f
) + 1;
616 fsize
= format_end
- f
;
620 size_t bytes
= mbrlen (f
+ len
, fsize
- len
, &mbstate
);
625 if (bytes
== (size_t) -2)
627 len
+= strlen (f
+ len
);
631 if (bytes
== (size_t) -1)
639 while (! mbsinit (&mbstate
));
647 #else /* ! DO_MULTIBYTE */
649 /* Either multibyte encodings are not supported, they are
650 safe for formats, so any non-'%' byte can be copied through,
651 or this is the wide character version. */
658 #endif /* ! DO_MULTIBYTE */
660 /* Check for flags that can modify a format. */
665 /* This influences the number formats. */
673 /* This changes textual output. */
692 if (INT_MULTIPLY_WRAPV (width
, 10, &width
)
693 || INT_ADD_WRAPV (width
, *f
- L_('0'), &width
))
697 while (ISDIGIT (*f
));
700 /* Check for modifiers. */
713 /* Now do the specified format. */
717 #define DO_NUMBER(d, v) \
725 #define DO_SIGNED_NUMBER(d, negative, v) \
726 DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_signed_number)
727 #define DO_YEARISH(d, negative, v) \
728 DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_yearish)
729 #define DO_MAYBE_SIGNED_NUMBER(d, negative, v, label) \
733 negative_number = negative; \
734 u_number_value = v; \
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) \
746 tz_colon_mask = mask; \
747 u_number_value = v; \
751 #define DO_NUMBER_SPACEPAD(d, v) \
756 goto do_number_spacepad; \
775 cpy (aw_len
, a_wkday
);
778 goto underlying_strftime
;
790 cpy (STRLEN (f_wkday
), f_wkday
);
793 goto underlying_strftime
;
803 if (modifier
== L_('E'))
806 if (modifier
== L_('O'))
807 cpy (aam_len
, a_altmonth
);
809 cpy (am_len
, a_month
);
812 goto underlying_strftime
;
816 if (modifier
== L_('E'))
824 if (modifier
== L_('O'))
825 cpy (STRLEN (f_altmonth
), f_altmonth
);
827 cpy (STRLEN (f_month
), f_month
);
830 goto underlying_strftime
;
834 if (modifier
== L_('O'))
837 if (! (modifier
== L_('E')
839 (const CHAR_T
*) _NL_CURRENT (LC_TIME
,
842 subfmt
= (const CHAR_T
*) _NL_CURRENT (LC_TIME
, NLW(D_T_FMT
));
844 goto underlying_strftime
;
851 size_t len
= __strftime_internal (NULL
, STRFTIME_ARG ((size_t) -1)
852 subfmt
, tp
, to_uppcase
,
853 pad
, subwidth
, tzset_called
854 extra_args LOCALE_ARG
);
855 add (len
, __strftime_internal (p
,
856 STRFTIME_ARG (maxsize
- i
)
857 subfmt
, tp
, to_uppcase
,
858 pad
, subwidth
, tzset_called
859 extra_args LOCALE_ARG
));
863 #if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
866 /* The relevant information is available only via the
867 underlying strftime implementation, so use that. */
870 char ubuf
[1024]; /* enough for any single format in practice */
872 /* Make sure we're calling the actual underlying strftime.
873 In some cases, config.h contains something like
874 "#define strftime rpl_strftime". */
880 /* The space helps distinguish strftime failure from empty
888 len
= strftime (ubuf
, sizeof ubuf
, ufmt
, tp
);
890 cpy (len
- 1, ubuf
+ 1);
896 if (modifier
== L_('E'))
898 #if HAVE_STRUCT_ERA_ENTRY
899 struct era_entry
*era
= _nl_get_era_entry (tp HELPER_LOCALE_ARG
);
903 size_t len
= __wcslen (era
->era_wname
);
904 cpy (len
, era
->era_wname
);
906 size_t len
= strlen (era
->era_name
);
907 cpy (len
, era
->era_name
);
912 goto underlying_strftime
;
917 bool negative_year
= tp
->tm_year
< - TM_YEAR_BASE
;
918 bool zero_thru_1899
= !negative_year
& (tp
->tm_year
< 0);
919 int century
= ((tp
->tm_year
- 99 * zero_thru_1899
) / 100
920 + TM_YEAR_BASE
/ 100);
921 DO_YEARISH (2, negative_year
, century
);
925 if (modifier
== L_('O'))
928 if (! (modifier
== L_('E')
930 (const CHAR_T
*) _NL_CURRENT (LC_TIME
, NLW(ERA_D_FMT
)))
932 subfmt
= (const CHAR_T
*) _NL_CURRENT (LC_TIME
, NLW(D_FMT
));
935 goto underlying_strftime
;
940 subfmt
= L_("%m/%d/%y");
944 if (modifier
== L_('E'))
947 DO_NUMBER (2, tp
->tm_mday
);
950 if (modifier
== L_('E'))
953 DO_NUMBER_SPACEPAD (2, tp
->tm_mday
);
955 /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
956 and then jump to one of these labels. */
959 always_output_a_sign
= true;
967 && ((digits
== 2 ? 99 : 9999) < u_number_value
969 goto do_maybe_signed_number
;
976 /* Format NUMBER_VALUE according to the MODIFIER flag. */
977 negative_number
= number_value
< 0;
978 u_number_value
= number_value
;
981 always_output_a_sign
= false;
983 do_maybe_signed_number
:
987 /* Format U_NUMBER_VALUE according to the MODIFIER flag.
988 NEGATIVE_NUMBER is nonzero if the original number was
989 negative; in this case it was converted directly to
990 unsigned int (i.e., modulo (UINT_MAX + 1)) without
992 if (modifier
== L_('O') && !negative_number
)
995 /* Get the locale specific alternate representation of
996 the number. If none exist NULL is returned. */
997 const CHAR_T
*cp
= nl_get_alt_digit (u_number_value
1002 size_t digitlen
= STRLEN (cp
);
1010 goto underlying_strftime
;
1014 bufp
= buf
+ sizeof (buf
) / sizeof (buf
[0]);
1016 if (negative_number
)
1017 u_number_value
= - u_number_value
;
1021 if (tz_colon_mask
& 1)
1023 tz_colon_mask
>>= 1;
1024 *--bufp
= u_number_value
% 10 + L_('0');
1025 u_number_value
/= 10;
1027 while (u_number_value
!= 0 || tz_colon_mask
!= 0);
1029 do_number_sign_and_padding
:
1036 CHAR_T sign_char
= (negative_number
? L_('-')
1037 : always_output_a_sign
? L_('+')
1039 int numlen
= buf
+ sizeof buf
/ sizeof buf
[0] - bufp
;
1040 int shortage
= width
- !!sign_char
- numlen
;
1041 int padding
= pad
== L_('-') || shortage
<= 0 ? 0 : shortage
;
1048 memset_space (p
, padding
);
1052 width_add1 (0, sign_char
);
1063 if (pad
== 0 && width
< 0)
1070 subwidth
= width
- 6;
1074 subfmt
= L_("%Y-%m-%d");
1075 goto subformat_width
;
1078 if (modifier
== L_('E'))
1081 DO_NUMBER (2, tp
->tm_hour
);
1084 if (modifier
== L_('E'))
1087 DO_NUMBER (2, hour12
);
1089 case L_('k'): /* GNU extension. */
1090 if (modifier
== L_('E'))
1093 DO_NUMBER_SPACEPAD (2, tp
->tm_hour
);
1095 case L_('l'): /* GNU extension. */
1096 if (modifier
== L_('E'))
1099 DO_NUMBER_SPACEPAD (2, hour12
);
1102 if (modifier
== L_('E'))
1105 DO_SIGNED_NUMBER (3, tp
->tm_yday
< -1, tp
->tm_yday
+ 1U);
1108 if (modifier
== L_('E'))
1111 DO_NUMBER (2, tp
->tm_min
);
1114 if (modifier
== L_('E'))
1117 DO_SIGNED_NUMBER (2, tp
->tm_mon
< -1, tp
->tm_mon
+ 1U);
1120 case L_('N'): /* GNU extension. */
1121 if (modifier
== L_('E'))
1124 int n
= ns
, ns_digits
= 9;
1127 int ndigs
= ns_digits
;
1128 while (width
< ndigs
|| (1 < ndigs
&& n
% 10 == 0))
1130 for (int j
= ndigs
; 0 < j
; j
--)
1131 buf
[j
- 1] = n
% 10 + L_('0'), n
/= 10;
1134 width_cpy (0, ndigs
, buf
);
1135 width_add (width
- ndigs
, 0, (void) 0);
1147 format_char
= L_('p');
1160 goto underlying_strftime
;
1163 case L_('q'): /* GNU extension. */
1164 DO_SIGNED_NUMBER (1, false, ((tp
->tm_mon
* 11) >> 5) + 1);
1168 subfmt
= L_("%H:%M");
1173 if (*(subfmt
= (const CHAR_T
*) _NL_CURRENT (LC_TIME
,
1176 subfmt
= L_("%I:%M:%S %p");
1179 goto underlying_strftime
;
1183 if (modifier
== L_('E'))
1186 DO_NUMBER (2, tp
->tm_sec
);
1188 case L_('s'): /* GNU extension. */
1195 t
= mktime_z (tz
, <m
);
1196 if (ltm
.tm_yday
< 0)
1202 /* Generate string value for T using time_t arithmetic;
1203 this works even if sizeof (long) < sizeof (time_t). */
1205 bufp
= buf
+ sizeof (buf
) / sizeof (buf
[0]);
1206 negative_number
= t
< 0;
1212 *--bufp
= (negative_number
? -d
: d
) + L_('0');
1217 always_output_a_sign
= false;
1218 goto do_number_sign_and_padding
;
1222 if (modifier
== L_('O'))
1225 if (! (modifier
== L_('E')
1227 (const CHAR_T
*) _NL_CURRENT (LC_TIME
, NLW(ERA_T_FMT
)))
1229 subfmt
= (const CHAR_T
*) _NL_CURRENT (LC_TIME
, NLW(T_FMT
));
1232 goto underlying_strftime
;
1235 subfmt
= L_("%H:%M:%S");
1243 DO_NUMBER (1, (tp
->tm_wday
- 1 + 7) % 7 + 1);
1246 if (modifier
== L_('E'))
1249 DO_NUMBER (2, (tp
->tm_yday
- tp
->tm_wday
+ 7) / 7);
1254 if (modifier
== L_('E'))
1257 /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
1258 is a leap year, except that YEAR and YEAR - 1 both work
1259 correctly even when (tp->tm_year + TM_YEAR_BASE) would
1261 int year
= (tp
->tm_year
1263 ? TM_YEAR_BASE
% 400
1264 : TM_YEAR_BASE
% 400 - 400));
1265 int year_adjust
= 0;
1266 int days
= iso_week_days (tp
->tm_yday
, tp
->tm_wday
);
1270 /* This ISO week belongs to the previous year. */
1272 days
= iso_week_days (tp
->tm_yday
+ (365 + __isleap (year
- 1)),
1277 int d
= iso_week_days (tp
->tm_yday
- (365 + __isleap (year
)),
1281 /* This ISO week belongs to the next year. */
1291 int yy
= (tp
->tm_year
% 100 + year_adjust
) % 100;
1292 DO_YEARISH (2, false,
1295 : tp
->tm_year
< -TM_YEAR_BASE
- year_adjust
1301 DO_YEARISH (4, tp
->tm_year
< -TM_YEAR_BASE
- year_adjust
,
1302 (tp
->tm_year
+ (unsigned int) TM_YEAR_BASE
1306 DO_NUMBER (2, days
/ 7 + 1);
1311 if (modifier
== L_('E'))
1314 DO_NUMBER (2, (tp
->tm_yday
- (tp
->tm_wday
- 1 + 7) % 7 + 7) / 7);
1317 if (modifier
== L_('E'))
1320 DO_NUMBER (1, tp
->tm_wday
);
1323 if (modifier
== L_('E'))
1325 #if HAVE_STRUCT_ERA_ENTRY
1326 struct era_entry
*era
= _nl_get_era_entry (tp HELPER_LOCALE_ARG
);
1329 # ifdef COMPILE_WIDE
1330 subfmt
= era
->era_wformat
;
1332 subfmt
= era
->era_format
;
1339 goto underlying_strftime
;
1342 if (modifier
== L_('O'))
1345 DO_YEARISH (4, tp
->tm_year
< -TM_YEAR_BASE
,
1346 tp
->tm_year
+ (unsigned int) TM_YEAR_BASE
);
1349 if (modifier
== L_('E'))
1351 #if HAVE_STRUCT_ERA_ENTRY
1352 struct era_entry
*era
= _nl_get_era_entry (tp HELPER_LOCALE_ARG
);
1355 int delta
= tp
->tm_year
- era
->start_date
[0];
1358 DO_NUMBER (2, (era
->offset
1359 + delta
* era
->absolute_direction
));
1362 goto underlying_strftime
;
1367 int yy
= tp
->tm_year
% 100;
1369 yy
= tp
->tm_year
< - TM_YEAR_BASE
? -yy
: yy
+ 100;
1370 DO_YEARISH (2, false, yy
);
1382 /* The zone string is always given in multibyte form. We have
1383 to transform it first. */
1386 widen (zone
, wczone
, len
);
1390 cpy (strlen (zone
), zone
);
1395 /* :, ::, and ::: are valid only just before 'z'.
1396 :::: etc. are rejected later. */
1397 for (colons
= 1; f
[colons
] == L_(':'); colons
++)
1399 if (f
[colons
] != L_('z'))
1402 goto do_z_conversion
;
1408 if (tp
->tm_isdst
< 0)
1417 diff
= tp
->tm_gmtoff
;
1427 /* POSIX.1 requires that local time zone information be used as
1428 though strftime called tzset. */
1429 # ifndef my_strftime
1433 *tzset_called
= true;
1439 lt
= mktime_z (tz
, <m
);
1440 if (ltm
.tm_wday
< 0 || ! localtime_rz (0, <
, >m
))
1442 diff
= tm_diff (<m
, >m
);
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;
1454 DO_TZ_OFFSET (5, 0, hour_diff
* 100 + min_diff
);
1456 case 1: tz_hh_mm
: /* +hh:mm */
1457 DO_TZ_OFFSET (6, 04, hour_diff
* 100 + min_diff
);
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
);
1463 case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */
1468 DO_TZ_OFFSET (3, 0, hour_diff
);
1475 case L_('\0'): /* GNU extension: % at end of format. */
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. */
1485 for (flen
= 1; f
[1 - flen
] != L_('%'); flen
++)
1487 cpy (flen
, &f
[1 - flen
]);
1494 if (p
&& maxsize
!= 0)
1498 errno
= saved_errno
;