nstrftime, time_rz: Avoid using an obsolete Autoconf macro.
[gnulib.git] / lib / nstrftime.c
blob7ef75290bcc2bb1d5980b88b685358c06c6b07fb
1 /* Copyright (C) 1991-2021 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/>. */
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_STRUCT_TM_TM_ZONE 1
23 # define HAVE_TZNAME 1
24 # include "../locale/localeinfo.h"
25 #else
26 # include <config.h>
27 # if FPRINTFTIME
28 # include "fprintftime.h"
29 # else
30 # include "strftime.h"
31 # endif
32 # include "time-internal.h"
33 #endif
35 #include <ctype.h>
36 #include <errno.h>
37 #include <time.h>
39 #if HAVE_TZNAME && !HAVE_DECL_TZNAME
40 extern char *tzname[];
41 #endif
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
54 it. */
55 #if !(defined __osf__ && 0)
56 # define MULTIBYTE_IS_FORMAT_SAFE 1
57 #endif
58 #define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE)
60 #if DO_MULTIBYTE
61 # include <wchar.h>
62 static const mbstate_t mbstate_zero;
63 #endif
65 #include <limits.h>
66 #include <stddef.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <stdbool.h>
71 #include "attribute.h"
72 #include <intprops.h>
74 #ifdef COMPILE_WIDE
75 # include <endian.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)
84 #else
85 # define CHAR_T char
86 # define UCHAR_T unsigned char
87 # define L_(Str) Str
88 # define NLW(Sym) Sym
89 # define ABALTMON_1 _NL_ABALTMON_1
91 # define MEMCPY(d, s, n) memcpy (d, s, n)
92 # define STRLEN(s) strlen (s)
94 #endif
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. */
106 #define SHR(a, b) \
107 (-1 >> 1 == -1 \
108 ? (a) >> (b) \
109 : ((a) + ((a) < 0)) / (1 << (b)) - ((a) < 0))
111 #define TM_YEAR_BASE 1900
113 #ifndef __isleap
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))
118 #endif
121 #ifdef _LIBC
122 # define mktime_z(tz, tm) mktime (tm)
123 # define tzname __tzname
124 # define tzset __tzset
125 #endif
127 #ifndef FPRINTFTIME
128 # define FPRINTFTIME 0
129 #endif
131 #if FPRINTFTIME
132 # define STREAM_OR_CHAR_T FILE
133 # define STRFTIME_ARG(x) /* empty */
134 #else
135 # define STREAM_OR_CHAR_T CHAR_T
136 # define STRFTIME_ARG(x) x,
137 #endif
139 #if FPRINTFTIME
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))
147 #else
148 # define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
149 # define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
150 #endif
152 #if FPRINTFTIME
153 # define advance(P, N)
154 #else
155 # define advance(P, N) ((P) += (N))
156 #endif
158 #define add(n, f) width_add (width, n, f)
159 #define width_add(width, n, f) \
160 do \
162 size_t _n = (n); \
163 size_t _w = pad == L_('-') || width < 0 ? 0 : width; \
164 size_t _incr = _n < _w ? _w : _n; \
165 if (_incr >= maxsize - i) \
167 errno = ERANGE; \
168 return 0; \
170 if (p) \
172 if (_n < _w) \
174 size_t _delta = _w - _n; \
175 if (pad == L_('0') || pad == L_('+')) \
176 memset_zero (p, _delta); \
177 else \
178 memset_space (p, _delta); \
180 f; \
181 advance (p, _n); \
183 i += _incr; \
184 } while (0)
186 #define add1(c) width_add1 (width, c)
187 #if FPRINTFTIME
188 # define width_add1(width, c) width_add (width, 1, fputc (c, p))
189 #else
190 # define width_add1(width, c) width_add (width, 1, *p = c)
191 #endif
193 #define cpy(n, s) width_cpy (width, n, s)
194 #if FPRINTFTIME
195 # define width_cpy(width, n, s) \
196 width_add (width, n, \
197 do \
199 if (to_lowcase) \
200 fwrite_lowcase (p, (s), _n); \
201 else if (to_uppcase) \
202 fwrite_uppcase (p, (s), _n); \
203 else \
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); \
213 while (0) \
215 #else
216 # define width_cpy(width, n, s) \
217 width_add (width, n, \
218 if (to_lowcase) \
219 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
220 else if (to_uppcase) \
221 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
222 else \
223 MEMCPY ((void *) p, (void const *) (s), _n))
224 #endif
226 #ifdef COMPILE_WIDE
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)
230 # endif
231 # define widen(os, ws, l) \
233 mbstate_t __st; \
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); \
240 #endif
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
247 macro. */
248 # define strftime __strftime_l
249 # define wcsftime __wcsftime_l
250 # undef _NL_CURRENT
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
256 #else
257 # define LOCALE_PARAM
258 # define LOCALE_ARG
259 # ifdef _LIBC
260 # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
261 # else
262 # define HELPER_LOCALE_ARG
263 # endif
264 #endif
266 #ifdef COMPILE_WIDE
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)
270 # else
271 # define TOUPPER(Ch, L) towupper (Ch)
272 # define TOLOWER(Ch, L) towlower (Ch)
273 # endif
274 #else
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)
278 # else
279 # define TOUPPER(Ch, L) toupper (Ch)
280 # define TOLOWER(Ch, L) tolower (Ch)
281 # endif
282 #endif
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)
289 #if FPRINTFTIME
290 static void
291 fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len)
293 while (len-- > 0)
295 fputc (TOLOWER ((UCHAR_T) *src, loc), fp);
296 ++src;
300 static void
301 fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len)
303 while (len-- > 0)
305 fputc (TOUPPER ((UCHAR_T) *src, loc), fp);
306 ++src;
309 #else
310 static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
311 size_t len LOCALE_PARAM);
313 static CHAR_T *
314 memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
316 while (len-- > 0)
317 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
318 return dest;
321 static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
322 size_t len LOCALE_PARAM);
324 static CHAR_T *
325 memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
327 while (len-- > 0)
328 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
329 return dest;
331 #endif
334 #if ! HAVE_TM_GMTOFF
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 *);
339 static int
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__
372 __inline__
373 #endif
374 static int
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;
379 return (yday
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. */
389 #if FPRINTFTIME
390 # undef my_strftime
391 # define my_strftime fprintftime
392 #endif
394 #ifdef my_strftime
395 # define extra_args , tz, ns
396 # define extra_args_spec , timezone_t tz, int ns
397 #else
398 # if defined COMPILE_WIDE
399 # define my_strftime wcsftime
400 # define nl_get_alt_digit _nl_get_walt_digit
401 # else
402 # define my_strftime strftime
403 # define nl_get_alt_digit _nl_get_alt_digit
404 # endif
405 # define extra_args
406 # define extra_args_spec
407 /* We don't have this information in general. */
408 # define tz 1
409 # define ns 0
410 #endif
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. */
423 size_t
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)
434 #endif
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. */
440 static size_t
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];
449 #endif
450 #if FPRINTFTIME
451 size_t maxsize = (size_t) -1;
452 #endif
454 int saved_errno = errno;
455 int hour12 = tp->tm_hour;
456 #ifdef _NL_CURRENT
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. */
463 # define a_wkday \
464 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
465 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
466 # define f_wkday \
467 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
468 ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
469 # define a_month \
470 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
471 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
472 # define f_month \
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)))
481 # define ampm \
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)
489 #endif
490 #if HAVE_TZNAME
491 char **tzname_vec = tzname;
492 #endif
493 const char *zone;
494 size_t i = 0;
495 STREAM_OR_CHAR_T *p = s;
496 const CHAR_T *f;
497 #if DO_MULTIBYTE && !defined COMPILE_WIDE
498 const char *format_end = NULL;
499 #endif
501 zone = NULL;
502 #if HAVE_STRUCT_TM_TM_ZONE
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;
510 #endif
511 #if HAVE_TZNAME
512 if (!tz)
514 if (! (zone && *zone))
515 zone = "GMT";
517 else
519 # if !HAVE_STRUCT_TM_TM_ZONE
520 /* Infer the zone name from *TZ instead of from TZNAME. */
521 tzname_vec = tz->tzname_copy;
522 # endif
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. */
529 # ifndef my_strftime
530 if (!*tzset_called)
532 tzset ();
533 *tzset_called = true;
535 # endif
536 zone = tzname_vec[tp->tm_isdst != 0];
538 #endif
539 if (! zone)
540 zone = "";
542 if (hour12 > 12)
543 hour12 -= 12;
544 else
545 if (hour12 == 0)
546 hour12 = 12;
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;
559 CHAR_T *bufp;
560 CHAR_T buf[1
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;
567 size_t colons;
568 bool change_case = false;
569 int format_char;
570 int subwidth;
572 #if DO_MULTIBYTE && !defined COMPILE_WIDE
573 switch (*f)
575 case L_('%'):
576 break;
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_('}'):
598 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. */
603 add1 (*f);
604 continue;
606 default:
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;
611 size_t len = 0;
612 size_t fsize;
614 if (! format_end)
615 format_end = f + strlen (f) + 1;
616 fsize = format_end - f;
620 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
622 if (bytes == 0)
623 break;
625 if (bytes == (size_t) -2)
627 len += strlen (f + len);
628 break;
631 if (bytes == (size_t) -1)
633 len++;
634 break;
637 len += bytes;
639 while (! mbsinit (&mbstate));
641 cpy (len, f);
642 f += len - 1;
643 continue;
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. */
652 if (*f != L_('%'))
654 add1 (*f);
655 continue;
658 #endif /* ! DO_MULTIBYTE */
660 /* Check for flags that can modify a format. */
661 while (1)
663 switch (*++f)
665 /* This influences the number formats. */
666 case L_('_'):
667 case L_('-'):
668 case L_('+'):
669 case L_('0'):
670 pad = *f;
671 continue;
673 /* This changes textual output. */
674 case L_('^'):
675 to_uppcase = true;
676 continue;
677 case L_('#'):
678 change_case = true;
679 continue;
681 default:
682 break;
684 break;
687 if (ISDIGIT (*f))
689 width = 0;
692 if (INT_MULTIPLY_WRAPV (width, 10, &width)
693 || INT_ADD_WRAPV (width, *f - L_('0'), &width))
694 width = INT_MAX;
695 ++f;
697 while (ISDIGIT (*f));
700 /* Check for modifiers. */
701 switch (*f)
703 case L_('E'):
704 case L_('O'):
705 modifier = *f++;
706 break;
708 default:
709 modifier = 0;
710 break;
713 /* Now do the specified format. */
714 format_char = *f;
715 switch (format_char)
717 #define DO_NUMBER(d, v) \
718 do \
720 digits = d; \
721 number_value = v; \
722 goto do_number; \
724 while (0)
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) \
730 do \
732 digits = d; \
733 negative_number = negative; \
734 u_number_value = v; \
735 goto label; \
737 while (0)
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 \
745 digits = d; \
746 tz_colon_mask = mask; \
747 u_number_value = v; \
748 goto do_tz_offset; \
750 while (0)
751 #define DO_NUMBER_SPACEPAD(d, v) \
752 do \
754 digits = d; \
755 number_value = v; \
756 goto do_number_spacepad; \
758 while (0)
760 case L_('%'):
761 if (modifier != 0)
762 goto bad_format;
763 add1 (*f);
764 break;
766 case L_('a'):
767 if (modifier != 0)
768 goto bad_format;
769 if (change_case)
771 to_uppcase = true;
772 to_lowcase = false;
774 #ifdef _NL_CURRENT
775 cpy (aw_len, a_wkday);
776 break;
777 #else
778 goto underlying_strftime;
779 #endif
781 case 'A':
782 if (modifier != 0)
783 goto bad_format;
784 if (change_case)
786 to_uppcase = true;
787 to_lowcase = false;
789 #ifdef _NL_CURRENT
790 cpy (STRLEN (f_wkday), f_wkday);
791 break;
792 #else
793 goto underlying_strftime;
794 #endif
796 case L_('b'):
797 case L_('h'):
798 if (change_case)
800 to_uppcase = true;
801 to_lowcase = false;
803 if (modifier == L_('E'))
804 goto bad_format;
805 #ifdef _NL_CURRENT
806 if (modifier == L_('O'))
807 cpy (aam_len, a_altmonth);
808 else
809 cpy (am_len, a_month);
810 break;
811 #else
812 goto underlying_strftime;
813 #endif
815 case L_('B'):
816 if (modifier == L_('E'))
817 goto bad_format;
818 if (change_case)
820 to_uppcase = true;
821 to_lowcase = false;
823 #ifdef _NL_CURRENT
824 if (modifier == L_('O'))
825 cpy (STRLEN (f_altmonth), f_altmonth);
826 else
827 cpy (STRLEN (f_month), f_month);
828 break;
829 #else
830 goto underlying_strftime;
831 #endif
833 case L_('c'):
834 if (modifier == L_('O'))
835 goto bad_format;
836 #ifdef _NL_CURRENT
837 if (! (modifier == L_('E')
838 && (*(subfmt =
839 (const CHAR_T *) _NL_CURRENT (LC_TIME,
840 NLW(ERA_D_T_FMT)))
841 != '\0')))
842 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
843 #else
844 goto underlying_strftime;
845 #endif
847 subformat:
848 subwidth = -1;
849 subformat_width:
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));
861 break;
863 #if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
864 underlying_strftime:
866 /* The relevant information is available only via the
867 underlying strftime implementation, so use that. */
868 char ufmt[5];
869 char *u = ufmt;
870 char ubuf[1024]; /* enough for any single format in practice */
871 size_t len;
872 /* Make sure we're calling the actual underlying strftime.
873 In some cases, config.h contains something like
874 "#define strftime rpl_strftime". */
875 # ifdef strftime
876 # undef strftime
877 size_t strftime ();
878 # endif
880 /* The space helps distinguish strftime failure from empty
881 output. */
882 *u++ = ' ';
883 *u++ = '%';
884 if (modifier != 0)
885 *u++ = modifier;
886 *u++ = format_char;
887 *u = '\0';
888 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
889 if (len != 0)
890 cpy (len - 1, ubuf + 1);
892 break;
893 #endif
895 case L_('C'):
896 if (modifier == L_('E'))
898 #if HAVE_STRUCT_ERA_ENTRY
899 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
900 if (era)
902 # ifdef COMPILE_WIDE
903 size_t len = __wcslen (era->era_wname);
904 cpy (len, era->era_wname);
905 # else
906 size_t len = strlen (era->era_name);
907 cpy (len, era->era_name);
908 # endif
909 break;
911 #else
912 goto underlying_strftime;
913 #endif
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);
924 case L_('x'):
925 if (modifier == L_('O'))
926 goto bad_format;
927 #ifdef _NL_CURRENT
928 if (! (modifier == L_('E')
929 && (*(subfmt =
930 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
931 != L_('\0'))))
932 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
933 goto subformat;
934 #else
935 goto underlying_strftime;
936 #endif
937 case L_('D'):
938 if (modifier != 0)
939 goto bad_format;
940 subfmt = L_("%m/%d/%y");
941 goto subformat;
943 case L_('d'):
944 if (modifier == L_('E'))
945 goto bad_format;
947 DO_NUMBER (2, tp->tm_mday);
949 case L_('e'):
950 if (modifier == L_('E'))
951 goto bad_format;
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. */
958 do_tz_offset:
959 always_output_a_sign = true;
960 goto do_number_body;
962 do_yearish:
963 if (pad == 0)
964 pad = yr_spec;
965 always_output_a_sign
966 = (pad == L_('+')
967 && ((digits == 2 ? 99 : 9999) < u_number_value
968 || digits < width));
969 goto do_maybe_signed_number;
971 do_number_spacepad:
972 if (pad == 0)
973 pad = L_('_');
975 do_number:
976 /* Format NUMBER_VALUE according to the MODIFIER flag. */
977 negative_number = number_value < 0;
978 u_number_value = number_value;
980 do_signed_number:
981 always_output_a_sign = false;
983 do_maybe_signed_number:
984 tz_colon_mask = 0;
986 do_number_body:
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
991 negating it. */
992 if (modifier == L_('O') && !negative_number)
994 #ifdef _NL_CURRENT
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
998 HELPER_LOCALE_ARG);
1000 if (cp != NULL)
1002 size_t digitlen = STRLEN (cp);
1003 if (digitlen != 0)
1005 cpy (digitlen, cp);
1006 break;
1009 #else
1010 goto underlying_strftime;
1011 #endif
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)
1022 *--bufp = ':';
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:
1030 if (pad == 0)
1031 pad = L_('0');
1032 if (width < 0)
1033 width = digits;
1036 CHAR_T sign_char = (negative_number ? L_('-')
1037 : always_output_a_sign ? L_('+')
1038 : 0);
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;
1043 if (sign_char)
1045 if (pad == L_('_'))
1047 if (p)
1048 memset_space (p, padding);
1049 i += padding;
1050 width -= padding;
1052 width_add1 (0, sign_char);
1053 width--;
1056 cpy (numlen, bufp);
1058 break;
1060 case L_('F'):
1061 if (modifier != 0)
1062 goto bad_format;
1063 if (pad == 0 && width < 0)
1065 pad = L_('+');
1066 subwidth = 4;
1068 else
1070 subwidth = width - 6;
1071 if (subwidth < 0)
1072 subwidth = 0;
1074 subfmt = L_("%Y-%m-%d");
1075 goto subformat_width;
1077 case L_('H'):
1078 if (modifier == L_('E'))
1079 goto bad_format;
1081 DO_NUMBER (2, tp->tm_hour);
1083 case L_('I'):
1084 if (modifier == L_('E'))
1085 goto bad_format;
1087 DO_NUMBER (2, hour12);
1089 case L_('k'): /* GNU extension. */
1090 if (modifier == L_('E'))
1091 goto bad_format;
1093 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1095 case L_('l'): /* GNU extension. */
1096 if (modifier == L_('E'))
1097 goto bad_format;
1099 DO_NUMBER_SPACEPAD (2, hour12);
1101 case L_('j'):
1102 if (modifier == L_('E'))
1103 goto bad_format;
1105 DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
1107 case L_('M'):
1108 if (modifier == L_('E'))
1109 goto bad_format;
1111 DO_NUMBER (2, tp->tm_min);
1113 case L_('m'):
1114 if (modifier == L_('E'))
1115 goto bad_format;
1117 DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
1119 #ifndef _LIBC
1120 case L_('N'): /* GNU extension. */
1121 if (modifier == L_('E'))
1122 goto bad_format;
1124 int n = ns, ns_digits = 9;
1125 if (width <= 0)
1126 width = ns_digits;
1127 int ndigs = ns_digits;
1128 while (width < ndigs || (1 < ndigs && n % 10 == 0))
1129 ndigs--, n /= 10;
1130 for (int j = ndigs; 0 < j; j--)
1131 buf[j - 1] = n % 10 + L_('0'), n /= 10;
1132 if (!pad)
1133 pad = L_('0');
1134 width_cpy (0, ndigs, buf);
1135 width_add (width - ndigs, 0, (void) 0);
1137 break;
1138 #endif
1140 case L_('n'):
1141 add1 (L_('\n'));
1142 break;
1144 case L_('P'):
1145 to_lowcase = true;
1146 #ifndef _NL_CURRENT
1147 format_char = L_('p');
1148 #endif
1149 FALLTHROUGH;
1150 case L_('p'):
1151 if (change_case)
1153 to_uppcase = false;
1154 to_lowcase = true;
1156 #ifdef _NL_CURRENT
1157 cpy (ap_len, ampm);
1158 break;
1159 #else
1160 goto underlying_strftime;
1161 #endif
1163 case L_('q'): /* GNU extension. */
1164 DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1);
1165 break;
1167 case L_('R'):
1168 subfmt = L_("%H:%M");
1169 goto subformat;
1171 case L_('r'):
1172 #ifdef _NL_CURRENT
1173 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1174 NLW(T_FMT_AMPM)))
1175 == L_('\0'))
1176 subfmt = L_("%I:%M:%S %p");
1177 goto subformat;
1178 #else
1179 goto underlying_strftime;
1180 #endif
1182 case L_('S'):
1183 if (modifier == L_('E'))
1184 goto bad_format;
1186 DO_NUMBER (2, tp->tm_sec);
1188 case L_('s'): /* GNU extension. */
1190 struct tm ltm;
1191 time_t t;
1193 ltm = *tp;
1194 ltm.tm_yday = -1;
1195 t = mktime_z (tz, &ltm);
1196 if (ltm.tm_yday < 0)
1198 errno = EOVERFLOW;
1199 return 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;
1210 int d = t % 10;
1211 t /= 10;
1212 *--bufp = (negative_number ? -d : d) + L_('0');
1214 while (t != 0);
1216 digits = 1;
1217 always_output_a_sign = false;
1218 goto do_number_sign_and_padding;
1221 case L_('X'):
1222 if (modifier == L_('O'))
1223 goto bad_format;
1224 #ifdef _NL_CURRENT
1225 if (! (modifier == L_('E')
1226 && (*(subfmt =
1227 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1228 != L_('\0'))))
1229 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1230 goto subformat;
1231 #else
1232 goto underlying_strftime;
1233 #endif
1234 case L_('T'):
1235 subfmt = L_("%H:%M:%S");
1236 goto subformat;
1238 case L_('t'):
1239 add1 (L_('\t'));
1240 break;
1242 case L_('u'):
1243 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1245 case L_('U'):
1246 if (modifier == L_('E'))
1247 goto bad_format;
1249 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1251 case L_('V'):
1252 case L_('g'):
1253 case L_('G'):
1254 if (modifier == L_('E'))
1255 goto bad_format;
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
1260 overflow. */
1261 int year = (tp->tm_year
1262 + (tp->tm_year < 0
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);
1268 if (days < 0)
1270 /* This ISO week belongs to the previous year. */
1271 year_adjust = -1;
1272 days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
1273 tp->tm_wday);
1275 else
1277 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1278 tp->tm_wday);
1279 if (0 <= d)
1281 /* This ISO week belongs to the next year. */
1282 year_adjust = 1;
1283 days = d;
1287 switch (*f)
1289 case L_('g'):
1291 int yy = (tp->tm_year % 100 + year_adjust) % 100;
1292 DO_YEARISH (2, false,
1293 (0 <= yy
1294 ? yy
1295 : tp->tm_year < -TM_YEAR_BASE - year_adjust
1296 ? -yy
1297 : yy + 100));
1300 case L_('G'):
1301 DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
1302 (tp->tm_year + (unsigned int) TM_YEAR_BASE
1303 + year_adjust));
1305 default:
1306 DO_NUMBER (2, days / 7 + 1);
1310 case L_('W'):
1311 if (modifier == L_('E'))
1312 goto bad_format;
1314 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1316 case L_('w'):
1317 if (modifier == L_('E'))
1318 goto bad_format;
1320 DO_NUMBER (1, tp->tm_wday);
1322 case L_('Y'):
1323 if (modifier == L_('E'))
1325 #if HAVE_STRUCT_ERA_ENTRY
1326 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1327 if (era)
1329 # ifdef COMPILE_WIDE
1330 subfmt = era->era_wformat;
1331 # else
1332 subfmt = era->era_format;
1333 # endif
1334 if (pad == 0)
1335 pad = yr_spec;
1336 goto subformat;
1338 #else
1339 goto underlying_strftime;
1340 #endif
1342 if (modifier == L_('O'))
1343 goto bad_format;
1345 DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE,
1346 tp->tm_year + (unsigned int) TM_YEAR_BASE);
1348 case L_('y'):
1349 if (modifier == L_('E'))
1351 #if HAVE_STRUCT_ERA_ENTRY
1352 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1353 if (era)
1355 int delta = tp->tm_year - era->start_date[0];
1356 if (pad == 0)
1357 pad = yr_spec;
1358 DO_NUMBER (2, (era->offset
1359 + delta * era->absolute_direction));
1361 #else
1362 goto underlying_strftime;
1363 #endif
1367 int yy = tp->tm_year % 100;
1368 if (yy < 0)
1369 yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
1370 DO_YEARISH (2, false, yy);
1373 case L_('Z'):
1374 if (change_case)
1376 to_uppcase = false;
1377 to_lowcase = true;
1380 #ifdef COMPILE_WIDE
1382 /* The zone string is always given in multibyte form. We have
1383 to transform it first. */
1384 wchar_t *wczone;
1385 size_t len;
1386 widen (zone, wczone, len);
1387 cpy (len, wczone);
1389 #else
1390 cpy (strlen (zone), zone);
1391 #endif
1392 break;
1394 case L_(':'):
1395 /* :, ::, and ::: are valid only just before 'z'.
1396 :::: etc. are rejected later. */
1397 for (colons = 1; f[colons] == L_(':'); colons++)
1398 continue;
1399 if (f[colons] != L_('z'))
1400 goto bad_format;
1401 f += colons;
1402 goto do_z_conversion;
1404 case L_('z'):
1405 colons = 0;
1407 do_z_conversion:
1408 if (tp->tm_isdst < 0)
1409 break;
1412 int diff;
1413 int hour_diff;
1414 int min_diff;
1415 int sec_diff;
1416 #if HAVE_TM_GMTOFF
1417 diff = tp->tm_gmtoff;
1418 #else
1419 if (!tz)
1420 diff = 0;
1421 else
1423 struct tm gtm;
1424 struct tm ltm;
1425 time_t lt;
1427 /* POSIX.1 requires that local time zone information be used as
1428 though strftime called tzset. */
1429 # ifndef my_strftime
1430 if (!*tzset_called)
1432 tzset ();
1433 *tzset_called = true;
1435 # endif
1437 ltm = *tp;
1438 ltm.tm_wday = -1;
1439 lt = mktime_z (tz, &ltm);
1440 if (ltm.tm_wday < 0 || ! localtime_rz (0, &lt, &gtm))
1441 break;
1442 diff = tm_diff (&ltm, &gtm);
1444 #endif
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;
1451 switch (colons)
1453 case 0: /* +hhmm */
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 */
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);
1470 default:
1471 goto bad_format;
1475 case L_('\0'): /* GNU extension: % at end of format. */
1476 --f;
1477 FALLTHROUGH;
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:
1484 int flen;
1485 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1486 continue;
1487 cpy (flen, &f[1 - flen]);
1489 break;
1493 #if ! FPRINTFTIME
1494 if (p && maxsize != 0)
1495 *p = L_('\0');
1496 #endif
1498 errno = saved_errno;
1499 return i;