]> code.delx.au - gnu-emacs/blob - lib/strftime.c
Remove now-inaccurate bytecode comments
[gnu-emacs] / lib / strftime.c
1 /* Copyright (C) 1991-2001, 2003-2007, 2009-2016 Free Software Foundation, Inc.
2
3 NOTE: The canonical source of this file is maintained with the GNU C Library.
4 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19 #ifdef _LIBC
20 # define HAVE_STRUCT_ERA_ENTRY 1
21 # define HAVE_TM_GMTOFF 1
22 # define HAVE_TM_ZONE 1
23 # define HAVE_TZNAME 1
24 # define HAVE_TZSET 1
25 # include "../locale/localeinfo.h"
26 #else
27 # include <config.h>
28 # if FPRINTFTIME
29 # include "fprintftime.h"
30 # else
31 # include "strftime.h"
32 # endif
33 # include "time-internal.h"
34 #endif
35
36 #include <ctype.h>
37 #include <time.h>
38
39 #if HAVE_TZNAME && !HAVE_DECL_TZNAME
40 extern char *tzname[];
41 #endif
42
43 /* Do multibyte processing if multibyte encodings are supported, unless
44 multibyte sequences are safe in formats. Multibyte sequences are
45 safe if they cannot contain byte sequences that look like format
46 conversion specifications. The multibyte encodings used by the
47 C library on the various platforms (UTF-8, GB2312, GBK, CP936,
48 GB18030, EUC-TW, BIG5, BIG5-HKSCS, CP950, EUC-JP, EUC-KR, CP949,
49 SHIFT_JIS, CP932, JOHAB) are safe for formats, because the byte '%'
50 cannot occur in a multibyte character except in the first byte.
51
52 The DEC-HANYU encoding used on OSF/1 is not safe for formats, but
53 this encoding has never been seen in real-life use, so we ignore
54 it. */
55 #if !(defined __osf__ && 0)
56 # define MULTIBYTE_IS_FORMAT_SAFE 1
57 #endif
58 #define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE)
59
60 #if DO_MULTIBYTE
61 # include <wchar.h>
62 static const mbstate_t mbstate_zero;
63 #endif
64
65 #include <limits.h>
66 #include <stdbool.h>
67 #include <stddef.h>
68 #include <stdlib.h>
69 #include <string.h>
70
71 #ifdef COMPILE_WIDE
72 # include <endian.h>
73 # define CHAR_T wchar_t
74 # define UCHAR_T unsigned int
75 # define L_(Str) L##Str
76 # define NLW(Sym) _NL_W##Sym
77
78 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
79 # define STRLEN(s) __wcslen (s)
80
81 #else
82 # define CHAR_T char
83 # define UCHAR_T unsigned char
84 # define L_(Str) Str
85 # define NLW(Sym) Sym
86
87 # define MEMCPY(d, s, n) memcpy (d, s, n)
88 # define STRLEN(s) strlen (s)
89
90 #endif
91
92 /* Shift A right by B bits portably, by dividing A by 2**B and
93 truncating towards minus infinity. A and B should be free of side
94 effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
95 INT_BITS is the number of useful bits in an int. GNU code can
96 assume that INT_BITS is at least 32.
97
98 ISO C99 says that A >> B is implementation-defined if A < 0. Some
99 implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
100 right in the usual way when A < 0, so SHR falls back on division if
101 ordinary A >> B doesn't seem to be the usual signed shift. */
102 #define SHR(a, b) \
103 (-1 >> 1 == -1 \
104 ? (a) >> (b) \
105 : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
106
107 /* Bound on length of the string representing an integer type or expression T.
108 Subtract 1 for the sign bit if t is signed; log10 (2.0) < 146/485;
109 add 1 for integer division truncation; add 1 more for a minus sign
110 if needed. */
111 #define INT_STRLEN_BOUND(t) \
112 ((sizeof (t) * CHAR_BIT - 1) * 146 / 485 + 2)
113
114 #define TM_YEAR_BASE 1900
115
116 #ifndef __isleap
117 /* Nonzero if YEAR is a leap year (every 4 years,
118 except every 100th isn't, and every 400th is). */
119 # define __isleap(year) \
120 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
121 #endif
122
123
124 #ifdef _LIBC
125 # define mktime_z(tz, tm) mktime (tm)
126 # define tzname __tzname
127 # define tzset __tzset
128 #endif
129
130 #ifndef FPRINTFTIME
131 # define FPRINTFTIME 0
132 #endif
133
134 #if FPRINTFTIME
135 # define STREAM_OR_CHAR_T FILE
136 # define STRFTIME_ARG(x) /* empty */
137 #else
138 # define STREAM_OR_CHAR_T CHAR_T
139 # define STRFTIME_ARG(x) x,
140 #endif
141
142 #if FPRINTFTIME
143 # define memset_byte(P, Len, Byte) \
144 do { size_t _i; for (_i = 0; _i < Len; _i++) fputc (Byte, P); } while (0)
145 # define memset_space(P, Len) memset_byte (P, Len, ' ')
146 # define memset_zero(P, Len) memset_byte (P, Len, '0')
147 #elif defined COMPILE_WIDE
148 # define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
149 # define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
150 #else
151 # define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
152 # define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
153 #endif
154
155 #if FPRINTFTIME
156 # define advance(P, N)
157 #else
158 # define advance(P, N) ((P) += (N))
159 #endif
160
161 #define add(n, f) \
162 do \
163 { \
164 size_t _n = (n); \
165 size_t _w = (width < 0 ? 0 : width); \
166 size_t _incr = _n < _w ? _w : _n; \
167 if (_incr >= maxsize - i) \
168 return 0; \
169 if (p) \
170 { \
171 if (digits == 0 && _n < _w) \
172 { \
173 size_t _delta = width - _n; \
174 if (pad == L_('0')) \
175 memset_zero (p, _delta); \
176 else \
177 memset_space (p, _delta); \
178 } \
179 f; \
180 advance (p, _n); \
181 } \
182 i += _incr; \
183 } while (0)
184
185 #if FPRINTFTIME
186 # define add1(C) add (1, fputc (C, p))
187 #else
188 # define add1(C) add (1, *p = C)
189 #endif
190
191 #if FPRINTFTIME
192 # define cpy(n, s) \
193 add ((n), \
194 do \
195 { \
196 if (to_lowcase) \
197 fwrite_lowcase (p, (s), _n); \
198 else if (to_uppcase) \
199 fwrite_uppcase (p, (s), _n); \
200 else \
201 { \
202 /* Ignore the value of fwrite. The caller can determine whether \
203 an error occurred by inspecting ferror (P). All known fwrite \
204 implementations set the stream's error indicator when they \
205 fail due to ENOMEM etc., even though C11 and POSIX.1-2008 do \
206 not require this. */ \
207 fwrite (s, _n, 1, p); \
208 } \
209 } \
210 while (0) \
211 )
212 #else
213 # define cpy(n, s) \
214 add ((n), \
215 if (to_lowcase) \
216 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
217 else if (to_uppcase) \
218 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
219 else \
220 MEMCPY ((void *) p, (void const *) (s), _n))
221 #endif
222
223 #ifdef COMPILE_WIDE
224 # ifndef USE_IN_EXTENDED_LOCALE_MODEL
225 # undef __mbsrtowcs_l
226 # define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
227 # endif
228 # define widen(os, ws, l) \
229 { \
230 mbstate_t __st; \
231 const char *__s = os; \
232 memset (&__st, '\0', sizeof (__st)); \
233 l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
234 ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \
235 (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
236 }
237 #endif
238
239
240 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
241 /* We use this code also for the extended locale handling where the
242 function gets as an additional argument the locale which has to be
243 used. To access the values we have to redefine the _NL_CURRENT
244 macro. */
245 # define strftime __strftime_l
246 # define wcsftime __wcsftime_l
247 # undef _NL_CURRENT
248 # define _NL_CURRENT(category, item) \
249 (current->values[_NL_ITEM_INDEX (item)].string)
250 # define LOCALE_ARG , loc
251 # define LOCALE_PARAM_PROTO , __locale_t loc
252 # define HELPER_LOCALE_ARG , current
253 #else
254 # define LOCALE_PARAM_PROTO
255 # define LOCALE_ARG
256 # ifdef _LIBC
257 # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
258 # else
259 # define HELPER_LOCALE_ARG
260 # endif
261 #endif
262
263 #ifdef COMPILE_WIDE
264 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
265 # define TOUPPER(Ch, L) __towupper_l (Ch, L)
266 # define TOLOWER(Ch, L) __towlower_l (Ch, L)
267 # else
268 # define TOUPPER(Ch, L) towupper (Ch)
269 # define TOLOWER(Ch, L) towlower (Ch)
270 # endif
271 #else
272 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
273 # define TOUPPER(Ch, L) __toupper_l (Ch, L)
274 # define TOLOWER(Ch, L) __tolower_l (Ch, L)
275 # else
276 # define TOUPPER(Ch, L) toupper (Ch)
277 # define TOLOWER(Ch, L) tolower (Ch)
278 # endif
279 #endif
280 /* We don't use 'isdigit' here since the locale dependent
281 interpretation is not what we want here. We only need to accept
282 the arabic digits in the ASCII range. One day there is perhaps a
283 more reliable way to accept other sets of digits. */
284 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
285
286 #if FPRINTFTIME
287 static void
288 fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len)
289 {
290 while (len-- > 0)
291 {
292 fputc (TOLOWER ((UCHAR_T) *src, loc), fp);
293 ++src;
294 }
295 }
296
297 static void
298 fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len)
299 {
300 while (len-- > 0)
301 {
302 fputc (TOUPPER ((UCHAR_T) *src, loc), fp);
303 ++src;
304 }
305 }
306 #else
307 static CHAR_T *
308 memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
309 size_t len LOCALE_PARAM_PROTO)
310 {
311 while (len-- > 0)
312 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
313 return dest;
314 }
315
316 static CHAR_T *
317 memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
318 size_t len LOCALE_PARAM_PROTO)
319 {
320 while (len-- > 0)
321 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
322 return dest;
323 }
324 #endif
325
326
327 #if ! HAVE_TM_GMTOFF
328 /* Yield the difference between *A and *B,
329 measured in seconds, ignoring leap seconds. */
330 # define tm_diff ftime_tm_diff
331 static int
332 tm_diff (const struct tm *a, const struct tm *b)
333 {
334 /* Compute intervening leap days correctly even if year is negative.
335 Take care to avoid int overflow in leap day calculations,
336 but it's OK to assume that A and B are close to each other. */
337 int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
338 int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
339 int a100 = a4 / 25 - (a4 % 25 < 0);
340 int b100 = b4 / 25 - (b4 % 25 < 0);
341 int a400 = SHR (a100, 2);
342 int b400 = SHR (b100, 2);
343 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
344 int years = a->tm_year - b->tm_year;
345 int days = (365 * years + intervening_leap_days
346 + (a->tm_yday - b->tm_yday));
347 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
348 + (a->tm_min - b->tm_min))
349 + (a->tm_sec - b->tm_sec));
350 }
351 #endif /* ! HAVE_TM_GMTOFF */
352
353
354
355 /* The number of days from the first day of the first ISO week of this
356 year to the year day YDAY with week day WDAY. ISO weeks start on
357 Monday; the first ISO week has the year's first Thursday. YDAY may
358 be as small as YDAY_MINIMUM. */
359 #define ISO_WEEK_START_WDAY 1 /* Monday */
360 #define ISO_WEEK1_WDAY 4 /* Thursday */
361 #define YDAY_MINIMUM (-366)
362 #ifdef __GNUC__
363 __inline__
364 #endif
365 static int
366 iso_week_days (int yday, int wday)
367 {
368 /* Add enough to the first operand of % to make it nonnegative. */
369 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
370 return (yday
371 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
372 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
373 }
374
375
376 /* When compiling this file, GNU applications can #define my_strftime
377 to a symbol (typically nstrftime) to get an extended strftime with
378 extra arguments TZ and NS. */
379
380 #if FPRINTFTIME
381 # undef my_strftime
382 # define my_strftime fprintftime
383 #endif
384
385 #ifdef my_strftime
386 # undef HAVE_TZSET
387 # define extra_args , tz, ns
388 # define extra_args_spec , timezone_t tz, int ns
389 #else
390 # if defined COMPILE_WIDE
391 # define my_strftime wcsftime
392 # define nl_get_alt_digit _nl_get_walt_digit
393 # else
394 # define my_strftime strftime
395 # define nl_get_alt_digit _nl_get_alt_digit
396 # endif
397 # define extra_args
398 # define extra_args_spec
399 /* We don't have this information in general. */
400 # define tz 1
401 # define ns 0
402 #endif
403
404
405 /* Just like my_strftime, below, but with one more parameter, UPCASE,
406 to indicate that the result should be converted to upper case. */
407 static size_t
408 strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
409 STRFTIME_ARG (size_t maxsize)
410 const CHAR_T *format,
411 const struct tm *tp extra_args_spec LOCALE_PARAM_PROTO)
412 {
413 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
414 struct locale_data *const current = loc->__locales[LC_TIME];
415 #endif
416 #if FPRINTFTIME
417 size_t maxsize = (size_t) -1;
418 #endif
419
420 int hour12 = tp->tm_hour;
421 #ifdef _NL_CURRENT
422 /* We cannot make the following values variables since we must delay
423 the evaluation of these values until really needed since some
424 expressions might not be valid in every situation. The 'struct tm'
425 might be generated by a strptime() call that initialized
426 only a few elements. Dereference the pointers only if the format
427 requires this. Then it is ok to fail if the pointers are invalid. */
428 # define a_wkday \
429 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
430 # define f_wkday \
431 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
432 # define a_month \
433 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
434 # define f_month \
435 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
436 # define ampm \
437 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
438 ? NLW(PM_STR) : NLW(AM_STR)))
439
440 # define aw_len STRLEN (a_wkday)
441 # define am_len STRLEN (a_month)
442 # define ap_len STRLEN (ampm)
443 #endif
444 #if HAVE_TZNAME
445 char **tzname_vec = tzname;
446 #endif
447 const char *zone;
448 size_t i = 0;
449 STREAM_OR_CHAR_T *p = s;
450 const CHAR_T *f;
451 #if DO_MULTIBYTE && !defined COMPILE_WIDE
452 const char *format_end = NULL;
453 #endif
454
455 #if ! defined _LIBC && ! HAVE_RUN_TZSET_TEST
456 /* Solaris 2.5.x and 2.6 tzset sometimes modify the storage returned
457 by localtime. On such systems, we must either use the tzset and
458 localtime wrappers to work around the bug (which sets
459 HAVE_RUN_TZSET_TEST) or make a copy of the structure. */
460 struct tm copy = *tp;
461 tp = &copy;
462 #endif
463
464 zone = NULL;
465 #if HAVE_TM_ZONE
466 /* The POSIX test suite assumes that setting
467 the environment variable TZ to a new value before calling strftime()
468 will influence the result (the %Z format) even if the information in
469 TP is computed with a totally different time zone.
470 This is bogus: though POSIX allows bad behavior like this,
471 POSIX does not require it. Do the right thing instead. */
472 zone = (const char *) tp->tm_zone;
473 #endif
474 #if HAVE_TZNAME
475 if (!tz)
476 {
477 if (! (zone && *zone))
478 zone = "GMT";
479 }
480 else
481 {
482 # if !HAVE_TM_ZONE
483 /* Infer the zone name from *TZ instead of from TZNAME. */
484 tzname_vec = tz->tzname_copy;
485 # endif
486 /* POSIX.1 requires that local time zone information be used as
487 though strftime called tzset. */
488 # if HAVE_TZSET
489 tzset ();
490 # endif
491 }
492 /* The tzset() call might have changed the value. */
493 if (!(zone && *zone) && tp->tm_isdst >= 0)
494 zone = tzname_vec[tp->tm_isdst != 0];
495 #endif
496 if (! zone)
497 zone = "";
498
499 if (hour12 > 12)
500 hour12 -= 12;
501 else
502 if (hour12 == 0)
503 hour12 = 12;
504
505 for (f = format; *f != '\0'; ++f)
506 {
507 int pad = 0; /* Padding for number ('-', '_', or 0). */
508 int modifier; /* Field modifier ('E', 'O', or 0). */
509 int digits = 0; /* Max digits for numeric format. */
510 int number_value; /* Numeric value to be printed. */
511 unsigned int u_number_value; /* (unsigned int) number_value. */
512 bool negative_number; /* The number is negative. */
513 bool always_output_a_sign; /* +/- should always be output. */
514 int tz_colon_mask; /* Bitmask of where ':' should appear. */
515 const CHAR_T *subfmt;
516 CHAR_T sign_char;
517 CHAR_T *bufp;
518 CHAR_T buf[1
519 + 2 /* for the two colons in a %::z or %:::z time zone */
520 + (sizeof (int) < sizeof (time_t)
521 ? INT_STRLEN_BOUND (time_t)
522 : INT_STRLEN_BOUND (int))];
523 int width = -1;
524 bool to_lowcase = false;
525 bool to_uppcase = upcase;
526 size_t colons;
527 bool change_case = false;
528 int format_char;
529
530 #if DO_MULTIBYTE && !defined COMPILE_WIDE
531 switch (*f)
532 {
533 case L_('%'):
534 break;
535
536 case L_('\b'): case L_('\t'): case L_('\n'):
537 case L_('\v'): case L_('\f'): case L_('\r'):
538 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
539 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
540 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
541 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
542 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
543 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
544 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
545 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
546 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
547 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
548 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
549 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
550 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
551 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
552 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
553 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
554 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
555 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
556 case L_('~'):
557 /* The C Standard requires these 98 characters (plus '%') to
558 be in the basic execution character set. None of these
559 characters can start a multibyte sequence, so they need
560 not be analyzed further. */
561 add1 (*f);
562 continue;
563
564 default:
565 /* Copy this multibyte sequence until we reach its end, find
566 an error, or come back to the initial shift state. */
567 {
568 mbstate_t mbstate = mbstate_zero;
569 size_t len = 0;
570 size_t fsize;
571
572 if (! format_end)
573 format_end = f + strlen (f) + 1;
574 fsize = format_end - f;
575
576 do
577 {
578 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
579
580 if (bytes == 0)
581 break;
582
583 if (bytes == (size_t) -2)
584 {
585 len += strlen (f + len);
586 break;
587 }
588
589 if (bytes == (size_t) -1)
590 {
591 len++;
592 break;
593 }
594
595 len += bytes;
596 }
597 while (! mbsinit (&mbstate));
598
599 cpy (len, f);
600 f += len - 1;
601 continue;
602 }
603 }
604
605 #else /* ! DO_MULTIBYTE */
606
607 /* Either multibyte encodings are not supported, they are
608 safe for formats, so any non-'%' byte can be copied through,
609 or this is the wide character version. */
610 if (*f != L_('%'))
611 {
612 add1 (*f);
613 continue;
614 }
615
616 #endif /* ! DO_MULTIBYTE */
617
618 /* Check for flags that can modify a format. */
619 while (1)
620 {
621 switch (*++f)
622 {
623 /* This influences the number formats. */
624 case L_('_'):
625 case L_('-'):
626 case L_('0'):
627 pad = *f;
628 continue;
629
630 /* This changes textual output. */
631 case L_('^'):
632 to_uppcase = true;
633 continue;
634 case L_('#'):
635 change_case = true;
636 continue;
637
638 default:
639 break;
640 }
641 break;
642 }
643
644 /* As a GNU extension we allow the field width to be specified. */
645 if (ISDIGIT (*f))
646 {
647 width = 0;
648 do
649 {
650 if (width > INT_MAX / 10
651 || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
652 /* Avoid overflow. */
653 width = INT_MAX;
654 else
655 {
656 width *= 10;
657 width += *f - L_('0');
658 }
659 ++f;
660 }
661 while (ISDIGIT (*f));
662 }
663
664 /* Check for modifiers. */
665 switch (*f)
666 {
667 case L_('E'):
668 case L_('O'):
669 modifier = *f++;
670 break;
671
672 default:
673 modifier = 0;
674 break;
675 }
676
677 /* Now do the specified format. */
678 format_char = *f;
679 switch (format_char)
680 {
681 #define DO_NUMBER(d, v) \
682 do \
683 { \
684 digits = d; \
685 number_value = v; \
686 goto do_number; \
687 } \
688 while (0)
689 #define DO_SIGNED_NUMBER(d, negative, v) \
690 do \
691 { \
692 digits = d; \
693 negative_number = negative; \
694 u_number_value = v; \
695 goto do_signed_number; \
696 } \
697 while (0)
698
699 /* The mask is not what you might think.
700 When the ordinal i'th bit is set, insert a colon
701 before the i'th digit of the time zone representation. */
702 #define DO_TZ_OFFSET(d, negative, mask, v) \
703 do \
704 { \
705 digits = d; \
706 negative_number = negative; \
707 tz_colon_mask = mask; \
708 u_number_value = v; \
709 goto do_tz_offset; \
710 } \
711 while (0)
712 #define DO_NUMBER_SPACEPAD(d, v) \
713 do \
714 { \
715 digits = d; \
716 number_value = v; \
717 goto do_number_spacepad; \
718 } \
719 while (0)
720
721 case L_('%'):
722 if (modifier != 0)
723 goto bad_format;
724 add1 (*f);
725 break;
726
727 case L_('a'):
728 if (modifier != 0)
729 goto bad_format;
730 if (change_case)
731 {
732 to_uppcase = true;
733 to_lowcase = false;
734 }
735 #ifdef _NL_CURRENT
736 cpy (aw_len, a_wkday);
737 break;
738 #else
739 goto underlying_strftime;
740 #endif
741
742 case 'A':
743 if (modifier != 0)
744 goto bad_format;
745 if (change_case)
746 {
747 to_uppcase = true;
748 to_lowcase = false;
749 }
750 #ifdef _NL_CURRENT
751 cpy (STRLEN (f_wkday), f_wkday);
752 break;
753 #else
754 goto underlying_strftime;
755 #endif
756
757 case L_('b'):
758 case L_('h'):
759 if (change_case)
760 {
761 to_uppcase = true;
762 to_lowcase = false;
763 }
764 if (modifier != 0)
765 goto bad_format;
766 #ifdef _NL_CURRENT
767 cpy (am_len, a_month);
768 break;
769 #else
770 goto underlying_strftime;
771 #endif
772
773 case L_('B'):
774 if (modifier != 0)
775 goto bad_format;
776 if (change_case)
777 {
778 to_uppcase = true;
779 to_lowcase = false;
780 }
781 #ifdef _NL_CURRENT
782 cpy (STRLEN (f_month), f_month);
783 break;
784 #else
785 goto underlying_strftime;
786 #endif
787
788 case L_('c'):
789 if (modifier == L_('O'))
790 goto bad_format;
791 #ifdef _NL_CURRENT
792 if (! (modifier == 'E'
793 && (*(subfmt =
794 (const CHAR_T *) _NL_CURRENT (LC_TIME,
795 NLW(ERA_D_T_FMT)))
796 != '\0')))
797 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
798 #else
799 goto underlying_strftime;
800 #endif
801
802 subformat:
803 {
804 size_t len = strftime_case_ (to_uppcase,
805 NULL, STRFTIME_ARG ((size_t) -1)
806 subfmt,
807 tp extra_args LOCALE_ARG);
808 add (len, strftime_case_ (to_uppcase, p,
809 STRFTIME_ARG (maxsize - i)
810 subfmt,
811 tp extra_args LOCALE_ARG));
812 }
813 break;
814
815 #if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
816 underlying_strftime:
817 {
818 /* The relevant information is available only via the
819 underlying strftime implementation, so use that. */
820 char ufmt[5];
821 char *u = ufmt;
822 char ubuf[1024]; /* enough for any single format in practice */
823 size_t len;
824 /* Make sure we're calling the actual underlying strftime.
825 In some cases, config.h contains something like
826 "#define strftime rpl_strftime". */
827 # ifdef strftime
828 # undef strftime
829 size_t strftime ();
830 # endif
831
832 /* The space helps distinguish strftime failure from empty
833 output. */
834 *u++ = ' ';
835 *u++ = '%';
836 if (modifier != 0)
837 *u++ = modifier;
838 *u++ = format_char;
839 *u = '\0';
840 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
841 if (len != 0)
842 cpy (len - 1, ubuf + 1);
843 }
844 break;
845 #endif
846
847 case L_('C'):
848 if (modifier == L_('O'))
849 goto bad_format;
850 if (modifier == L_('E'))
851 {
852 #if HAVE_STRUCT_ERA_ENTRY
853 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
854 if (era)
855 {
856 # ifdef COMPILE_WIDE
857 size_t len = __wcslen (era->era_wname);
858 cpy (len, era->era_wname);
859 # else
860 size_t len = strlen (era->era_name);
861 cpy (len, era->era_name);
862 # endif
863 break;
864 }
865 #else
866 goto underlying_strftime;
867 #endif
868 }
869
870 {
871 int century = tp->tm_year / 100 + TM_YEAR_BASE / 100;
872 century -= tp->tm_year % 100 < 0 && 0 < century;
873 DO_SIGNED_NUMBER (2, tp->tm_year < - TM_YEAR_BASE, century);
874 }
875
876 case L_('x'):
877 if (modifier == L_('O'))
878 goto bad_format;
879 #ifdef _NL_CURRENT
880 if (! (modifier == L_('E')
881 && (*(subfmt =
882 (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
883 != L_('\0'))))
884 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
885 goto subformat;
886 #else
887 goto underlying_strftime;
888 #endif
889 case L_('D'):
890 if (modifier != 0)
891 goto bad_format;
892 subfmt = L_("%m/%d/%y");
893 goto subformat;
894
895 case L_('d'):
896 if (modifier == L_('E'))
897 goto bad_format;
898
899 DO_NUMBER (2, tp->tm_mday);
900
901 case L_('e'):
902 if (modifier == L_('E'))
903 goto bad_format;
904
905 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
906
907 /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
908 and then jump to one of these labels. */
909
910 do_tz_offset:
911 always_output_a_sign = true;
912 goto do_number_body;
913
914 do_number_spacepad:
915 /* Force '_' flag unless overridden by '0' or '-' flag. */
916 if (pad != L_('0') && pad != L_('-'))
917 pad = L_('_');
918
919 do_number:
920 /* Format NUMBER_VALUE according to the MODIFIER flag. */
921 negative_number = number_value < 0;
922 u_number_value = number_value;
923
924 do_signed_number:
925 always_output_a_sign = false;
926 tz_colon_mask = 0;
927
928 do_number_body:
929 /* Format U_NUMBER_VALUE according to the MODIFIER flag.
930 NEGATIVE_NUMBER is nonzero if the original number was
931 negative; in this case it was converted directly to
932 unsigned int (i.e., modulo (UINT_MAX + 1)) without
933 negating it. */
934 if (modifier == L_('O') && !negative_number)
935 {
936 #ifdef _NL_CURRENT
937 /* Get the locale specific alternate representation of
938 the number. If none exist NULL is returned. */
939 const CHAR_T *cp = nl_get_alt_digit (u_number_value
940 HELPER_LOCALE_ARG);
941
942 if (cp != NULL)
943 {
944 size_t digitlen = STRLEN (cp);
945 if (digitlen != 0)
946 {
947 cpy (digitlen, cp);
948 break;
949 }
950 }
951 #else
952 goto underlying_strftime;
953 #endif
954 }
955
956 bufp = buf + sizeof (buf) / sizeof (buf[0]);
957
958 if (negative_number)
959 u_number_value = - u_number_value;
960
961 do
962 {
963 if (tz_colon_mask & 1)
964 *--bufp = ':';
965 tz_colon_mask >>= 1;
966 *--bufp = u_number_value % 10 + L_('0');
967 u_number_value /= 10;
968 }
969 while (u_number_value != 0 || tz_colon_mask != 0);
970
971 do_number_sign_and_padding:
972 if (digits < width)
973 digits = width;
974
975 sign_char = (negative_number ? L_('-')
976 : always_output_a_sign ? L_('+')
977 : 0);
978
979 if (pad == L_('-'))
980 {
981 if (sign_char)
982 add1 (sign_char);
983 }
984 else
985 {
986 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
987 - bufp) - !!sign_char;
988
989 if (padding > 0)
990 {
991 if (pad == L_('_'))
992 {
993 if ((size_t) padding >= maxsize - i)
994 return 0;
995
996 if (p)
997 memset_space (p, padding);
998 i += padding;
999 width = width > padding ? width - padding : 0;
1000 if (sign_char)
1001 add1 (sign_char);
1002 }
1003 else
1004 {
1005 if ((size_t) digits >= maxsize - i)
1006 return 0;
1007
1008 if (sign_char)
1009 add1 (sign_char);
1010
1011 if (p)
1012 memset_zero (p, padding);
1013 i += padding;
1014 width = 0;
1015 }
1016 }
1017 else
1018 {
1019 if (sign_char)
1020 add1 (sign_char);
1021 }
1022 }
1023
1024 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1025 break;
1026
1027 case L_('F'):
1028 if (modifier != 0)
1029 goto bad_format;
1030 subfmt = L_("%Y-%m-%d");
1031 goto subformat;
1032
1033 case L_('H'):
1034 if (modifier == L_('E'))
1035 goto bad_format;
1036
1037 DO_NUMBER (2, tp->tm_hour);
1038
1039 case L_('I'):
1040 if (modifier == L_('E'))
1041 goto bad_format;
1042
1043 DO_NUMBER (2, hour12);
1044
1045 case L_('k'): /* GNU extension. */
1046 if (modifier == L_('E'))
1047 goto bad_format;
1048
1049 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1050
1051 case L_('l'): /* GNU extension. */
1052 if (modifier == L_('E'))
1053 goto bad_format;
1054
1055 DO_NUMBER_SPACEPAD (2, hour12);
1056
1057 case L_('j'):
1058 if (modifier == L_('E'))
1059 goto bad_format;
1060
1061 DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
1062
1063 case L_('M'):
1064 if (modifier == L_('E'))
1065 goto bad_format;
1066
1067 DO_NUMBER (2, tp->tm_min);
1068
1069 case L_('m'):
1070 if (modifier == L_('E'))
1071 goto bad_format;
1072
1073 DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
1074
1075 #ifndef _LIBC
1076 case L_('N'): /* GNU extension. */
1077 if (modifier == L_('E'))
1078 goto bad_format;
1079
1080 number_value = ns;
1081 if (width == -1)
1082 width = 9;
1083 else
1084 {
1085 /* Take an explicit width less than 9 as a precision. */
1086 int j;
1087 for (j = width; j < 9; j++)
1088 number_value /= 10;
1089 }
1090
1091 DO_NUMBER (width, number_value);
1092 #endif
1093
1094 case L_('n'):
1095 add1 (L_('\n'));
1096 break;
1097
1098 case L_('P'):
1099 to_lowcase = true;
1100 #ifndef _NL_CURRENT
1101 format_char = L_('p');
1102 #endif
1103 /* FALLTHROUGH */
1104
1105 case L_('p'):
1106 if (change_case)
1107 {
1108 to_uppcase = false;
1109 to_lowcase = true;
1110 }
1111 #ifdef _NL_CURRENT
1112 cpy (ap_len, ampm);
1113 break;
1114 #else
1115 goto underlying_strftime;
1116 #endif
1117
1118 case L_('R'):
1119 subfmt = L_("%H:%M");
1120 goto subformat;
1121
1122 case L_('r'):
1123 #ifdef _NL_CURRENT
1124 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1125 NLW(T_FMT_AMPM)))
1126 == L_('\0'))
1127 subfmt = L_("%I:%M:%S %p");
1128 goto subformat;
1129 #else
1130 goto underlying_strftime;
1131 #endif
1132
1133 case L_('S'):
1134 if (modifier == L_('E'))
1135 goto bad_format;
1136
1137 DO_NUMBER (2, tp->tm_sec);
1138
1139 case L_('s'): /* GNU extension. */
1140 {
1141 struct tm ltm;
1142 time_t t;
1143
1144 ltm = *tp;
1145 t = mktime_z (tz, &ltm);
1146
1147 /* Generate string value for T using time_t arithmetic;
1148 this works even if sizeof (long) < sizeof (time_t). */
1149
1150 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1151 negative_number = t < 0;
1152
1153 do
1154 {
1155 int d = t % 10;
1156 t /= 10;
1157 *--bufp = (negative_number ? -d : d) + L_('0');
1158 }
1159 while (t != 0);
1160
1161 digits = 1;
1162 always_output_a_sign = false;
1163 goto do_number_sign_and_padding;
1164 }
1165
1166 case L_('X'):
1167 if (modifier == L_('O'))
1168 goto bad_format;
1169 #ifdef _NL_CURRENT
1170 if (! (modifier == L_('E')
1171 && (*(subfmt =
1172 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1173 != L_('\0'))))
1174 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1175 goto subformat;
1176 #else
1177 goto underlying_strftime;
1178 #endif
1179 case L_('T'):
1180 subfmt = L_("%H:%M:%S");
1181 goto subformat;
1182
1183 case L_('t'):
1184 add1 (L_('\t'));
1185 break;
1186
1187 case L_('u'):
1188 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1189
1190 case L_('U'):
1191 if (modifier == L_('E'))
1192 goto bad_format;
1193
1194 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1195
1196 case L_('V'):
1197 case L_('g'):
1198 case L_('G'):
1199 if (modifier == L_('E'))
1200 goto bad_format;
1201 {
1202 /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
1203 is a leap year, except that YEAR and YEAR - 1 both work
1204 correctly even when (tp->tm_year + TM_YEAR_BASE) would
1205 overflow. */
1206 int year = (tp->tm_year
1207 + (tp->tm_year < 0
1208 ? TM_YEAR_BASE % 400
1209 : TM_YEAR_BASE % 400 - 400));
1210 int year_adjust = 0;
1211 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1212
1213 if (days < 0)
1214 {
1215 /* This ISO week belongs to the previous year. */
1216 year_adjust = -1;
1217 days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
1218 tp->tm_wday);
1219 }
1220 else
1221 {
1222 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1223 tp->tm_wday);
1224 if (0 <= d)
1225 {
1226 /* This ISO week belongs to the next year. */
1227 year_adjust = 1;
1228 days = d;
1229 }
1230 }
1231
1232 switch (*f)
1233 {
1234 case L_('g'):
1235 {
1236 int yy = (tp->tm_year % 100 + year_adjust) % 100;
1237 DO_NUMBER (2, (0 <= yy
1238 ? yy
1239 : tp->tm_year < -TM_YEAR_BASE - year_adjust
1240 ? -yy
1241 : yy + 100));
1242 }
1243
1244 case L_('G'):
1245 DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
1246 (tp->tm_year + (unsigned int) TM_YEAR_BASE
1247 + year_adjust));
1248
1249 default:
1250 DO_NUMBER (2, days / 7 + 1);
1251 }
1252 }
1253
1254 case L_('W'):
1255 if (modifier == L_('E'))
1256 goto bad_format;
1257
1258 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1259
1260 case L_('w'):
1261 if (modifier == L_('E'))
1262 goto bad_format;
1263
1264 DO_NUMBER (1, tp->tm_wday);
1265
1266 case L_('Y'):
1267 if (modifier == 'E')
1268 {
1269 #if HAVE_STRUCT_ERA_ENTRY
1270 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1271 if (era)
1272 {
1273 # ifdef COMPILE_WIDE
1274 subfmt = era->era_wformat;
1275 # else
1276 subfmt = era->era_format;
1277 # endif
1278 goto subformat;
1279 }
1280 #else
1281 goto underlying_strftime;
1282 #endif
1283 }
1284 if (modifier == L_('O'))
1285 goto bad_format;
1286
1287 DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE,
1288 tp->tm_year + (unsigned int) TM_YEAR_BASE);
1289
1290 case L_('y'):
1291 if (modifier == L_('E'))
1292 {
1293 #if HAVE_STRUCT_ERA_ENTRY
1294 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1295 if (era)
1296 {
1297 int delta = tp->tm_year - era->start_date[0];
1298 DO_NUMBER (1, (era->offset
1299 + delta * era->absolute_direction));
1300 }
1301 #else
1302 goto underlying_strftime;
1303 #endif
1304 }
1305
1306 {
1307 int yy = tp->tm_year % 100;
1308 if (yy < 0)
1309 yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
1310 DO_NUMBER (2, yy);
1311 }
1312
1313 case L_('Z'):
1314 if (change_case)
1315 {
1316 to_uppcase = false;
1317 to_lowcase = true;
1318 }
1319
1320 #ifdef COMPILE_WIDE
1321 {
1322 /* The zone string is always given in multibyte form. We have
1323 to transform it first. */
1324 wchar_t *wczone;
1325 size_t len;
1326 widen (zone, wczone, len);
1327 cpy (len, wczone);
1328 }
1329 #else
1330 cpy (strlen (zone), zone);
1331 #endif
1332 break;
1333
1334 case L_(':'):
1335 /* :, ::, and ::: are valid only just before 'z'.
1336 :::: etc. are rejected later. */
1337 for (colons = 1; f[colons] == L_(':'); colons++)
1338 continue;
1339 if (f[colons] != L_('z'))
1340 goto bad_format;
1341 f += colons;
1342 goto do_z_conversion;
1343
1344 case L_('z'):
1345 colons = 0;
1346
1347 do_z_conversion:
1348 if (tp->tm_isdst < 0)
1349 break;
1350
1351 {
1352 int diff;
1353 int hour_diff;
1354 int min_diff;
1355 int sec_diff;
1356 #if HAVE_TM_GMTOFF
1357 diff = tp->tm_gmtoff;
1358 #else
1359 if (!tz)
1360 diff = 0;
1361 else
1362 {
1363 struct tm gtm;
1364 struct tm ltm;
1365 time_t lt;
1366
1367 ltm = *tp;
1368 lt = mktime_z (tz, &ltm);
1369
1370 if (lt == (time_t) -1)
1371 {
1372 /* mktime returns -1 for errors, but -1 is also a
1373 valid time_t value. Check whether an error really
1374 occurred. */
1375 struct tm tm;
1376
1377 if (! localtime_rz (tz, &lt, &tm)
1378 || ((ltm.tm_sec ^ tm.tm_sec)
1379 | (ltm.tm_min ^ tm.tm_min)
1380 | (ltm.tm_hour ^ tm.tm_hour)
1381 | (ltm.tm_mday ^ tm.tm_mday)
1382 | (ltm.tm_mon ^ tm.tm_mon)
1383 | (ltm.tm_year ^ tm.tm_year)))
1384 break;
1385 }
1386
1387 if (! localtime_rz (0, &lt, &gtm))
1388 break;
1389
1390 diff = tm_diff (&ltm, &gtm);
1391 }
1392 #endif
1393
1394 hour_diff = diff / 60 / 60;
1395 min_diff = diff / 60 % 60;
1396 sec_diff = diff % 60;
1397
1398 switch (colons)
1399 {
1400 case 0: /* +hhmm */
1401 DO_TZ_OFFSET (5, diff < 0, 0, hour_diff * 100 + min_diff);
1402
1403 case 1: tz_hh_mm: /* +hh:mm */
1404 DO_TZ_OFFSET (6, diff < 0, 04, hour_diff * 100 + min_diff);
1405
1406 case 2: tz_hh_mm_ss: /* +hh:mm:ss */
1407 DO_TZ_OFFSET (9, diff < 0, 024,
1408 hour_diff * 10000 + min_diff * 100 + sec_diff);
1409
1410 case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */
1411 if (sec_diff != 0)
1412 goto tz_hh_mm_ss;
1413 if (min_diff != 0)
1414 goto tz_hh_mm;
1415 DO_TZ_OFFSET (3, diff < 0, 0, hour_diff);
1416
1417 default:
1418 goto bad_format;
1419 }
1420 }
1421
1422 case L_('\0'): /* GNU extension: % at end of format. */
1423 --f;
1424 /* Fall through. */
1425 default:
1426 /* Unknown format; output the format, including the '%',
1427 since this is most likely the right thing to do if a
1428 multibyte string has been misparsed. */
1429 bad_format:
1430 {
1431 int flen;
1432 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1433 continue;
1434 cpy (flen, &f[1 - flen]);
1435 }
1436 break;
1437 }
1438 }
1439
1440 #if ! FPRINTFTIME
1441 if (p && maxsize != 0)
1442 *p = L_('\0');
1443 #endif
1444
1445 return i;
1446 }
1447
1448 /* Write information from TP into S according to the format
1449 string FORMAT, writing no more that MAXSIZE characters
1450 (including the terminating '\0') and returning number of
1451 characters written. If S is NULL, nothing will be written
1452 anywhere, so to determine how many characters would be
1453 written, use NULL for S and (size_t) -1 for MAXSIZE. */
1454 size_t
1455 my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
1456 const CHAR_T *format,
1457 const struct tm *tp extra_args_spec LOCALE_PARAM_PROTO)
1458 {
1459 return strftime_case_ (false, s, STRFTIME_ARG (maxsize)
1460 format, tp extra_args LOCALE_ARG);
1461 }
1462
1463 #if defined _LIBC && ! FPRINTFTIME
1464 libc_hidden_def (my_strftime)
1465 #endif