(Supported Configurations): Add s390-linux.
[glibc.git] / time / strftime.c
blob95dbae1850a5a82d875ea4946d8fdb5de10851b4
1 /* Copyright (C) 1991-1999, 2000 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 #else
87 # ifndef HAVE_MEMCPY
88 # define memcpy(d, s, n) bcopy ((s), (d), (n))
89 # endif
90 #endif
92 #ifdef COMPILE_WIDE
93 # include <endian.h>
94 # define CHAR_T wchar_t
95 # define UCHAR_T unsigned int
96 # define L_(Str) L##Str
97 # define NLW(Sym) _NL_W##Sym
99 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
100 # define STRLEN(s) __wcslen (s)
102 #else
103 # define CHAR_T char
104 # define UCHAR_T unsigned char
105 # define L_(Str) Str
106 # define NLW(Sym) Sym
108 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
109 # define MEMCPY(d, s, n) bcopy ((s), (d), (n))
110 # else
111 # define MEMCPY(d, s, n) memcpy ((d), (s), (n))
112 # endif
113 # define STRLEN(s) strlen (s)
115 # ifdef _LIBC
116 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
117 # else
118 # ifndef HAVE_MEMPCPY
119 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
120 # endif
121 # endif
122 #endif
124 #ifndef __P
125 # if defined __GNUC__ || (defined __STDC__ && __STDC__)
126 # define __P(args) args
127 # else
128 # define __P(args) ()
129 # endif /* GCC. */
130 #endif /* Not __P. */
132 #ifndef PTR
133 # ifdef __STDC__
134 # define PTR void *
135 # else
136 # define PTR char *
137 # endif
138 #endif
140 #ifndef CHAR_BIT
141 # define CHAR_BIT 8
142 #endif
144 #ifndef NULL
145 # define NULL 0
146 #endif
148 #define TYPE_SIGNED(t) ((t) -1 < 0)
150 /* Bound on length of the string representing an integer value of type t.
151 Subtract one for the sign bit if t is signed;
152 302 / 1000 is log10 (2) rounded up;
153 add one for integer division truncation;
154 add one more for a minus sign if t is signed. */
155 #define INT_STRLEN_BOUND(t) \
156 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
158 #define TM_YEAR_BASE 1900
160 #ifndef __isleap
161 /* Nonzero if YEAR is a leap year (every 4 years,
162 except every 100th isn't, and every 400th is). */
163 # define __isleap(year) \
164 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
165 #endif
168 #ifdef _LIBC
169 # define my_strftime_gmtime_r __gmtime_r
170 # define my_strftime_localtime_r __localtime_r
171 # define tzname __tzname
172 # define tzset __tzset
173 #else
175 /* If we're a strftime substitute in a GNU program, then prefer gmtime
176 to gmtime_r, since many gmtime_r implementations are buggy.
177 Similarly for localtime_r. */
179 # if ! HAVE_TM_GMTOFF
180 static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
181 static struct tm *
182 my_strftime_gmtime_r (t, tp)
183 const time_t *t;
184 struct tm *tp;
186 struct tm *l = gmtime (t);
187 if (! l)
188 return 0;
189 *tp = *l;
190 return tp;
192 # endif /* ! HAVE_TM_GMTOFF */
194 static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
195 static struct tm *
196 my_strftime_localtime_r (t, tp)
197 const time_t *t;
198 struct tm *tp;
200 struct tm *l = localtime (t);
201 if (! l)
202 return 0;
203 *tp = *l;
204 return tp;
206 #endif /* ! defined _LIBC */
209 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
210 /* Some systems lack the `memset' function and we don't want to
211 introduce additional dependencies. */
212 /* The SGI compiler reportedly barfs on the trailing null
213 if we use a string constant as the initializer. 28 June 1997, rms. */
214 static const CHAR_T spaces[16] = /* " " */
216 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
217 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
219 static const CHAR_T zeroes[16] = /* "0000000000000000" */
221 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
222 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
225 # define memset_space(P, Len) \
226 do { \
227 int _len = (Len); \
229 do \
231 int _this = _len > 16 ? 16 : _len; \
232 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
233 _len -= _this; \
235 while (_len > 0); \
236 } while (0)
238 # define memset_zero(P, Len) \
239 do { \
240 int _len = (Len); \
242 do \
244 int _this = _len > 16 ? 16 : _len; \
245 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
246 _len -= _this; \
248 while (_len > 0); \
249 } while (0)
250 #else
251 # ifdef COMPILE_WIDE
252 # define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
253 # define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
254 # else
255 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
256 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
257 # endif
258 #endif
260 #define add(n, f) \
261 do \
263 int _n = (n); \
264 int _delta = width - _n; \
265 int _incr = _n + (_delta > 0 ? _delta : 0); \
266 if (i + _incr >= maxsize) \
267 return 0; \
268 if (p) \
270 if (_delta > 0) \
272 if (pad == L_('0')) \
273 memset_zero (p, _delta); \
274 else \
275 memset_space (p, _delta); \
277 f; \
278 p += _n; \
280 i += _incr; \
281 } while (0)
283 #define cpy(n, s) \
284 add ((n), \
285 if (to_lowcase) \
286 memcpy_lowcase (p, (s), _n); \
287 else if (to_uppcase) \
288 memcpy_uppcase (p, (s), _n); \
289 else \
290 MEMCPY ((PTR) p, (PTR) (s), _n))
292 #ifdef COMPILE_WIDE
293 # define widen(os, ws, l) \
295 mbstate_t __st; \
296 const char *__s = os; \
297 memset (&__st, '\0', sizeof (__st)); \
298 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
299 ws = alloca ((l + 1) * sizeof (wchar_t)); \
300 (void) __mbsrtowcs (ws, &__s, l, &__st); \
302 #endif
305 #ifdef COMPILE_WIDE
306 # define TOUPPER(Ch) towupper (Ch)
307 # define TOLOWER(Ch) towlower (Ch)
308 #else
309 # ifdef _LIBC
310 # define TOUPPER(Ch) toupper (Ch)
311 # define TOLOWER(Ch) tolower (Ch)
312 # else
313 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
314 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
315 # endif
316 #endif
317 /* We don't use `isdigit' here since the locale dependent
318 interpretation is not what we want here. We only need to accept
319 the arabic digits in the ASCII range. One day there is perhaps a
320 more reliable way to accept other sets of digits. */
321 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
323 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
324 size_t len));
326 static CHAR_T *
327 memcpy_lowcase (dest, src, len)
328 CHAR_T *dest;
329 const CHAR_T *src;
330 size_t len;
332 while (len-- > 0)
333 dest[len] = TOLOWER ((UCHAR_T) src[len]);
334 return dest;
337 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
338 size_t len));
340 static CHAR_T *
341 memcpy_uppcase (dest, src, len)
342 CHAR_T *dest;
343 const CHAR_T *src;
344 size_t len;
346 while (len-- > 0)
347 dest[len] = TOUPPER ((UCHAR_T) src[len]);
348 return dest;
352 #if ! HAVE_TM_GMTOFF
353 /* Yield the difference between *A and *B,
354 measured in seconds, ignoring leap seconds. */
355 # define tm_diff ftime_tm_diff
356 static int tm_diff __P ((const struct tm *, const struct tm *));
357 static int
358 tm_diff (a, b)
359 const struct tm *a;
360 const struct tm *b;
362 /* Compute intervening leap days correctly even if year is negative.
363 Take care to avoid int overflow in leap day calculations,
364 but it's OK to assume that A and B are close to each other. */
365 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
366 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
367 int a100 = a4 / 25 - (a4 % 25 < 0);
368 int b100 = b4 / 25 - (b4 % 25 < 0);
369 int a400 = a100 >> 2;
370 int b400 = b100 >> 2;
371 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
372 int years = a->tm_year - b->tm_year;
373 int days = (365 * years + intervening_leap_days
374 + (a->tm_yday - b->tm_yday));
375 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
376 + (a->tm_min - b->tm_min))
377 + (a->tm_sec - b->tm_sec));
379 #endif /* ! HAVE_TM_GMTOFF */
383 /* The number of days from the first day of the first ISO week of this
384 year to the year day YDAY with week day WDAY. ISO weeks start on
385 Monday; the first ISO week has the year's first Thursday. YDAY may
386 be as small as YDAY_MINIMUM. */
387 #define ISO_WEEK_START_WDAY 1 /* Monday */
388 #define ISO_WEEK1_WDAY 4 /* Thursday */
389 #define YDAY_MINIMUM (-366)
390 static int iso_week_days __P ((int, int));
391 #ifdef __GNUC__
392 __inline__
393 #endif
394 static int
395 iso_week_days (yday, wday)
396 int yday;
397 int wday;
399 /* Add enough to the first operand of % to make it nonnegative. */
400 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
401 return (yday
402 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
403 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
407 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
408 static CHAR_T const weekday_name[][10] =
410 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
411 L_("Thursday"), L_("Friday"), L_("Saturday")
413 static CHAR_T const month_name[][10] =
415 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
416 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
417 L_("November"), L_("December")
419 #endif
422 #ifdef emacs
423 # define my_strftime emacs_strftimeu
424 # define ut_argument , ut
425 # define ut_argument_spec int ut;
426 # define ut_argument_spec_iso , int ut
427 #else
428 # ifdef COMPILE_WIDE
429 # define my_strftime wcsftime
430 # else
431 # define my_strftime strftime
432 # endif
433 # define ut_argument
434 # define ut_argument_spec
435 # define ut_argument_spec_iso
436 /* We don't have this information in general. */
437 # define ut 0
438 #endif
440 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
441 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
442 Work around this bug by copying *tp before it might be munged. */
443 size_t _strftime_copytm __P ((char *, size_t, const char *,
444 const struct tm * ut_argument_spec_iso));
445 size_t
446 my_strftime (s, maxsize, format, tp ut_argument)
447 CHAR_T *s;
448 size_t maxsize;
449 const CHAR_T *format;
450 const struct tm *tp;
451 ut_argument_spec
453 struct tm tmcopy;
454 tmcopy = *tp;
455 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
457 # undef my_strftime
458 # define my_strftime(S, Maxsize, Format, Tp) \
459 _strftime_copytm (S, Maxsize, Format, Tp)
460 #endif
463 /* Write information from TP into S according to the format
464 string FORMAT, writing no more that MAXSIZE characters
465 (including the terminating '\0') and returning number of
466 characters written. If S is NULL, nothing will be written
467 anywhere, so to determine how many characters would be
468 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
469 size_t
470 my_strftime (s, maxsize, format, tp ut_argument)
471 CHAR_T *s;
472 size_t maxsize;
473 const CHAR_T *format;
474 const struct tm *tp;
475 ut_argument_spec
477 int hour12 = tp->tm_hour;
478 #ifdef _NL_CURRENT
479 /* We cannot make the following values variables since we must delay
480 the evaluation of these values until really needed since some
481 expressions might not be valid in every situation. The `struct tm'
482 might be generated by a strptime() call that initialized
483 only a few elements. Dereference the pointers only if the format
484 requires this. Then it is ok to fail if the pointers are invalid. */
485 # define a_wkday \
486 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
487 # define f_wkday \
488 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
489 # define a_month \
490 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
491 # define f_month \
492 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
493 # define ampm \
494 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
495 ? NLW(PM_STR) : NLW(AM_STR)))
497 # define aw_len STRLEN (a_wkday)
498 # define am_len STRLEN (a_month)
499 # define ap_len STRLEN (ampm)
500 #else
501 # if !HAVE_STRFTIME
502 # define f_wkday (weekday_name[tp->tm_wday])
503 # define f_month (month_name[tp->tm_mon])
504 # define a_wkday f_wkday
505 # define a_month f_month
506 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
508 size_t aw_len = 3;
509 size_t am_len = 3;
510 size_t ap_len = 2;
511 # endif
512 #endif
513 const char *zone;
514 size_t i = 0;
515 CHAR_T *p = s;
516 const CHAR_T *f;
518 zone = NULL;
519 #if HAVE_TM_ZONE
520 /* The POSIX test suite assumes that setting
521 the environment variable TZ to a new value before calling strftime()
522 will influence the result (the %Z format) even if the information in
523 TP is computed with a totally different time zone.
524 This is bogus: though POSIX allows bad behavior like this,
525 POSIX does not require it. Do the right thing instead. */
526 zone = (const char *) tp->tm_zone;
527 #endif
528 #if HAVE_TZNAME
529 if (ut)
531 if (! (zone && *zone))
532 zone = "GMT";
534 else
536 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
537 time zone names contained in the external variable `tzname' shall
538 be set as if the tzset() function had been called. */
539 # if HAVE_TZSET
540 tzset ();
541 # endif
543 #endif
545 if (hour12 > 12)
546 hour12 -= 12;
547 else
548 if (hour12 == 0)
549 hour12 = 12;
551 for (f = format; *f != '\0'; ++f)
553 int pad = 0; /* Padding for number ('-', '_', or 0). */
554 int modifier; /* Field modifier ('E', 'O', or 0). */
555 int digits; /* Max digits for numeric format. */
556 int number_value; /* Numeric value to be printed. */
557 int negative_number; /* 1 if the number is negative. */
558 const CHAR_T *subfmt;
559 CHAR_T *bufp;
560 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
561 ? INT_STRLEN_BOUND (time_t)
562 : INT_STRLEN_BOUND (int))];
563 int width = -1;
564 int to_lowcase = 0;
565 int to_uppcase = 0;
566 int change_case = 0;
567 int format_char;
569 #if DO_MULTIBYTE && !defined COMPILE_WIDE
570 switch (*f)
572 case L_('%'):
573 break;
575 case L_('\b'): case L_('\t'): case L_('\n'):
576 case L_('\v'): case L_('\f'): case L_('\r'):
577 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
578 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
579 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
580 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
581 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
582 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
583 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
584 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
585 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
586 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
587 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
588 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
589 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
590 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
591 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
592 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
593 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
594 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
595 case L_('~'):
596 /* The C Standard requires these 98 characters (plus '%') to
597 be in the basic execution character set. None of these
598 characters can start a multibyte sequence, so they need
599 not be analyzed further. */
600 add (1, *p = *f);
601 continue;
603 default:
604 /* Copy this multibyte sequence until we reach its end, find
605 an error, or come back to the initial shift state. */
607 mbstate_t mbstate = mbstate_zero;
608 size_t len = 0;
612 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
614 if (bytes == 0)
615 break;
617 if (bytes == (size_t) -2)
619 len += strlen (f + len);
620 break;
623 if (bytes == (size_t) -1)
625 len++;
626 break;
629 len += bytes;
631 while (! mbsinit (&mbstate));
633 cpy (len, f);
634 f += len - 1;
635 continue;
639 #else /* ! DO_MULTIBYTE */
641 /* Either multibyte encodings are not supported, they are
642 safe for formats, so any non-'%' byte can be copied through,
643 or this is the wide character version. */
644 if (*f != L_('%'))
646 add (1, *p = *f);
647 continue;
650 #endif /* ! DO_MULTIBYTE */
652 /* Check for flags that can modify a format. */
653 while (1)
655 switch (*++f)
657 /* This influences the number formats. */
658 case L_('_'):
659 case L_('-'):
660 case L_('0'):
661 pad = *f;
662 continue;
664 /* This changes textual output. */
665 case L_('^'):
666 to_uppcase = 1;
667 continue;
668 case L_('#'):
669 change_case = 1;
670 continue;
672 default:
673 break;
675 break;
678 /* As a GNU extension we allow to specify the field width. */
679 if (ISDIGIT (*f))
681 width = 0;
684 width *= 10;
685 width += *f - L_('0');
686 ++f;
688 while (ISDIGIT (*f));
691 /* Check for modifiers. */
692 switch (*f)
694 case L_('E'):
695 case L_('O'):
696 modifier = *f++;
697 break;
699 default:
700 modifier = 0;
701 break;
704 /* Now do the specified format. */
705 format_char = *f;
706 switch (format_char)
708 #define DO_NUMBER(d, v) \
709 digits = width == -1 ? d : width; \
710 number_value = v; goto do_number
711 #define DO_NUMBER_SPACEPAD(d, v) \
712 digits = width == -1 ? d : width; \
713 number_value = v; goto do_number_spacepad
715 case L_('%'):
716 if (modifier != 0)
717 goto bad_format;
718 add (1, *p = *f);
719 break;
721 case L_('a'):
722 if (modifier != 0)
723 goto bad_format;
724 if (change_case)
726 to_uppcase = 1;
727 to_lowcase = 0;
729 #if defined _NL_CURRENT || !HAVE_STRFTIME
730 cpy (aw_len, a_wkday);
731 break;
732 #else
733 goto underlying_strftime;
734 #endif
736 case 'A':
737 if (modifier != 0)
738 goto bad_format;
739 if (change_case)
741 to_uppcase = 1;
742 to_lowcase = 0;
744 #if defined _NL_CURRENT || !HAVE_STRFTIME
745 cpy (STRLEN (f_wkday), f_wkday);
746 break;
747 #else
748 goto underlying_strftime;
749 #endif
751 case L_('b'):
752 case L_('h'): /* POSIX.2 extension. */
753 if (change_case)
755 to_uppcase = 1;
756 to_lowcase = 0;
758 if (modifier != 0)
759 goto bad_format;
760 #if defined _NL_CURRENT || !HAVE_STRFTIME
761 cpy (am_len, a_month);
762 break;
763 #else
764 goto underlying_strftime;
765 #endif
767 case L_('B'):
768 if (modifier != 0)
769 goto bad_format;
770 if (change_case)
772 to_uppcase = 1;
773 to_lowcase = 0;
775 #if defined _NL_CURRENT || !HAVE_STRFTIME
776 cpy (STRLEN (f_month), f_month);
777 break;
778 #else
779 goto underlying_strftime;
780 #endif
782 case L_('c'):
783 if (modifier == L_('O'))
784 goto bad_format;
785 #ifdef _NL_CURRENT
786 if (! (modifier == 'E'
787 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
788 NLW(ERA_D_T_FMT)))
789 != '\0')))
790 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
791 #else
792 # if HAVE_STRFTIME
793 goto underlying_strftime;
794 # else
795 subfmt = L_("%a %b %e %H:%M:%S %Y");
796 # endif
797 #endif
799 subformat:
801 CHAR_T *old_start = p;
802 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp);
803 add (len, my_strftime (p, maxsize - i, subfmt, tp));
805 if (to_uppcase)
806 while (old_start < p)
808 *old_start = TOUPPER ((UCHAR_T) *old_start);
809 ++old_start;
812 break;
814 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
815 underlying_strftime:
817 /* The relevant information is available only via the
818 underlying strftime implementation, so use that. */
819 char ufmt[4];
820 char *u = ufmt;
821 char ubuf[1024]; /* enough for any single format in practice */
822 size_t len;
823 /* Make sure we're calling the actual underlying strftime.
824 In some cases, config.h contains something like
825 "#define strftime rpl_strftime". */
826 # ifdef strftime
827 # undef strftime
828 size_t strftime ();
829 # endif
831 *u++ = '%';
832 if (modifier != 0)
833 *u++ = modifier;
834 *u++ = format_char;
835 *u = '\0';
836 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
837 if (len == 0 && ubuf[0] != '\0')
838 return 0;
839 cpy (len, ubuf);
841 break;
842 #endif
844 case L_('C'): /* POSIX.2 extension. */
845 if (modifier == L_('O'))
846 goto bad_format;
847 if (modifier == L_('E'))
849 #if HAVE_STRUCT_ERA_ENTRY
850 struct era_entry *era = _nl_get_era_entry (tp);
851 if (era)
853 # ifdef COMPILE_WIDE
854 size_t len = __wcslen (era->era_wname);
855 cpy (len, era->era_wname);
856 # else
857 size_t len = strlen (era->era_name);
858 cpy (len, era->era_name);
859 # endif
860 break;
862 #else
863 # if HAVE_STRFTIME
864 goto underlying_strftime;
865 # endif
866 #endif
870 int year = tp->tm_year + TM_YEAR_BASE;
871 DO_NUMBER (1, year / 100 - (year % 100 < 0));
874 case L_('x'):
875 if (modifier == L_('O'))
876 goto bad_format;
877 #ifdef _NL_CURRENT
878 if (! (modifier == L_('E')
879 && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
880 NLW(ERA_D_FMT)))
881 != L_('\0'))))
882 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
883 goto subformat;
884 #else
885 # if HAVE_STRFTIME
886 goto underlying_strftime;
887 # else
888 /* Fall through. */
889 # endif
890 #endif
891 case L_('D'): /* POSIX.2 extension. */
892 if (modifier != 0)
893 goto bad_format;
894 subfmt = L_("%m/%d/%y");
895 goto subformat;
897 case L_('d'):
898 if (modifier == L_('E'))
899 goto bad_format;
901 DO_NUMBER (2, tp->tm_mday);
903 case L_('e'): /* POSIX.2 extension. */
904 if (modifier == L_('E'))
905 goto bad_format;
907 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
909 /* All numeric formats set DIGITS and NUMBER_VALUE and then
910 jump to one of these two labels. */
912 do_number_spacepad:
913 /* Force `_' flag unless overwritten by `0' flag. */
914 if (pad != L_('0'))
915 pad = L_('_');
917 do_number:
918 /* Format the number according to the MODIFIER flag. */
920 if (modifier == L_('O') && 0 <= number_value)
922 #ifdef _NL_CURRENT
923 /* Get the locale specific alternate representation of
924 the number NUMBER_VALUE. If none exist NULL is returned. */
925 # ifdef COMPILE_WIDE
926 const wchar_t *cp = _nl_get_walt_digit (number_value);
927 # else
928 const char *cp = _nl_get_alt_digit (number_value);
929 # endif
931 if (cp != NULL)
933 size_t digitlen = STRLEN (cp);
934 if (digitlen != 0)
936 cpy (digitlen, cp);
937 break;
940 #else
941 # if HAVE_STRFTIME
942 goto underlying_strftime;
943 # endif
944 #endif
947 unsigned int u = number_value;
949 bufp = buf + sizeof (buf) / sizeof (buf[0]);
950 negative_number = number_value < 0;
952 if (negative_number)
953 u = -u;
956 *--bufp = u % 10 + L_('0');
957 while ((u /= 10) != 0);
960 do_number_sign_and_padding:
961 if (negative_number)
962 *--bufp = L_('-');
964 if (pad != L_('-'))
966 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
967 - bufp);
969 if (pad == L_('_'))
971 while (0 < padding--)
972 *--bufp = L_(' ');
974 else
976 bufp += negative_number;
977 while (0 < padding--)
978 *--bufp = L_('0');
979 if (negative_number)
980 *--bufp = L_('-');
984 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
985 break;
987 case L_('F'):
988 if (modifier != 0)
989 goto bad_format;
990 subfmt = L_("%Y-%m-%d");
991 goto subformat;
993 case L_('H'):
994 if (modifier == L_('E'))
995 goto bad_format;
997 DO_NUMBER (2, tp->tm_hour);
999 case L_('I'):
1000 if (modifier == L_('E'))
1001 goto bad_format;
1003 DO_NUMBER (2, hour12);
1005 case L_('k'): /* GNU extension. */
1006 if (modifier == L_('E'))
1007 goto bad_format;
1009 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1011 case L_('l'): /* GNU extension. */
1012 if (modifier == L_('E'))
1013 goto bad_format;
1015 DO_NUMBER_SPACEPAD (2, hour12);
1017 case L_('j'):
1018 if (modifier == L_('E'))
1019 goto bad_format;
1021 DO_NUMBER (3, 1 + tp->tm_yday);
1023 case L_('M'):
1024 if (modifier == L_('E'))
1025 goto bad_format;
1027 DO_NUMBER (2, tp->tm_min);
1029 case L_('m'):
1030 if (modifier == L_('E'))
1031 goto bad_format;
1033 DO_NUMBER (2, tp->tm_mon + 1);
1035 case L_('n'): /* POSIX.2 extension. */
1036 add (1, *p = L_('\n'));
1037 break;
1039 case L_('P'):
1040 to_lowcase = 1;
1041 #if !defined _NL_CURRENT && HAVE_STRFTIME
1042 format_char = L_('p');
1043 #endif
1044 /* FALLTHROUGH */
1046 case L_('p'):
1047 if (change_case)
1049 to_uppcase = 0;
1050 to_lowcase = 1;
1052 #if defined _NL_CURRENT || !HAVE_STRFTIME
1053 cpy (ap_len, ampm);
1054 break;
1055 #else
1056 goto underlying_strftime;
1057 #endif
1059 case L_('R'): /* GNU extension. */
1060 subfmt = L_("%H:%M");
1061 goto subformat;
1063 case L_('r'): /* POSIX.2 extension. */
1064 #ifdef _NL_CURRENT
1065 if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1066 NLW(T_FMT_AMPM))) == L_('\0'))
1067 #endif
1068 subfmt = L_("%I:%M:%S %p");
1069 goto subformat;
1071 case L_('S'):
1072 if (modifier == L_('E'))
1073 goto bad_format;
1075 DO_NUMBER (2, tp->tm_sec);
1077 case L_('s'): /* GNU extension. */
1079 struct tm ltm;
1080 time_t t;
1082 ltm = *tp;
1083 t = mktime (&ltm);
1085 /* Generate string value for T using time_t arithmetic;
1086 this works even if sizeof (long) < sizeof (time_t). */
1088 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1089 negative_number = t < 0;
1093 int d = t % 10;
1094 t /= 10;
1096 if (negative_number)
1098 d = -d;
1100 /* Adjust if division truncates to minus infinity. */
1101 if (0 < -1 % 10 && d < 0)
1103 t++;
1104 d += 10;
1108 *--bufp = d + L_('0');
1110 while (t != 0);
1112 digits = 1;
1113 goto do_number_sign_and_padding;
1116 case L_('X'):
1117 if (modifier == L_('O'))
1118 goto bad_format;
1119 #ifdef _NL_CURRENT
1120 if (! (modifier == L_('E')
1121 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1122 NLW(ERA_T_FMT)))
1123 != L_('\0'))))
1124 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1125 goto subformat;
1126 #else
1127 # if HAVE_STRFTIME
1128 goto underlying_strftime;
1129 # else
1130 /* Fall through. */
1131 # endif
1132 #endif
1133 case L_('T'): /* POSIX.2 extension. */
1134 subfmt = L_("%H:%M:%S");
1135 goto subformat;
1137 case L_('t'): /* POSIX.2 extension. */
1138 add (1, *p = L_('\t'));
1139 break;
1141 case L_('u'): /* POSIX.2 extension. */
1142 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1144 case L_('U'):
1145 if (modifier == L_('E'))
1146 goto bad_format;
1148 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1150 case L_('V'):
1151 case L_('g'): /* GNU extension. */
1152 case L_('G'): /* GNU extension. */
1153 if (modifier == L_('E'))
1154 goto bad_format;
1156 int year = tp->tm_year + TM_YEAR_BASE;
1157 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1159 if (days < 0)
1161 /* This ISO week belongs to the previous year. */
1162 year--;
1163 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1164 tp->tm_wday);
1166 else
1168 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1169 tp->tm_wday);
1170 if (0 <= d)
1172 /* This ISO week belongs to the next year. */
1173 year++;
1174 days = d;
1178 switch (*f)
1180 case L_('g'):
1181 DO_NUMBER (2, (year % 100 + 100) % 100);
1183 case L_('G'):
1184 DO_NUMBER (1, year);
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);
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_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1228 case L_('y'):
1229 if (modifier == L_('E'))
1231 #if HAVE_STRUCT_ERA_ENTRY
1232 struct era_entry *era = _nl_get_era_entry (tp);
1233 if (era)
1235 int delta = tp->tm_year - era->start_date[0];
1236 DO_NUMBER (1, (era->offset
1237 + delta * era->absolute_direction));
1239 #else
1240 # if HAVE_STRFTIME
1241 goto underlying_strftime;
1242 # endif
1243 #endif
1245 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1247 case L_('Z'):
1248 if (change_case)
1250 to_uppcase = 0;
1251 to_lowcase = 1;
1254 #if HAVE_TZNAME
1255 /* The tzset() call might have changed the value. */
1256 if (!(zone && *zone) && tp->tm_isdst >= 0)
1257 zone = tzname[tp->tm_isdst];
1258 #endif
1259 if (! zone)
1260 zone = ""; /* POSIX.2 requires the empty string here. */
1262 #ifdef COMPILE_WIDE
1264 /* The zone string is always given in multibyte form. We have
1265 to transform it first. */
1266 wchar_t *wczone;
1267 size_t len;
1268 widen (zone, wczone, len);
1269 cpy (len, wczone);
1271 #else
1272 cpy (strlen (zone), zone);
1273 #endif
1274 break;
1276 case L_('z'): /* GNU extension. */
1277 if (tp->tm_isdst < 0)
1278 break;
1281 int diff;
1282 #if HAVE_TM_GMTOFF
1283 diff = tp->tm_gmtoff;
1284 #else
1285 if (ut)
1286 diff = 0;
1287 else
1289 struct tm gtm;
1290 struct tm ltm;
1291 time_t lt;
1293 ltm = *tp;
1294 lt = mktime (&ltm);
1296 if (lt == (time_t) -1)
1298 /* mktime returns -1 for errors, but -1 is also a
1299 valid time_t value. Check whether an error really
1300 occurred. */
1301 struct tm tm;
1303 if (! my_strftime_localtime_r (&lt, &tm)
1304 || ((ltm.tm_sec ^ tm.tm_sec)
1305 | (ltm.tm_min ^ tm.tm_min)
1306 | (ltm.tm_hour ^ tm.tm_hour)
1307 | (ltm.tm_mday ^ tm.tm_mday)
1308 | (ltm.tm_mon ^ tm.tm_mon)
1309 | (ltm.tm_year ^ tm.tm_year)))
1310 break;
1313 if (! my_strftime_gmtime_r (&lt, &gtm))
1314 break;
1316 diff = tm_diff (&ltm, &gtm);
1318 #endif
1320 if (diff < 0)
1322 add (1, *p = L_('-'));
1323 diff = -diff;
1325 else
1326 add (1, *p = L_('+'));
1328 diff /= 60;
1329 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1332 case L_('\0'): /* GNU extension: % at end of format. */
1333 --f;
1334 /* Fall through. */
1335 default:
1336 /* Unknown format; output the format, including the '%',
1337 since this is most likely the right thing to do if a
1338 multibyte string has been misparsed. */
1339 bad_format:
1341 int flen;
1342 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1343 continue;
1344 cpy (flen, &f[1 - flen]);
1346 break;
1350 if (p && maxsize != 0)
1351 *p = L_('\0');
1352 return i;
1356 #ifdef emacs
1357 /* For Emacs we have a separate interface which corresponds to the normal
1358 strftime function and does not have the extra information whether the
1359 TP arguments comes from a `gmtime' call or not. */
1360 size_t
1361 emacs_strftime (s, maxsize, format, tp)
1362 char *s;
1363 size_t maxsize;
1364 const char *format;
1365 const struct tm *tp;
1367 return my_strftime (s, maxsize, format, tp, 0);
1369 #endif