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