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