Update.
[glibc.git] / time / strftime.c
blob3c8cfeed17d1c724dcd882a45d8d820cd0de8453
1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 #ifdef _LIBC
24 # define HAVE_LIMITS_H 1
25 # define HAVE_MBLEN 1
26 # define HAVE_MBRLEN 1
27 # define HAVE_STRUCT_ERA_ENTRY 1
28 # define HAVE_TM_GMTOFF 1
29 # define HAVE_TM_ZONE 1
30 # define HAVE_TZNAME 1
31 # define HAVE_TZSET 1
32 # define MULTIBYTE_IS_FORMAT_SAFE 1
33 # define STDC_HEADERS 1
34 # include "../locale/localeinfo.h"
35 #endif
37 #if defined emacs && !defined HAVE_BCOPY
38 # define HAVE_MEMCPY 1
39 #endif
41 #include <ctype.h>
42 #include <sys/types.h> /* Some systems define `time_t' here. */
44 #ifdef TIME_WITH_SYS_TIME
45 # include <sys/time.h>
46 # include <time.h>
47 #else
48 # ifdef HAVE_SYS_TIME_H
49 # include <sys/time.h>
50 # else
51 # include <time.h>
52 # endif
53 #endif
54 #if HAVE_TZNAME
55 extern char *tzname[];
56 #endif
58 /* Do multibyte processing if multibytes are supported, unless
59 multibyte sequences are safe in formats. Multibyte sequences are
60 safe if they cannot contain byte sequences that look like format
61 conversion specifications. The GNU C Library uses UTF8 multibyte
62 encoding, which is safe for formats, but strftime.c can be used
63 with other C libraries that use unsafe encodings. */
64 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
66 #if DO_MULTIBYTE
67 # if HAVE_MBRLEN
68 # include <wchar.h>
69 # else
70 /* Simulate mbrlen with mblen as best we can. */
71 # define mbstate_t int
72 # define mbrlen(s, n, ps) mblen (s, n)
73 # define mbsinit(ps) (*(ps) == 0)
74 # endif
75 static const mbstate_t mbstate_zero;
76 #endif
78 #if HAVE_LIMITS_H
79 # include <limits.h>
80 #endif
82 #if STDC_HEADERS
83 # include <stddef.h>
84 # include <stdlib.h>
85 # include <string.h>
86 #endif
88 #ifdef COMPILE_WIDE
89 # include <endian.h>
90 # define CHAR_T wchar_t
91 # define UCHAR_T unsigned int
92 # define L_(Str) L##Str
93 # define NLW(Sym) _NL_W##Sym
95 # define MEMCPY(d, s, n) wmemcpy (d, s, n)
96 # define STRLEN(s) wcslen (s)
98 #else
99 # define CHAR_T char
100 # define UCHAR_T unsigned char
101 # define L_(Str) Str
102 # define NLW(Sym) Sym
104 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
105 # define MEMCPY(d, s, n) bcopy ((s), (d), (n))
106 # else
107 # define MEMCPY(d, s, n) memcpy ((d), (s), (n))
108 # endif
109 # define STRLEN(s) strlen (s)
111 # ifdef _LIBC
112 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
113 # else
114 # ifndef HAVE_MEMPCPY
115 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
116 # endif
117 # endif
118 #endif
120 #ifndef __P
121 # if defined __GNUC__ || (defined __STDC__ && __STDC__)
122 # define __P(args) args
123 # else
124 # define __P(args) ()
125 # endif /* GCC. */
126 #endif /* Not __P. */
128 #ifndef PTR
129 # ifdef __STDC__
130 # define PTR void *
131 # else
132 # define PTR char *
133 # endif
134 #endif
136 #ifndef CHAR_BIT
137 # define CHAR_BIT 8
138 #endif
140 #ifndef NULL
141 # define NULL 0
142 #endif
144 #define TYPE_SIGNED(t) ((t) -1 < 0)
146 /* Bound on length of the string representing an integer value of type t.
147 Subtract one for the sign bit if t is signed;
148 302 / 1000 is log10 (2) rounded up;
149 add one for integer division truncation;
150 add one more for a minus sign if t is signed. */
151 #define INT_STRLEN_BOUND(t) \
152 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
154 #define TM_YEAR_BASE 1900
156 #ifndef __isleap
157 /* Nonzero if YEAR is a leap year (every 4 years,
158 except every 100th isn't, and every 400th is). */
159 # define __isleap(year) \
160 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
161 #endif
164 #ifdef _LIBC
165 # define my_strftime_gmtime_r __gmtime_r
166 # define my_strftime_localtime_r __localtime_r
167 # define tzname __tzname
168 # define tzset __tzset
169 #else
171 /* If we're a strftime substitute in a GNU program, then prefer gmtime
172 to gmtime_r, since many gmtime_r implementations are buggy.
173 Similarly for localtime_r. */
175 # if ! HAVE_TM_GMTOFF
176 static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
177 static struct tm *
178 my_strftime_gmtime_r (t, tp)
179 const time_t *t;
180 struct tm *tp;
182 struct tm *l = gmtime (t);
183 if (! l)
184 return 0;
185 *tp = *l;
186 return tp;
188 # endif /* ! HAVE_TM_GMTOFF */
190 static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
191 static struct tm *
192 my_strftime_localtime_r (t, tp)
193 const time_t *t;
194 struct tm *tp;
196 struct tm *l = localtime (t);
197 if (! l)
198 return 0;
199 *tp = *l;
200 return tp;
202 #endif /* ! defined _LIBC */
205 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
206 /* Some systems lack the `memset' function and we don't want to
207 introduce additional dependencies. */
208 /* The SGI compiler reportedly barfs on the trailing null
209 if we use a string constant as the initializer. 28 June 1997, rms. */
210 static const CHAR_T spaces[16] = /* " " */
212 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
213 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
215 static const CHAR_T zeroes[16] = /* "0000000000000000" */
217 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
218 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
221 # define memset_space(P, Len) \
222 do { \
223 int _len = (Len); \
225 do \
227 int _this = _len > 16 ? 16 : _len; \
228 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
229 _len -= _this; \
231 while (_len > 0); \
232 } while (0)
234 # define memset_zero(P, Len) \
235 do { \
236 int _len = (Len); \
238 do \
240 int _this = _len > 16 ? 16 : _len; \
241 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
242 _len -= _this; \
244 while (_len > 0); \
245 } while (0)
246 #else
247 # ifdef COMPILE_WIDE
248 # define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
249 # define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
250 # else
251 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
252 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
253 # endif
254 #endif
256 #define add(n, f) \
257 do \
259 int _n = (n); \
260 int _delta = width - _n; \
261 int _incr = _n + (_delta > 0 ? _delta : 0); \
262 if (i + _incr >= maxsize) \
263 return 0; \
264 if (p) \
266 if (_delta > 0) \
268 if (pad == L_('0')) \
269 memset_zero (p, _delta); \
270 else \
271 memset_space (p, _delta); \
273 f; \
274 p += _n; \
276 i += _incr; \
277 } while (0)
279 #define cpy(n, s) \
280 add ((n), \
281 if (to_lowcase) \
282 memcpy_lowcase (p, (s), _n); \
283 else if (to_uppcase) \
284 memcpy_uppcase (p, (s), _n); \
285 else \
286 MEMCPY ((PTR) p, (PTR) (s), _n))
288 #ifdef COMPILE_WIDE
289 # define widen(os, ws, l) \
291 mbstate_t __st; \
292 const char *__s = os; \
293 memset (&__st, '\0', sizeof (__st)); \
294 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
295 ws = alloca ((l + 1) * sizeof (wchar_t)); \
296 (void) __mbsrtowcs (ws, &__s, l, &__st); \
298 #endif
301 #ifdef COMPILE_WIDE
302 # define TOUPPER(Ch) towupper (Ch)
303 # define TOLOWER(Ch) towlower (Ch)
304 #else
305 # ifdef _LIBC
306 # define TOUPPER(Ch) toupper (Ch)
307 # define TOLOWER(Ch) tolower (Ch)
308 # else
309 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
310 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
311 # endif
312 #endif
313 /* We don't use `isdigit' here since the locale dependent
314 interpretation is not what we want here. We only need to accept
315 the arabic digits in the ASCII range. One day there is perhaps a
316 more reliable way to accept other sets of digits. */
317 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
319 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
320 size_t len));
322 static CHAR_T *
323 memcpy_lowcase (dest, src, len)
324 CHAR_T *dest;
325 const CHAR_T *src;
326 size_t len;
328 while (len-- > 0)
329 dest[len] = TOLOWER ((UCHAR_T) src[len]);
330 return dest;
333 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
334 size_t len));
336 static CHAR_T *
337 memcpy_uppcase (dest, src, len)
338 CHAR_T *dest;
339 const CHAR_T *src;
340 size_t len;
342 while (len-- > 0)
343 dest[len] = TOUPPER ((UCHAR_T) src[len]);
344 return dest;
348 #if ! HAVE_TM_GMTOFF
349 /* Yield the difference between *A and *B,
350 measured in seconds, ignoring leap seconds. */
351 # define tm_diff ftime_tm_diff
352 static int tm_diff __P ((const struct tm *, const struct tm *));
353 static int
354 tm_diff (a, b)
355 const struct tm *a;
356 const struct tm *b;
358 /* Compute intervening leap days correctly even if year is negative.
359 Take care to avoid int overflow in leap day calculations,
360 but it's OK to assume that A and B are close to each other. */
361 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
362 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
363 int a100 = a4 / 25 - (a4 % 25 < 0);
364 int b100 = b4 / 25 - (b4 % 25 < 0);
365 int a400 = a100 >> 2;
366 int b400 = b100 >> 2;
367 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
368 int years = a->tm_year - b->tm_year;
369 int days = (365 * years + intervening_leap_days
370 + (a->tm_yday - b->tm_yday));
371 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
372 + (a->tm_min - b->tm_min))
373 + (a->tm_sec - b->tm_sec));
375 #endif /* ! HAVE_TM_GMTOFF */
379 /* The number of days from the first day of the first ISO week of this
380 year to the year day YDAY with week day WDAY. ISO weeks start on
381 Monday; the first ISO week has the year's first Thursday. YDAY may
382 be as small as YDAY_MINIMUM. */
383 #define ISO_WEEK_START_WDAY 1 /* Monday */
384 #define ISO_WEEK1_WDAY 4 /* Thursday */
385 #define YDAY_MINIMUM (-366)
386 static int iso_week_days __P ((int, int));
387 #ifdef __GNUC__
388 __inline__
389 #endif
390 static int
391 iso_week_days (yday, wday)
392 int yday;
393 int wday;
395 /* Add enough to the first operand of % to make it nonnegative. */
396 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
397 return (yday
398 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
399 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
403 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
404 static CHAR_T const weekday_name[][10] =
406 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
407 L_("Thursday"), L_("Friday"), L_("Saturday")
409 static CHAR_T const month_name[][10] =
411 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
412 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
413 L_("November"), L_("December")
415 #endif
418 #ifdef emacs
419 # define my_strftime emacs_strftimeu
420 # define ut_argument , ut
421 # define ut_argument_spec int ut;
422 # define ut_argument_spec_iso , int ut
423 #else
424 # ifdef COMPILE_WIDE
425 # define my_strftime wcsftime
426 # else
427 # define my_strftime strftime
428 # endif
429 # define ut_argument
430 # define ut_argument_spec
431 # define ut_argument_spec_iso
432 /* We don't have this information in general. */
433 # define ut 0
434 #endif
436 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
437 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
438 Work around this bug by copying *tp before it might be munged. */
439 size_t _strftime_copytm __P ((char *, size_t, const char *,
440 const struct tm * ut_argument_spec_iso));
441 size_t
442 my_strftime (s, maxsize, format, tp ut_argument)
443 CHAR_T *s;
444 size_t maxsize;
445 const CHAR_T *format;
446 const struct tm *tp;
447 ut_argument_spec
449 struct tm tmcopy;
450 tmcopy = *tp;
451 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
453 # undef my_strftime
454 # define my_strftime(S, Maxsize, Format, Tp) \
455 _strftime_copytm (S, Maxsize, Format, Tp)
456 #endif
459 /* Write information from TP into S according to the format
460 string FORMAT, writing no more that MAXSIZE characters
461 (including the terminating '\0') and returning number of
462 characters written. If S is NULL, nothing will be written
463 anywhere, so to determine how many characters would be
464 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
465 size_t
466 my_strftime (s, maxsize, format, tp ut_argument)
467 CHAR_T *s;
468 size_t maxsize;
469 const CHAR_T *format;
470 const struct tm *tp;
471 ut_argument_spec
473 int hour12 = tp->tm_hour;
474 #ifdef _NL_CURRENT
475 /* We cannot make the following values variables since we must delay
476 the evaluation of these values until really needed since some
477 expressions might not be valid in every situation. The `struct tm'
478 might be generated by a strptime() call that initialized
479 only a few elements. Dereference the pointers only if the format
480 requires this. Then it is ok to fail if the pointers are invalid. */
481 # define a_wkday \
482 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
483 # define f_wkday \
484 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
485 # define a_month \
486 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
487 # define f_month \
488 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
489 # define ampm \
490 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
491 ? NLW(PM_STR) : NLW(AM_STR)))
493 # define aw_len STRLEN (a_wkday)
494 # define am_len STRLEN (a_month)
495 # define ap_len STRLEN (ampm)
496 #else
497 # if !HAVE_STRFTIME
498 # define f_wkday (weekday_name[tp->tm_wday])
499 # define f_month (month_name[tp->tm_mon])
500 # define a_wkday f_wkday
501 # define a_month f_month
502 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
504 size_t aw_len = 3;
505 size_t am_len = 3;
506 size_t ap_len = 2;
507 # endif
508 #endif
509 const char *zone;
510 size_t i = 0;
511 CHAR_T *p = s;
512 const CHAR_T *f;
514 zone = NULL;
515 #if HAVE_TM_ZONE
516 /* The POSIX test suite assumes that setting
517 the environment variable TZ to a new value before calling strftime()
518 will influence the result (the %Z format) even if the information in
519 TP is computed with a totally different time zone.
520 This is bogus: though POSIX allows bad behavior like this,
521 POSIX does not require it. Do the right thing instead. */
522 zone = (const char *) tp->tm_zone;
523 #endif
524 #if HAVE_TZNAME
525 if (ut)
527 if (! (zone && *zone))
528 zone = "GMT";
530 else
532 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
533 time zone names contained in the external variable `tzname' shall
534 be set as if the tzset() function had been called. */
535 # if HAVE_TZSET
536 tzset ();
537 # endif
539 #endif
541 if (hour12 > 12)
542 hour12 -= 12;
543 else
544 if (hour12 == 0)
545 hour12 = 12;
547 for (f = format; *f != '\0'; ++f)
549 int pad = 0; /* Padding for number ('-', '_', or 0). */
550 int modifier; /* Field modifier ('E', 'O', or 0). */
551 int digits; /* Max digits for numeric format. */
552 int number_value; /* Numeric value to be printed. */
553 int negative_number; /* 1 if the number is negative. */
554 const CHAR_T *subfmt;
555 CHAR_T *bufp;
556 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
557 ? INT_STRLEN_BOUND (time_t)
558 : INT_STRLEN_BOUND (int))];
559 int width = -1;
560 int to_lowcase = 0;
561 int to_uppcase = 0;
562 int change_case = 0;
563 int format_char;
565 #if DO_MULTIBYTE && !defined COMPILE_WIDE
566 switch (*f)
568 case L_('%'):
569 break;
571 case L_('\a'): case L_('\b'): case L_('\t'): case L_('\n'):
572 case L_('\v'): case L_('\f'): case L_('\r'):
573 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
574 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
575 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
576 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
577 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
578 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
579 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
580 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
581 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
582 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
583 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
584 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
585 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
586 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
587 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
588 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
589 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
590 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
591 case L_('~'):
592 /* The C Standard requires these 98 characters (plus '%') to
593 be in the basic execution character set. None of these
594 characters can start a multibyte sequence, so they need
595 not be analyzed further. */
596 add (1, *p = *f);
597 continue;
599 default:
600 /* Copy this multibyte sequence until we reach its end, find
601 an error, or come back to the initial shift state. */
603 mbstate_t mbstate = mbstate_zero;
604 size_t len = 0;
608 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
610 if (bytes == 0)
611 break;
613 if (bytes == (size_t) -2)
615 len += strlen (f + len);
616 break;
619 if (bytes == (size_t) -1)
621 len++;
622 break;
625 len += bytes;
627 while (! mbsinit (&mbstate));
629 cpy (len, f);
630 f += len - 1;
631 continue;
635 #else /* ! DO_MULTIBYTE */
637 /* Either multibyte encodings are not supported, they are
638 safe for formats, so any non-'%' byte can be copied through,
639 or this is the wide character version. */
640 if (*f != L_('%'))
642 add (1, *p = *f);
643 continue;
646 #endif /* ! DO_MULTIBYTE */
648 /* Check for flags that can modify a format. */
649 while (1)
651 switch (*++f)
653 /* This influences the number formats. */
654 case L_('_'):
655 case L_('-'):
656 case L_('0'):
657 pad = *f;
658 continue;
660 /* This changes textual output. */
661 case L_('^'):
662 to_uppcase = 1;
663 continue;
664 case L_('#'):
665 change_case = 1;
666 continue;
668 default:
669 break;
671 break;
674 /* As a GNU extension we allow to specify the field width. */
675 if (ISDIGIT (*f))
677 width = 0;
680 width *= 10;
681 width += *f - L_('0');
682 ++f;
684 while (ISDIGIT (*f));
687 /* Check for modifiers. */
688 switch (*f)
690 case L_('E'):
691 case L_('O'):
692 modifier = *f++;
693 break;
695 default:
696 modifier = 0;
697 break;
700 /* Now do the specified format. */
701 format_char = *f;
702 switch (format_char)
704 #define DO_NUMBER(d, v) \
705 digits = width == -1 ? d : width; \
706 number_value = v; goto do_number
707 #define DO_NUMBER_SPACEPAD(d, v) \
708 digits = width == -1 ? d : width; \
709 number_value = v; goto do_number_spacepad
711 case L_('%'):
712 if (modifier != 0)
713 goto bad_format;
714 add (1, *p = *f);
715 break;
717 case L_('a'):
718 if (modifier != 0)
719 goto bad_format;
720 if (change_case)
722 to_uppcase = 1;
723 to_lowcase = 0;
725 #if defined _NL_CURRENT || !HAVE_STRFTIME
726 cpy (aw_len, a_wkday);
727 break;
728 #else
729 goto underlying_strftime;
730 #endif
732 case 'A':
733 if (modifier != 0)
734 goto bad_format;
735 if (change_case)
737 to_uppcase = 1;
738 to_lowcase = 0;
740 #if defined _NL_CURRENT || !HAVE_STRFTIME
741 cpy (STRLEN (f_wkday), f_wkday);
742 break;
743 #else
744 goto underlying_strftime;
745 #endif
747 case L_('b'):
748 case L_('h'): /* POSIX.2 extension. */
749 if (modifier != 0)
750 goto bad_format;
751 #if defined _NL_CURRENT || !HAVE_STRFTIME
752 cpy (am_len, a_month);
753 break;
754 #else
755 goto underlying_strftime;
756 #endif
758 case L_('B'):
759 if (modifier != 0)
760 goto bad_format;
761 if (change_case)
763 to_uppcase = 1;
764 to_lowcase = 0;
766 #if defined _NL_CURRENT || !HAVE_STRFTIME
767 cpy (STRLEN (f_month), f_month);
768 break;
769 #else
770 goto underlying_strftime;
771 #endif
773 case L_('c'):
774 if (modifier == L_('O'))
775 goto bad_format;
776 #ifdef _NL_CURRENT
777 if (! (modifier == 'E'
778 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
779 NLW(ERA_D_T_FMT)))
780 != '\0')))
781 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
782 #else
783 # if HAVE_STRFTIME
784 goto underlying_strftime;
785 # else
786 subfmt = L_("%a %b %e %H:%M:%S %Y");
787 # endif
788 #endif
790 subformat:
792 CHAR_T *old_start = p;
793 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp);
794 add (len, my_strftime (p, maxsize - i, subfmt, tp));
796 if (to_uppcase)
797 while (old_start < p)
799 *old_start = TOUPPER ((UCHAR_T) *old_start);
800 ++old_start;
803 break;
805 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
806 underlying_strftime:
808 /* The relevant information is available only via the
809 underlying strftime implementation, so use that. */
810 char ufmt[4];
811 char *u = ufmt;
812 char ubuf[1024]; /* enough for any single format in practice */
813 size_t len;
814 *u++ = '%';
815 if (modifier != 0)
816 *u++ = modifier;
817 *u++ = format_char;
818 *u = '\0';
819 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
820 if (len == 0 && ubuf[0] != '\0')
821 return 0;
822 cpy (len, ubuf);
824 break;
825 #endif
827 case L_('C'): /* POSIX.2 extension. */
828 if (modifier == L_('O'))
829 goto bad_format;
830 if (modifier == L_('E'))
832 #if HAVE_STRUCT_ERA_ENTRY
833 struct era_entry *era = _nl_get_era_entry (tp);
834 if (era)
836 # ifdef COMPILE_WIDE
837 /* The wide name is after the multi byte name and
838 format. */
839 wchar_t *ws;
840 size_t len;
841 char *tcp = strchr (era->name_fmt, '\0') + 1;
842 tcp = strchr (tcp, '\0') + 1;
843 tcp += 3 - (((tcp - era->name_fmt) + 3) & 3);
844 ws = (wchar_t *) tcp;
845 len = wcslen (ws);
846 cpy (len, ws);
847 # else
848 size_t len = strlen (era->name_fmt);
849 cpy (len, era->name_fmt);
850 # endif
851 break;
853 #else
854 # if HAVE_STRFTIME
855 goto underlying_strftime;
856 # endif
857 #endif
861 int year = tp->tm_year + TM_YEAR_BASE;
862 DO_NUMBER (1, year / 100 - (year % 100 < 0));
865 case L_('x'):
866 if (modifier == L_('O'))
867 goto bad_format;
868 #ifdef _NL_CURRENT
869 if (! (modifier == L_('E')
870 && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
871 NLW(ERA_D_FMT)))
872 != L_('\0'))))
873 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
874 goto subformat;
875 #else
876 # if HAVE_STRFTIME
877 goto underlying_strftime;
878 # else
879 /* Fall through. */
880 # endif
881 #endif
882 case L_('D'): /* POSIX.2 extension. */
883 if (modifier != 0)
884 goto bad_format;
885 subfmt = L_("%m/%d/%y");
886 goto subformat;
888 case L_('d'):
889 if (modifier == L_('E'))
890 goto bad_format;
892 DO_NUMBER (2, tp->tm_mday);
894 case L_('e'): /* POSIX.2 extension. */
895 if (modifier == L_('E'))
896 goto bad_format;
898 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
900 /* All numeric formats set DIGITS and NUMBER_VALUE and then
901 jump to one of these two labels. */
903 do_number_spacepad:
904 /* Force `_' flag unless overwritten by `0' flag. */
905 if (pad != L_('0'))
906 pad = L_('_');
908 do_number:
909 /* Format the number according to the MODIFIER flag. */
911 if (modifier == L_('O') && 0 <= number_value)
913 #ifdef _NL_CURRENT
914 /* Get the locale specific alternate representation of
915 the number NUMBER_VALUE. If none exist NULL is returned. */
916 # ifdef COMPILE_WIDE
917 const wchar_t *cp = _nl_get_walt_digit (number_value);
918 # else
919 const char *cp = _nl_get_alt_digit (number_value);
920 # endif
922 if (cp != NULL)
924 size_t digitlen = STRLEN (cp);
925 if (digitlen != 0)
927 cpy (digitlen, cp);
928 break;
931 #else
932 # if HAVE_STRFTIME
933 goto underlying_strftime;
934 # endif
935 #endif
938 unsigned int u = number_value;
940 bufp = buf + sizeof (buf) / sizeof (buf[0]);
941 negative_number = number_value < 0;
943 if (negative_number)
944 u = -u;
947 *--bufp = u % 10 + L_('0');
948 while ((u /= 10) != 0);
951 do_number_sign_and_padding:
952 if (negative_number)
953 *--bufp = L_('-');
955 if (pad != L_('-'))
957 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
958 - bufp);
960 if (pad == L_('_'))
962 while (0 < padding--)
963 *--bufp = L_(' ');
965 else
967 bufp += negative_number;
968 while (0 < padding--)
969 *--bufp = L_('0');
970 if (negative_number)
971 *--bufp = L_('-');
975 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
976 break;
978 case L_('F'):
979 if (modifier != 0)
980 goto bad_format;
981 subfmt = L_("%Y-%m-%d");
982 goto subformat;
984 case L_('H'):
985 if (modifier == L_('E'))
986 goto bad_format;
988 DO_NUMBER (2, tp->tm_hour);
990 case L_('I'):
991 if (modifier == L_('E'))
992 goto bad_format;
994 DO_NUMBER (2, hour12);
996 case L_('k'): /* GNU extension. */
997 if (modifier == L_('E'))
998 goto bad_format;
1000 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1002 case L_('l'): /* GNU extension. */
1003 if (modifier == L_('E'))
1004 goto bad_format;
1006 DO_NUMBER_SPACEPAD (2, hour12);
1008 case L_('j'):
1009 if (modifier == L_('E'))
1010 goto bad_format;
1012 DO_NUMBER (3, 1 + tp->tm_yday);
1014 case L_('M'):
1015 if (modifier == L_('E'))
1016 goto bad_format;
1018 DO_NUMBER (2, tp->tm_min);
1020 case L_('m'):
1021 if (modifier == L_('E'))
1022 goto bad_format;
1024 DO_NUMBER (2, tp->tm_mon + 1);
1026 case L_('n'): /* POSIX.2 extension. */
1027 add (1, *p = L_('\n'));
1028 break;
1030 case L_('P'):
1031 to_lowcase = 1;
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 = 0;
1041 to_lowcase = 1;
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'): /* GNU extension. */
1051 subfmt = L_("%H:%M");
1052 goto subformat;
1054 case L_('r'): /* POSIX.2 extension. */
1055 #ifdef _NL_CURRENT
1056 if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1057 NLW(T_FMT_AMPM))) == L_('\0'))
1058 #endif
1059 subfmt = L_("%I:%M:%S %p");
1060 goto subformat;
1062 case L_('S'):
1063 if (modifier == L_('E'))
1064 goto bad_format;
1066 DO_NUMBER (2, tp->tm_sec);
1068 case L_('s'): /* GNU extension. */
1070 struct tm ltm;
1071 time_t t;
1073 ltm = *tp;
1074 t = mktime (&ltm);
1076 /* Generate string value for T using time_t arithmetic;
1077 this works even if sizeof (long) < sizeof (time_t). */
1079 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1080 negative_number = t < 0;
1084 int d = t % 10;
1085 t /= 10;
1087 if (negative_number)
1089 d = -d;
1091 /* Adjust if division truncates to minus infinity. */
1092 if (0 < -1 % 10 && d < 0)
1094 t++;
1095 d += 10;
1099 *--bufp = d + L_('0');
1101 while (t != 0);
1103 digits = 1;
1104 goto do_number_sign_and_padding;
1107 case L_('X'):
1108 if (modifier == L_('O'))
1109 goto bad_format;
1110 #ifdef _NL_CURRENT
1111 if (! (modifier == L_('E')
1112 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1113 NLW(ERA_T_FMT)))
1114 != L_('\0'))))
1115 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1116 goto subformat;
1117 #else
1118 # if HAVE_STRFTIME
1119 goto underlying_strftime;
1120 # else
1121 /* Fall through. */
1122 # endif
1123 #endif
1124 case L_('T'): /* POSIX.2 extension. */
1125 subfmt = L_("%H:%M:%S");
1126 goto subformat;
1128 case L_('t'): /* POSIX.2 extension. */
1129 add (1, *p = L_('\t'));
1130 break;
1132 case L_('u'): /* POSIX.2 extension. */
1133 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1135 case L_('U'):
1136 if (modifier == L_('E'))
1137 goto bad_format;
1139 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1141 case L_('V'):
1142 case L_('g'): /* GNU extension. */
1143 case L_('G'): /* GNU extension. */
1144 if (modifier == L_('E'))
1145 goto bad_format;
1147 int year = tp->tm_year + TM_YEAR_BASE;
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--;
1154 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
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++;
1165 days = d;
1169 switch (*f)
1171 case L_('g'):
1172 DO_NUMBER (2, (year % 100 + 100) % 100);
1174 case L_('G'):
1175 DO_NUMBER (1, year);
1177 default:
1178 DO_NUMBER (2, days / 7 + 1);
1182 case L_('W'):
1183 if (modifier == L_('E'))
1184 goto bad_format;
1186 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1188 case L_('w'):
1189 if (modifier == L_('E'))
1190 goto bad_format;
1192 DO_NUMBER (1, tp->tm_wday);
1194 case L_('Y'):
1195 if (modifier == 'E')
1197 #if HAVE_STRUCT_ERA_ENTRY
1198 struct era_entry *era = _nl_get_era_entry (tp);
1199 if (era)
1201 # ifdef COMPILE_WIDE
1202 /* The wide name is after the multi byte name and
1203 format. */
1204 char *tcp = strchr (era->name_fmt, '\0') + 1;
1205 tcp = strchr (tcp, '\0') + 1;
1206 tcp += 3 - (((tcp - era->name_fmt) + 3) & 3);
1207 subfmt = (wchar_t *) tcp;
1208 subfmt = wcschr (subfmt, L'\0') + 1;
1209 # else
1210 subfmt = strchr (era->name_fmt, '\0') + 1;
1211 # endif
1212 goto subformat;
1214 #else
1215 # if HAVE_STRFTIME
1216 goto underlying_strftime;
1217 # endif
1218 #endif
1220 if (modifier == L_('O'))
1221 goto bad_format;
1222 else
1223 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1225 case L_('y'):
1226 if (modifier == L_('E'))
1228 #if HAVE_STRUCT_ERA_ENTRY
1229 struct era_entry *era = _nl_get_era_entry (tp);
1230 if (era)
1232 int delta = tp->tm_year - era->start_date[0];
1233 DO_NUMBER (1, (era->offset
1234 + (era->direction == '-' ? -delta : delta)));
1236 #else
1237 # if HAVE_STRFTIME
1238 goto underlying_strftime;
1239 # endif
1240 #endif
1242 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1244 case L_('Z'):
1245 if (change_case)
1247 to_uppcase = 0;
1248 to_lowcase = 1;
1251 #if HAVE_TZNAME
1252 /* The tzset() call might have changed the value. */
1253 if (!(zone && *zone) && tp->tm_isdst >= 0)
1254 zone = tzname[tp->tm_isdst];
1255 #endif
1256 if (! zone)
1257 zone = ""; /* POSIX.2 requires the empty string here. */
1259 #ifdef COMPILE_WIDE
1261 /* The zone string is always given in multibyte form. We have
1262 to transform it first. */
1263 wchar_t *wczone;
1264 size_t len;
1265 widen (zone, wczone, len);
1266 cpy (len, wczone);
1268 #else
1269 cpy (strlen (zone), zone);
1270 #endif
1271 break;
1273 case L_('z'): /* GNU extension. */
1274 if (tp->tm_isdst < 0)
1275 break;
1278 int diff;
1279 #if HAVE_TM_GMTOFF
1280 diff = tp->tm_gmtoff;
1281 #else
1282 if (ut)
1283 diff = 0;
1284 else
1286 struct tm gtm;
1287 struct tm ltm;
1288 time_t lt;
1290 ltm = *tp;
1291 lt = mktime (&ltm);
1293 if (lt == (time_t) -1)
1295 /* mktime returns -1 for errors, but -1 is also a
1296 valid time_t value. Check whether an error really
1297 occurred. */
1298 struct tm tm;
1300 if (! my_strftime_localtime_r (&lt, &tm)
1301 || ((ltm.tm_sec ^ tm.tm_sec)
1302 | (ltm.tm_min ^ tm.tm_min)
1303 | (ltm.tm_hour ^ tm.tm_hour)
1304 | (ltm.tm_mday ^ tm.tm_mday)
1305 | (ltm.tm_mon ^ tm.tm_mon)
1306 | (ltm.tm_year ^ tm.tm_year)))
1307 break;
1310 if (! my_strftime_gmtime_r (&lt, &gtm))
1311 break;
1313 diff = tm_diff (&ltm, &gtm);
1315 #endif
1317 if (diff < 0)
1319 add (1, *p = L_('-'));
1320 diff = -diff;
1322 else
1323 add (1, *p = L_('+'));
1325 diff /= 60;
1326 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1329 case L_('\0'): /* GNU extension: % at end of format. */
1330 --f;
1331 /* Fall through. */
1332 default:
1333 /* Unknown format; output the format, including the '%',
1334 since this is most likely the right thing to do if a
1335 multibyte string has been misparsed. */
1336 bad_format:
1338 int flen;
1339 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1340 continue;
1341 cpy (flen, &f[1 - flen]);
1343 break;
1347 if (p && maxsize != 0)
1348 *p = L_('\0');
1349 return i;
1353 #ifdef emacs
1354 /* For Emacs we have a separate interface which corresponds to the normal
1355 strftime function and does not have the extra information whether the
1356 TP arguments comes from a `gmtime' call or not. */
1357 size_t
1358 emacs_strftime (s, maxsize, format, tp)
1359 char *s;
1360 size_t maxsize;
1361 const char *format;
1362 const struct tm *tp;
1364 return my_strftime (s, maxsize, format, tp, 0);
1366 #endif