Fix last ChangeLog entry.
[gnulib.git] / lib / nstrftime.c
blob791fbff7fdb06754cdfa0cafdce4c401b4e7bc88
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/>. */
18 #ifdef _LIBC
19 # define USE_IN_EXTENDED_LOCALE_MODEL 1
20 # define HAVE_STRUCT_ERA_ENTRY 1
21 # define HAVE_TM_GMTOFF 1
22 # define HAVE_TM_ZONE 1
23 # define HAVE_TZNAME 1
24 # define HAVE_TZSET 1
25 # include "../locale/localeinfo.h"
26 #else
27 # include <config.h>
28 # if FPRINTFTIME
29 # include "fprintftime.h"
30 # else
31 # include "strftime.h"
32 # endif
33 # include "time-internal.h"
34 #endif
36 #include <ctype.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) \
166 return 0; \
167 if (p) \
169 if (_n < _w) \
171 size_t _delta = _w - _n; \
172 if (pad == L_('0') || pad == L_('+')) \
173 memset_zero (p, _delta); \
174 else \
175 memset_space (p, _delta); \
177 f; \
178 advance (p, _n); \
180 i += _incr; \
181 } while (0)
183 #define add1(c) width_add1 (width, c)
184 #if FPRINTFTIME
185 # define width_add1(width, c) width_add (width, 1, fputc (c, p))
186 #else
187 # define width_add1(width, c) width_add (width, 1, *p = c)
188 #endif
190 #define cpy(n, s) width_cpy (width, n, s)
191 #if FPRINTFTIME
192 # define width_cpy(width, n, s) \
193 width_add (width, n, \
194 do \
196 if (to_lowcase) \
197 fwrite_lowcase (p, (s), _n); \
198 else if (to_uppcase) \
199 fwrite_uppcase (p, (s), _n); \
200 else \
202 /* Ignore the value of fwrite. The caller can determine whether \
203 an error occurred by inspecting ferror (P). All known fwrite \
204 implementations set the stream's error indicator when they \
205 fail due to ENOMEM etc., even though C11 and POSIX.1-2008 do \
206 not require this. */ \
207 fwrite (s, _n, 1, p); \
210 while (0) \
212 #else
213 # define width_cpy(width, n, s) \
214 width_add (width, n, \
215 if (to_lowcase) \
216 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
217 else if (to_uppcase) \
218 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
219 else \
220 MEMCPY ((void *) p, (void const *) (s), _n))
221 #endif
223 #ifdef COMPILE_WIDE
224 # ifndef USE_IN_EXTENDED_LOCALE_MODEL
225 # undef __mbsrtowcs_l
226 # define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
227 # endif
228 # define widen(os, ws, l) \
230 mbstate_t __st; \
231 const char *__s = os; \
232 memset (&__st, '\0', sizeof (__st)); \
233 l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
234 ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \
235 (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
237 #endif
240 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
241 /* We use this code also for the extended locale handling where the
242 function gets as an additional argument the locale which has to be
243 used. To access the values we have to redefine the _NL_CURRENT
244 macro. */
245 # define strftime __strftime_l
246 # define wcsftime __wcsftime_l
247 # undef _NL_CURRENT
248 # define _NL_CURRENT(category, item) \
249 (current->values[_NL_ITEM_INDEX (item)].string)
250 # define LOCALE_PARAM , locale_t loc
251 # define LOCALE_ARG , loc
252 # define HELPER_LOCALE_ARG , current
253 #else
254 # define LOCALE_PARAM
255 # define LOCALE_ARG
256 # ifdef _LIBC
257 # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
258 # else
259 # define HELPER_LOCALE_ARG
260 # endif
261 #endif
263 #ifdef COMPILE_WIDE
264 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
265 # define TOUPPER(Ch, L) __towupper_l (Ch, L)
266 # define TOLOWER(Ch, L) __towlower_l (Ch, L)
267 # else
268 # define TOUPPER(Ch, L) towupper (Ch)
269 # define TOLOWER(Ch, L) towlower (Ch)
270 # endif
271 #else
272 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
273 # define TOUPPER(Ch, L) __toupper_l (Ch, L)
274 # define TOLOWER(Ch, L) __tolower_l (Ch, L)
275 # else
276 # define TOUPPER(Ch, L) toupper (Ch)
277 # define TOLOWER(Ch, L) tolower (Ch)
278 # endif
279 #endif
280 /* We don't use 'isdigit' here since the locale dependent
281 interpretation is not what we want here. We only need to accept
282 the arabic digits in the ASCII range. One day there is perhaps a
283 more reliable way to accept other sets of digits. */
284 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
286 #if FPRINTFTIME
287 static void
288 fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len)
290 while (len-- > 0)
292 fputc (TOLOWER ((UCHAR_T) *src, loc), fp);
293 ++src;
297 static void
298 fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len)
300 while (len-- > 0)
302 fputc (TOUPPER ((UCHAR_T) *src, loc), fp);
303 ++src;
306 #else
307 static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
308 size_t len LOCALE_PARAM);
310 static CHAR_T *
311 memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
313 while (len-- > 0)
314 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
315 return dest;
318 static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
319 size_t len LOCALE_PARAM);
321 static CHAR_T *
322 memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
324 while (len-- > 0)
325 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
326 return dest;
328 #endif
331 #if ! HAVE_TM_GMTOFF
332 /* Yield the difference between *A and *B,
333 measured in seconds, ignoring leap seconds. */
334 # define tm_diff ftime_tm_diff
335 static int tm_diff (const struct tm *, const struct tm *);
336 static int
337 tm_diff (const struct tm *a, const struct tm *b)
339 /* Compute intervening leap days correctly even if year is negative.
340 Take care to avoid int overflow in leap day calculations,
341 but it's OK to assume that A and B are close to each other. */
342 int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
343 int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
344 int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
345 int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
346 int a400 = SHR (a100, 2);
347 int b400 = SHR (b100, 2);
348 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
349 int years = a->tm_year - b->tm_year;
350 int days = (365 * years + intervening_leap_days
351 + (a->tm_yday - b->tm_yday));
352 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
353 + (a->tm_min - b->tm_min))
354 + (a->tm_sec - b->tm_sec));
356 #endif /* ! HAVE_TM_GMTOFF */
360 /* The number of days from the first day of the first ISO week of this
361 year to the year day YDAY with week day WDAY. ISO weeks start on
362 Monday; the first ISO week has the year's first Thursday. YDAY may
363 be as small as YDAY_MINIMUM. */
364 #define ISO_WEEK_START_WDAY 1 /* Monday */
365 #define ISO_WEEK1_WDAY 4 /* Thursday */
366 #define YDAY_MINIMUM (-366)
367 static int iso_week_days (int, int);
368 #ifdef __GNUC__
369 __inline__
370 #endif
371 static int
372 iso_week_days (int yday, int wday)
374 /* Add enough to the first operand of % to make it nonnegative. */
375 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
376 return (yday
377 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
378 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
382 /* When compiling this file, GNU applications can #define my_strftime
383 to a symbol (typically nstrftime) to get an extended strftime with
384 extra arguments TZ and NS. */
386 #if FPRINTFTIME
387 # undef my_strftime
388 # define my_strftime fprintftime
389 #endif
391 #ifdef my_strftime
392 # undef HAVE_TZSET
393 # define extra_args , tz, ns
394 # define extra_args_spec , timezone_t tz, int ns
395 #else
396 # if defined COMPILE_WIDE
397 # define my_strftime wcsftime
398 # define nl_get_alt_digit _nl_get_walt_digit
399 # else
400 # define my_strftime strftime
401 # define nl_get_alt_digit _nl_get_alt_digit
402 # endif
403 # define extra_args
404 # define extra_args_spec
405 /* We don't have this information in general. */
406 # define tz 1
407 # define ns 0
408 #endif
410 static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t)
411 const CHAR_T *, const struct tm *,
412 bool, int, int, bool *
413 extra_args_spec LOCALE_PARAM);
415 /* Write information from TP into S according to the format
416 string FORMAT, writing no more that MAXSIZE characters
417 (including the terminating '\0') and returning number of
418 characters written. If S is NULL, nothing will be written
419 anywhere, so to determine how many characters would be
420 written, use NULL for S and (size_t) -1 for MAXSIZE. */
421 size_t
422 my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
423 const CHAR_T *format,
424 const struct tm *tp extra_args_spec LOCALE_PARAM)
426 bool tzset_called = false;
427 return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, false,
428 0, -1, &tzset_called extra_args LOCALE_ARG);
430 #if defined _LIBC && ! FPRINTFTIME
431 libc_hidden_def (my_strftime)
432 #endif
434 /* Just like my_strftime, above, but with more parameters.
435 UPCASE indicates that the result should be converted to upper case.
436 YR_SPEC and WIDTH specify the padding and width for the year.
437 *TZSET_CALLED indicates whether tzset has been called here. */
438 static size_t
439 __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
440 const CHAR_T *format,
441 const struct tm *tp, bool upcase,
442 int yr_spec, int width, bool *tzset_called
443 extra_args_spec LOCALE_PARAM)
445 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
446 struct __locale_data *const current = loc->__locales[LC_TIME];
447 #endif
448 #if FPRINTFTIME
449 size_t maxsize = (size_t) -1;
450 #endif
452 int hour12 = tp->tm_hour;
453 #ifdef _NL_CURRENT
454 /* We cannot make the following values variables since we must delay
455 the evaluation of these values until really needed since some
456 expressions might not be valid in every situation. The 'struct tm'
457 might be generated by a strptime() call that initialized
458 only a few elements. Dereference the pointers only if the format
459 requires this. Then it is ok to fail if the pointers are invalid. */
460 # define a_wkday \
461 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
462 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
463 # define f_wkday \
464 ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
465 ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
466 # define a_month \
467 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
468 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
469 # define f_month \
470 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
471 ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
472 # define a_altmonth \
473 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
474 ? "?" : _NL_CURRENT (LC_TIME, NLW(ABALTMON_1) + tp->tm_mon)))
475 # define f_altmonth \
476 ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
477 ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon)))
478 # define ampm \
479 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
480 ? NLW(PM_STR) : NLW(AM_STR)))
482 # define aw_len STRLEN (a_wkday)
483 # define am_len STRLEN (a_month)
484 # define aam_len STRLEN (a_altmonth)
485 # define ap_len STRLEN (ampm)
486 #endif
487 #if HAVE_TZNAME
488 char **tzname_vec = tzname;
489 #endif
490 const char *zone;
491 size_t i = 0;
492 STREAM_OR_CHAR_T *p = s;
493 const CHAR_T *f;
494 #if DO_MULTIBYTE && !defined COMPILE_WIDE
495 const char *format_end = NULL;
496 #endif
498 zone = NULL;
499 #if HAVE_TM_ZONE
500 /* The POSIX test suite assumes that setting
501 the environment variable TZ to a new value before calling strftime()
502 will influence the result (the %Z format) even if the information in
503 TP is computed with a totally different time zone.
504 This is bogus: though POSIX allows bad behavior like this,
505 POSIX does not require it. Do the right thing instead. */
506 zone = (const char *) tp->tm_zone;
507 #endif
508 #if HAVE_TZNAME
509 if (!tz)
511 if (! (zone && *zone))
512 zone = "GMT";
514 else
516 # if !HAVE_TM_ZONE
517 /* Infer the zone name from *TZ instead of from TZNAME. */
518 tzname_vec = tz->tzname_copy;
519 # endif
521 /* The tzset() call might have changed the value. */
522 if (!(zone && *zone) && tp->tm_isdst >= 0)
524 /* POSIX.1 requires that local time zone information be used as
525 though strftime called tzset. */
526 # if HAVE_TZSET
527 if (!*tzset_called)
529 tzset ();
530 *tzset_called = true;
532 # endif
533 zone = tzname_vec[tp->tm_isdst != 0];
535 #endif
536 if (! zone)
537 zone = "";
539 if (hour12 > 12)
540 hour12 -= 12;
541 else
542 if (hour12 == 0)
543 hour12 = 12;
545 for (f = format; *f != '\0'; width = -1, f++)
547 int pad = 0; /* Padding for number ('_', '-', '+', '0', or 0). */
548 int modifier; /* Field modifier ('E', 'O', or 0). */
549 int digits = 0; /* Max digits for numeric format. */
550 int number_value; /* Numeric value to be printed. */
551 unsigned int u_number_value; /* (unsigned int) number_value. */
552 bool negative_number; /* The number is negative. */
553 bool always_output_a_sign; /* +/- should always be output. */
554 int tz_colon_mask; /* Bitmask of where ':' should appear. */
555 const CHAR_T *subfmt;
556 CHAR_T *bufp;
557 CHAR_T buf[1
558 + 2 /* for the two colons in a %::z or %:::z time zone */
559 + (sizeof (int) < sizeof (time_t)
560 ? INT_STRLEN_BOUND (time_t)
561 : INT_STRLEN_BOUND (int))];
562 bool to_lowcase = false;
563 bool to_uppcase = upcase;
564 size_t colons;
565 bool change_case = false;
566 int format_char;
567 int subwidth;
569 #if DO_MULTIBYTE && !defined COMPILE_WIDE
570 switch (*f)
572 case L_('%'):
573 break;
575 case L_('\b'): case L_('\t'): case L_('\n'):
576 case L_('\v'): case L_('\f'): case L_('\r'):
577 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
578 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
579 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
580 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
581 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
582 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
583 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
584 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
585 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
586 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
587 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
588 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
589 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
590 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
591 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
592 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
593 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
594 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
595 case L_('~'):
596 /* The C Standard requires these 98 characters (plus '%') to
597 be in the basic execution character set. None of these
598 characters can start a multibyte sequence, so they need
599 not be analyzed further. */
600 add1 (*f);
601 continue;
603 default:
604 /* Copy this multibyte sequence until we reach its end, find
605 an error, or come back to the initial shift state. */
607 mbstate_t mbstate = mbstate_zero;
608 size_t len = 0;
609 size_t fsize;
611 if (! format_end)
612 format_end = f + strlen (f) + 1;
613 fsize = format_end - f;
617 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
619 if (bytes == 0)
620 break;
622 if (bytes == (size_t) -2)
624 len += strlen (f + len);
625 break;
628 if (bytes == (size_t) -1)
630 len++;
631 break;
634 len += bytes;
636 while (! mbsinit (&mbstate));
638 cpy (len, f);
639 f += len - 1;
640 continue;
644 #else /* ! DO_MULTIBYTE */
646 /* Either multibyte encodings are not supported, they are
647 safe for formats, so any non-'%' byte can be copied through,
648 or this is the wide character version. */
649 if (*f != L_('%'))
651 add1 (*f);
652 continue;
655 #endif /* ! DO_MULTIBYTE */
657 /* Check for flags that can modify a format. */
658 while (1)
660 switch (*++f)
662 /* This influences the number formats. */
663 case L_('_'):
664 case L_('-'):
665 case L_('+'):
666 case L_('0'):
667 pad = *f;
668 continue;
670 /* This changes textual output. */
671 case L_('^'):
672 to_uppcase = true;
673 continue;
674 case L_('#'):
675 change_case = true;
676 continue;
678 default:
679 break;
681 break;
684 if (ISDIGIT (*f))
686 width = 0;
689 if (INT_MULTIPLY_WRAPV (width, 10, &width)
690 || INT_ADD_WRAPV (width, *f - L_('0'), &width))
691 width = INT_MAX;
692 ++f;
694 while (ISDIGIT (*f));
697 /* Check for modifiers. */
698 switch (*f)
700 case L_('E'):
701 case L_('O'):
702 modifier = *f++;
703 break;
705 default:
706 modifier = 0;
707 break;
710 /* Now do the specified format. */
711 format_char = *f;
712 switch (format_char)
714 #define DO_NUMBER(d, v) \
715 do \
717 digits = d; \
718 number_value = v; \
719 goto do_number; \
721 while (0)
722 #define DO_SIGNED_NUMBER(d, negative, v) \
723 DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_signed_number)
724 #define DO_YEARISH(d, negative, v) \
725 DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_yearish)
726 #define DO_MAYBE_SIGNED_NUMBER(d, negative, v, label) \
727 do \
729 digits = d; \
730 negative_number = negative; \
731 u_number_value = v; \
732 goto label; \
734 while (0)
736 /* The mask is not what you might think.
737 When the ordinal i'th bit is set, insert a colon
738 before the i'th digit of the time zone representation. */
739 #define DO_TZ_OFFSET(d, mask, v) \
740 do \
742 digits = d; \
743 tz_colon_mask = mask; \
744 u_number_value = v; \
745 goto do_tz_offset; \
747 while (0)
748 #define DO_NUMBER_SPACEPAD(d, v) \
749 do \
751 digits = d; \
752 number_value = v; \
753 goto do_number_spacepad; \
755 while (0)
757 case L_('%'):
758 if (modifier != 0)
759 goto bad_format;
760 add1 (*f);
761 break;
763 case L_('a'):
764 if (modifier != 0)
765 goto bad_format;
766 if (change_case)
768 to_uppcase = true;
769 to_lowcase = false;
771 #ifdef _NL_CURRENT
772 cpy (aw_len, a_wkday);
773 break;
774 #else
775 goto underlying_strftime;
776 #endif
778 case 'A':
779 if (modifier != 0)
780 goto bad_format;
781 if (change_case)
783 to_uppcase = true;
784 to_lowcase = false;
786 #ifdef _NL_CURRENT
787 cpy (STRLEN (f_wkday), f_wkday);
788 break;
789 #else
790 goto underlying_strftime;
791 #endif
793 case L_('b'):
794 case L_('h'):
795 if (change_case)
797 to_uppcase = true;
798 to_lowcase = false;
800 if (modifier == L_('E'))
801 goto bad_format;
802 #ifdef _NL_CURRENT
803 if (modifier == L_('O'))
804 cpy (aam_len, a_altmonth);
805 else
806 cpy (am_len, a_month);
807 break;
808 #else
809 goto underlying_strftime;
810 #endif
812 case L_('B'):
813 if (modifier == L_('E'))
814 goto bad_format;
815 if (change_case)
817 to_uppcase = true;
818 to_lowcase = false;
820 #ifdef _NL_CURRENT
821 if (modifier == L_('O'))
822 cpy (STRLEN (f_altmonth), f_altmonth);
823 else
824 cpy (STRLEN (f_month), f_month);
825 break;
826 #else
827 goto underlying_strftime;
828 #endif
830 case L_('c'):
831 if (modifier == L_('O'))
832 goto bad_format;
833 #ifdef _NL_CURRENT
834 if (! (modifier == L_('E')
835 && (*(subfmt =
836 (const CHAR_T *) _NL_CURRENT (LC_TIME,
837 NLW(ERA_D_T_FMT)))
838 != '\0')))
839 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
840 #else
841 goto underlying_strftime;
842 #endif
844 subformat:
845 subwidth = -1;
846 subformat_width:
848 size_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1)
849 subfmt, tp, to_uppcase,
850 pad, subwidth, tzset_called
851 extra_args LOCALE_ARG);
852 add (len, __strftime_internal (p,
853 STRFTIME_ARG (maxsize - i)
854 subfmt, tp, to_uppcase,
855 pad, subwidth, tzset_called
856 extra_args LOCALE_ARG));
858 break;
860 #if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
861 underlying_strftime:
863 /* The relevant information is available only via the
864 underlying strftime implementation, so use that. */
865 char ufmt[5];
866 char *u = ufmt;
867 char ubuf[1024]; /* enough for any single format in practice */
868 size_t len;
869 /* Make sure we're calling the actual underlying strftime.
870 In some cases, config.h contains something like
871 "#define strftime rpl_strftime". */
872 # ifdef strftime
873 # undef strftime
874 size_t strftime ();
875 # endif
877 /* The space helps distinguish strftime failure from empty
878 output. */
879 *u++ = ' ';
880 *u++ = '%';
881 if (modifier != 0)
882 *u++ = modifier;
883 *u++ = format_char;
884 *u = '\0';
885 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
886 if (len != 0)
887 cpy (len - 1, ubuf + 1);
889 break;
890 #endif
892 case L_('C'):
893 if (modifier == L_('E'))
895 #if HAVE_STRUCT_ERA_ENTRY
896 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
897 if (era)
899 # ifdef COMPILE_WIDE
900 size_t len = __wcslen (era->era_wname);
901 cpy (len, era->era_wname);
902 # else
903 size_t len = strlen (era->era_name);
904 cpy (len, era->era_name);
905 # endif
906 break;
908 #else
909 goto underlying_strftime;
910 #endif
914 bool negative_year = tp->tm_year < - TM_YEAR_BASE;
915 bool zero_thru_1899 = !negative_year & (tp->tm_year < 0);
916 int century = ((tp->tm_year - 99 * zero_thru_1899) / 100
917 + TM_YEAR_BASE / 100);
918 DO_YEARISH (2, negative_year, century);
921 case L_('x'):
922 if (modifier == L_('O'))
923 goto bad_format;
924 #ifdef _NL_CURRENT
925 if (! (modifier == L_('E')
926 && (*(subfmt =
927 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
928 != L_('\0'))))
929 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
930 goto subformat;
931 #else
932 goto underlying_strftime;
933 #endif
934 case L_('D'):
935 if (modifier != 0)
936 goto bad_format;
937 subfmt = L_("%m/%d/%y");
938 goto subformat;
940 case L_('d'):
941 if (modifier == L_('E'))
942 goto bad_format;
944 DO_NUMBER (2, tp->tm_mday);
946 case L_('e'):
947 if (modifier == L_('E'))
948 goto bad_format;
950 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
952 /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
953 and then jump to one of these labels. */
955 do_tz_offset:
956 always_output_a_sign = true;
957 goto do_number_body;
959 do_yearish:
960 if (pad == 0)
961 pad = yr_spec;
962 always_output_a_sign
963 = (pad == L_('+')
964 && ((digits == 2 ? 99 : 9999) < u_number_value
965 || digits < width));
966 goto do_maybe_signed_number;
968 do_number_spacepad:
969 if (pad == 0)
970 pad = L_('_');
972 do_number:
973 /* Format NUMBER_VALUE according to the MODIFIER flag. */
974 negative_number = number_value < 0;
975 u_number_value = number_value;
977 do_signed_number:
978 always_output_a_sign = false;
980 do_maybe_signed_number:
981 tz_colon_mask = 0;
983 do_number_body:
984 /* Format U_NUMBER_VALUE according to the MODIFIER flag.
985 NEGATIVE_NUMBER is nonzero if the original number was
986 negative; in this case it was converted directly to
987 unsigned int (i.e., modulo (UINT_MAX + 1)) without
988 negating it. */
989 if (modifier == L_('O') && !negative_number)
991 #ifdef _NL_CURRENT
992 /* Get the locale specific alternate representation of
993 the number. If none exist NULL is returned. */
994 const CHAR_T *cp = nl_get_alt_digit (u_number_value
995 HELPER_LOCALE_ARG);
997 if (cp != NULL)
999 size_t digitlen = STRLEN (cp);
1000 if (digitlen != 0)
1002 cpy (digitlen, cp);
1003 break;
1006 #else
1007 goto underlying_strftime;
1008 #endif
1011 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1013 if (negative_number)
1014 u_number_value = - u_number_value;
1018 if (tz_colon_mask & 1)
1019 *--bufp = ':';
1020 tz_colon_mask >>= 1;
1021 *--bufp = u_number_value % 10 + L_('0');
1022 u_number_value /= 10;
1024 while (u_number_value != 0 || tz_colon_mask != 0);
1026 do_number_sign_and_padding:
1027 if (pad == 0)
1028 pad = L_('0');
1029 if (width < 0)
1030 width = digits;
1033 CHAR_T sign_char = (negative_number ? L_('-')
1034 : always_output_a_sign ? L_('+')
1035 : 0);
1036 int numlen = buf + sizeof buf / sizeof buf[0] - bufp;
1037 int shortage = width - !!sign_char - numlen;
1038 int padding = pad == L_('-') || shortage <= 0 ? 0 : shortage;
1040 if (sign_char)
1042 if (pad == L_('_'))
1044 if (p)
1045 memset_space (p, padding);
1046 i += padding;
1047 width -= padding;
1049 width_add1 (0, sign_char);
1050 width--;
1053 cpy (numlen, bufp);
1055 break;
1057 case L_('F'):
1058 if (modifier != 0)
1059 goto bad_format;
1060 if (pad == 0 && width < 0)
1062 pad = L_('+');
1063 subwidth = 4;
1065 else
1067 subwidth = width - 6;
1068 if (subwidth < 0)
1069 subwidth = 0;
1071 subfmt = L_("%Y-%m-%d");
1072 goto subformat_width;
1074 case L_('H'):
1075 if (modifier == L_('E'))
1076 goto bad_format;
1078 DO_NUMBER (2, tp->tm_hour);
1080 case L_('I'):
1081 if (modifier == L_('E'))
1082 goto bad_format;
1084 DO_NUMBER (2, hour12);
1086 case L_('k'): /* GNU extension. */
1087 if (modifier == L_('E'))
1088 goto bad_format;
1090 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1092 case L_('l'): /* GNU extension. */
1093 if (modifier == L_('E'))
1094 goto bad_format;
1096 DO_NUMBER_SPACEPAD (2, hour12);
1098 case L_('j'):
1099 if (modifier == L_('E'))
1100 goto bad_format;
1102 DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
1104 case L_('M'):
1105 if (modifier == L_('E'))
1106 goto bad_format;
1108 DO_NUMBER (2, tp->tm_min);
1110 case L_('m'):
1111 if (modifier == L_('E'))
1112 goto bad_format;
1114 DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
1116 #ifndef _LIBC
1117 case L_('N'): /* GNU extension. */
1118 if (modifier == L_('E'))
1119 goto bad_format;
1121 int n = ns, ns_digits = 9;
1122 if (width <= 0)
1123 width = ns_digits;
1124 int ndigs = ns_digits;
1125 while (width < ndigs || (1 < ndigs && n % 10 == 0))
1126 ndigs--, n /= 10;
1127 for (int j = ndigs; 0 < j; j--)
1128 buf[j - 1] = n % 10 + L_('0'), n /= 10;
1129 if (!pad)
1130 pad = L_('0');
1131 width_cpy (0, ndigs, buf);
1132 width_add (width - ndigs, 0, (void) 0);
1134 break;
1135 #endif
1137 case L_('n'):
1138 add1 (L_('\n'));
1139 break;
1141 case L_('P'):
1142 to_lowcase = true;
1143 #ifndef _NL_CURRENT
1144 format_char = L_('p');
1145 #endif
1146 FALLTHROUGH;
1147 case L_('p'):
1148 if (change_case)
1150 to_uppcase = false;
1151 to_lowcase = true;
1153 #ifdef _NL_CURRENT
1154 cpy (ap_len, ampm);
1155 break;
1156 #else
1157 goto underlying_strftime;
1158 #endif
1160 case L_('q'): /* GNU extension. */
1161 DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1);
1162 break;
1164 case L_('R'):
1165 subfmt = L_("%H:%M");
1166 goto subformat;
1168 case L_('r'):
1169 #ifdef _NL_CURRENT
1170 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1171 NLW(T_FMT_AMPM)))
1172 == L_('\0'))
1173 subfmt = L_("%I:%M:%S %p");
1174 goto subformat;
1175 #else
1176 goto underlying_strftime;
1177 #endif
1179 case L_('S'):
1180 if (modifier == L_('E'))
1181 goto bad_format;
1183 DO_NUMBER (2, tp->tm_sec);
1185 case L_('s'): /* GNU extension. */
1187 struct tm ltm;
1188 time_t t;
1190 ltm = *tp;
1191 t = mktime_z (tz, &ltm);
1193 /* Generate string value for T using time_t arithmetic;
1194 this works even if sizeof (long) < sizeof (time_t). */
1196 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1197 negative_number = t < 0;
1201 int d = t % 10;
1202 t /= 10;
1203 *--bufp = (negative_number ? -d : d) + L_('0');
1205 while (t != 0);
1207 digits = 1;
1208 always_output_a_sign = false;
1209 goto do_number_sign_and_padding;
1212 case L_('X'):
1213 if (modifier == L_('O'))
1214 goto bad_format;
1215 #ifdef _NL_CURRENT
1216 if (! (modifier == L_('E')
1217 && (*(subfmt =
1218 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1219 != L_('\0'))))
1220 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1221 goto subformat;
1222 #else
1223 goto underlying_strftime;
1224 #endif
1225 case L_('T'):
1226 subfmt = L_("%H:%M:%S");
1227 goto subformat;
1229 case L_('t'):
1230 add1 (L_('\t'));
1231 break;
1233 case L_('u'):
1234 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1236 case L_('U'):
1237 if (modifier == L_('E'))
1238 goto bad_format;
1240 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1242 case L_('V'):
1243 case L_('g'):
1244 case L_('G'):
1245 if (modifier == L_('E'))
1246 goto bad_format;
1248 /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
1249 is a leap year, except that YEAR and YEAR - 1 both work
1250 correctly even when (tp->tm_year + TM_YEAR_BASE) would
1251 overflow. */
1252 int year = (tp->tm_year
1253 + (tp->tm_year < 0
1254 ? TM_YEAR_BASE % 400
1255 : TM_YEAR_BASE % 400 - 400));
1256 int year_adjust = 0;
1257 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1259 if (days < 0)
1261 /* This ISO week belongs to the previous year. */
1262 year_adjust = -1;
1263 days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
1264 tp->tm_wday);
1266 else
1268 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1269 tp->tm_wday);
1270 if (0 <= d)
1272 /* This ISO week belongs to the next year. */
1273 year_adjust = 1;
1274 days = d;
1278 switch (*f)
1280 case L_('g'):
1282 int yy = (tp->tm_year % 100 + year_adjust) % 100;
1283 DO_YEARISH (2, false,
1284 (0 <= yy
1285 ? yy
1286 : tp->tm_year < -TM_YEAR_BASE - year_adjust
1287 ? -yy
1288 : yy + 100));
1291 case L_('G'):
1292 DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
1293 (tp->tm_year + (unsigned int) TM_YEAR_BASE
1294 + year_adjust));
1296 default:
1297 DO_NUMBER (2, days / 7 + 1);
1301 case L_('W'):
1302 if (modifier == L_('E'))
1303 goto bad_format;
1305 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1307 case L_('w'):
1308 if (modifier == L_('E'))
1309 goto bad_format;
1311 DO_NUMBER (1, tp->tm_wday);
1313 case L_('Y'):
1314 if (modifier == L_('E'))
1316 #if HAVE_STRUCT_ERA_ENTRY
1317 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1318 if (era)
1320 # ifdef COMPILE_WIDE
1321 subfmt = era->era_wformat;
1322 # else
1323 subfmt = era->era_format;
1324 # endif
1325 if (pad == 0)
1326 pad = yr_spec;
1327 goto subformat;
1329 #else
1330 goto underlying_strftime;
1331 #endif
1333 if (modifier == L_('O'))
1334 goto bad_format;
1336 DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE,
1337 tp->tm_year + (unsigned int) TM_YEAR_BASE);
1339 case L_('y'):
1340 if (modifier == L_('E'))
1342 #if HAVE_STRUCT_ERA_ENTRY
1343 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1344 if (era)
1346 int delta = tp->tm_year - era->start_date[0];
1347 if (pad == 0)
1348 pad = yr_spec;
1349 DO_NUMBER (2, (era->offset
1350 + delta * era->absolute_direction));
1352 #else
1353 goto underlying_strftime;
1354 #endif
1358 int yy = tp->tm_year % 100;
1359 if (yy < 0)
1360 yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
1361 DO_YEARISH (2, false, yy);
1364 case L_('Z'):
1365 if (change_case)
1367 to_uppcase = false;
1368 to_lowcase = true;
1371 #ifdef COMPILE_WIDE
1373 /* The zone string is always given in multibyte form. We have
1374 to transform it first. */
1375 wchar_t *wczone;
1376 size_t len;
1377 widen (zone, wczone, len);
1378 cpy (len, wczone);
1380 #else
1381 cpy (strlen (zone), zone);
1382 #endif
1383 break;
1385 case L_(':'):
1386 /* :, ::, and ::: are valid only just before 'z'.
1387 :::: etc. are rejected later. */
1388 for (colons = 1; f[colons] == L_(':'); colons++)
1389 continue;
1390 if (f[colons] != L_('z'))
1391 goto bad_format;
1392 f += colons;
1393 goto do_z_conversion;
1395 case L_('z'):
1396 colons = 0;
1398 do_z_conversion:
1399 if (tp->tm_isdst < 0)
1400 break;
1403 int diff;
1404 int hour_diff;
1405 int min_diff;
1406 int sec_diff;
1407 #if HAVE_TM_GMTOFF
1408 diff = tp->tm_gmtoff;
1409 #else
1410 if (!tz)
1411 diff = 0;
1412 else
1414 struct tm gtm;
1415 struct tm ltm;
1416 time_t lt;
1418 /* POSIX.1 requires that local time zone information be used as
1419 though strftime called tzset. */
1420 # if HAVE_TZSET
1421 if (!*tzset_called)
1423 tzset ();
1424 *tzset_called = true;
1426 # endif
1428 ltm = *tp;
1429 ltm.tm_wday = -1;
1430 lt = mktime_z (tz, &ltm);
1431 if (ltm.tm_wday < 0 || ! localtime_rz (0, &lt, &gtm))
1432 break;
1433 diff = tm_diff (&ltm, &gtm);
1435 #endif
1437 negative_number = diff < 0 || (diff == 0 && *zone == '-');
1438 hour_diff = diff / 60 / 60;
1439 min_diff = diff / 60 % 60;
1440 sec_diff = diff % 60;
1442 switch (colons)
1444 case 0: /* +hhmm */
1445 DO_TZ_OFFSET (5, 0, hour_diff * 100 + min_diff);
1447 case 1: tz_hh_mm: /* +hh:mm */
1448 DO_TZ_OFFSET (6, 04, hour_diff * 100 + min_diff);
1450 case 2: tz_hh_mm_ss: /* +hh:mm:ss */
1451 DO_TZ_OFFSET (9, 024,
1452 hour_diff * 10000 + min_diff * 100 + sec_diff);
1454 case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */
1455 if (sec_diff != 0)
1456 goto tz_hh_mm_ss;
1457 if (min_diff != 0)
1458 goto tz_hh_mm;
1459 DO_TZ_OFFSET (3, 0, hour_diff);
1461 default:
1462 goto bad_format;
1466 case L_('\0'): /* GNU extension: % at end of format. */
1467 --f;
1468 FALLTHROUGH;
1469 default:
1470 /* Unknown format; output the format, including the '%',
1471 since this is most likely the right thing to do if a
1472 multibyte string has been misparsed. */
1473 bad_format:
1475 int flen;
1476 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1477 continue;
1478 cpy (flen, &f[1 - flen]);
1480 break;
1484 #if ! FPRINTFTIME
1485 if (p && maxsize != 0)
1486 *p = L_('\0');
1487 #endif
1489 return i;