Update.
[glibc.git] / time / strftime.c
blob7771880e75cc65e4d628742c525dc2b06253e642
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 #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_('\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 size_t len = wcslen (era->era_wname);
838 cpy (len, era->era_wname);
839 # else
840 size_t len = strlen (era->era_name);
841 cpy (len, era->era_name);
842 # endif
843 break;
845 #else
846 # if HAVE_STRFTIME
847 goto underlying_strftime;
848 # endif
849 #endif
853 int year = tp->tm_year + TM_YEAR_BASE;
854 DO_NUMBER (1, year / 100 - (year % 100 < 0));
857 case L_('x'):
858 if (modifier == L_('O'))
859 goto bad_format;
860 #ifdef _NL_CURRENT
861 if (! (modifier == L_('E')
862 && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
863 NLW(ERA_D_FMT)))
864 != L_('\0'))))
865 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
866 goto subformat;
867 #else
868 # if HAVE_STRFTIME
869 goto underlying_strftime;
870 # else
871 /* Fall through. */
872 # endif
873 #endif
874 case L_('D'): /* POSIX.2 extension. */
875 if (modifier != 0)
876 goto bad_format;
877 subfmt = L_("%m/%d/%y");
878 goto subformat;
880 case L_('d'):
881 if (modifier == L_('E'))
882 goto bad_format;
884 DO_NUMBER (2, tp->tm_mday);
886 case L_('e'): /* POSIX.2 extension. */
887 if (modifier == L_('E'))
888 goto bad_format;
890 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
892 /* All numeric formats set DIGITS and NUMBER_VALUE and then
893 jump to one of these two labels. */
895 do_number_spacepad:
896 /* Force `_' flag unless overwritten by `0' flag. */
897 if (pad != L_('0'))
898 pad = L_('_');
900 do_number:
901 /* Format the number according to the MODIFIER flag. */
903 if (modifier == L_('O') && 0 <= number_value)
905 #ifdef _NL_CURRENT
906 /* Get the locale specific alternate representation of
907 the number NUMBER_VALUE. If none exist NULL is returned. */
908 # ifdef COMPILE_WIDE
909 const wchar_t *cp = _nl_get_walt_digit (number_value);
910 # else
911 const char *cp = _nl_get_alt_digit (number_value);
912 # endif
914 if (cp != NULL)
916 size_t digitlen = STRLEN (cp);
917 if (digitlen != 0)
919 cpy (digitlen, cp);
920 break;
923 #else
924 # if HAVE_STRFTIME
925 goto underlying_strftime;
926 # endif
927 #endif
930 unsigned int u = number_value;
932 bufp = buf + sizeof (buf) / sizeof (buf[0]);
933 negative_number = number_value < 0;
935 if (negative_number)
936 u = -u;
939 *--bufp = u % 10 + L_('0');
940 while ((u /= 10) != 0);
943 do_number_sign_and_padding:
944 if (negative_number)
945 *--bufp = L_('-');
947 if (pad != L_('-'))
949 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
950 - bufp);
952 if (pad == L_('_'))
954 while (0 < padding--)
955 *--bufp = L_(' ');
957 else
959 bufp += negative_number;
960 while (0 < padding--)
961 *--bufp = L_('0');
962 if (negative_number)
963 *--bufp = L_('-');
967 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
968 break;
970 case L_('F'):
971 if (modifier != 0)
972 goto bad_format;
973 subfmt = L_("%Y-%m-%d");
974 goto subformat;
976 case L_('H'):
977 if (modifier == L_('E'))
978 goto bad_format;
980 DO_NUMBER (2, tp->tm_hour);
982 case L_('I'):
983 if (modifier == L_('E'))
984 goto bad_format;
986 DO_NUMBER (2, hour12);
988 case L_('k'): /* GNU extension. */
989 if (modifier == L_('E'))
990 goto bad_format;
992 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
994 case L_('l'): /* GNU extension. */
995 if (modifier == L_('E'))
996 goto bad_format;
998 DO_NUMBER_SPACEPAD (2, hour12);
1000 case L_('j'):
1001 if (modifier == L_('E'))
1002 goto bad_format;
1004 DO_NUMBER (3, 1 + tp->tm_yday);
1006 case L_('M'):
1007 if (modifier == L_('E'))
1008 goto bad_format;
1010 DO_NUMBER (2, tp->tm_min);
1012 case L_('m'):
1013 if (modifier == L_('E'))
1014 goto bad_format;
1016 DO_NUMBER (2, tp->tm_mon + 1);
1018 case L_('n'): /* POSIX.2 extension. */
1019 add (1, *p = L_('\n'));
1020 break;
1022 case L_('P'):
1023 to_lowcase = 1;
1024 #if !defined _NL_CURRENT && HAVE_STRFTIME
1025 format_char = L_('p');
1026 #endif
1027 /* FALLTHROUGH */
1029 case L_('p'):
1030 if (change_case)
1032 to_uppcase = 0;
1033 to_lowcase = 1;
1035 #if defined _NL_CURRENT || !HAVE_STRFTIME
1036 cpy (ap_len, ampm);
1037 break;
1038 #else
1039 goto underlying_strftime;
1040 #endif
1042 case L_('R'): /* GNU extension. */
1043 subfmt = L_("%H:%M");
1044 goto subformat;
1046 case L_('r'): /* POSIX.2 extension. */
1047 #ifdef _NL_CURRENT
1048 if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1049 NLW(T_FMT_AMPM))) == L_('\0'))
1050 #endif
1051 subfmt = L_("%I:%M:%S %p");
1052 goto subformat;
1054 case L_('S'):
1055 if (modifier == L_('E'))
1056 goto bad_format;
1058 DO_NUMBER (2, tp->tm_sec);
1060 case L_('s'): /* GNU extension. */
1062 struct tm ltm;
1063 time_t t;
1065 ltm = *tp;
1066 t = mktime (&ltm);
1068 /* Generate string value for T using time_t arithmetic;
1069 this works even if sizeof (long) < sizeof (time_t). */
1071 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1072 negative_number = t < 0;
1076 int d = t % 10;
1077 t /= 10;
1079 if (negative_number)
1081 d = -d;
1083 /* Adjust if division truncates to minus infinity. */
1084 if (0 < -1 % 10 && d < 0)
1086 t++;
1087 d += 10;
1091 *--bufp = 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 = (CHAR_T *) _NL_CURRENT (LC_TIME,
1105 NLW(ERA_T_FMT)))
1106 != L_('\0'))))
1107 subfmt = (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'): /* POSIX.2 extension. */
1117 subfmt = L_("%H:%M:%S");
1118 goto subformat;
1120 case L_('t'): /* POSIX.2 extension. */
1121 add (1, *p = L_('\t'));
1122 break;
1124 case L_('u'): /* POSIX.2 extension. */
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'): /* GNU extension. */
1135 case L_('G'): /* GNU extension. */
1136 if (modifier == L_('E'))
1137 goto bad_format;
1139 int year = tp->tm_year + TM_YEAR_BASE;
1140 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1142 if (days < 0)
1144 /* This ISO week belongs to the previous year. */
1145 year--;
1146 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1147 tp->tm_wday);
1149 else
1151 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1152 tp->tm_wday);
1153 if (0 <= d)
1155 /* This ISO week belongs to the next year. */
1156 year++;
1157 days = d;
1161 switch (*f)
1163 case L_('g'):
1164 DO_NUMBER (2, (year % 100 + 100) % 100);
1166 case L_('G'):
1167 DO_NUMBER (1, year);
1169 default:
1170 DO_NUMBER (2, days / 7 + 1);
1174 case L_('W'):
1175 if (modifier == L_('E'))
1176 goto bad_format;
1178 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1180 case L_('w'):
1181 if (modifier == L_('E'))
1182 goto bad_format;
1184 DO_NUMBER (1, tp->tm_wday);
1186 case L_('Y'):
1187 if (modifier == 'E')
1189 #if HAVE_STRUCT_ERA_ENTRY
1190 struct era_entry *era = _nl_get_era_entry (tp);
1191 if (era)
1193 # ifdef COMPILE_WIDE
1194 subfmt = era->era_wformat;
1195 # else
1196 subfmt = era->era_format;
1197 # endif
1198 goto subformat;
1200 #else
1201 # if HAVE_STRFTIME
1202 goto underlying_strftime;
1203 # endif
1204 #endif
1206 if (modifier == L_('O'))
1207 goto bad_format;
1208 else
1209 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1211 case L_('y'):
1212 if (modifier == L_('E'))
1214 #if HAVE_STRUCT_ERA_ENTRY
1215 struct era_entry *era = _nl_get_era_entry (tp);
1216 if (era)
1218 int delta = tp->tm_year - era->start_date[0];
1219 DO_NUMBER (1, (era->offset
1220 + delta * era->absolute_direction));
1222 #else
1223 # if HAVE_STRFTIME
1224 goto underlying_strftime;
1225 # endif
1226 #endif
1228 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1230 case L_('Z'):
1231 if (change_case)
1233 to_uppcase = 0;
1234 to_lowcase = 1;
1237 #if HAVE_TZNAME
1238 /* The tzset() call might have changed the value. */
1239 if (!(zone && *zone) && tp->tm_isdst >= 0)
1240 zone = tzname[tp->tm_isdst];
1241 #endif
1242 if (! zone)
1243 zone = ""; /* POSIX.2 requires the empty string here. */
1245 #ifdef COMPILE_WIDE
1247 /* The zone string is always given in multibyte form. We have
1248 to transform it first. */
1249 wchar_t *wczone;
1250 size_t len;
1251 widen (zone, wczone, len);
1252 cpy (len, wczone);
1254 #else
1255 cpy (strlen (zone), zone);
1256 #endif
1257 break;
1259 case L_('z'): /* GNU extension. */
1260 if (tp->tm_isdst < 0)
1261 break;
1264 int diff;
1265 #if HAVE_TM_GMTOFF
1266 diff = tp->tm_gmtoff;
1267 #else
1268 if (ut)
1269 diff = 0;
1270 else
1272 struct tm gtm;
1273 struct tm ltm;
1274 time_t lt;
1276 ltm = *tp;
1277 lt = mktime (&ltm);
1279 if (lt == (time_t) -1)
1281 /* mktime returns -1 for errors, but -1 is also a
1282 valid time_t value. Check whether an error really
1283 occurred. */
1284 struct tm tm;
1286 if (! my_strftime_localtime_r (&lt, &tm)
1287 || ((ltm.tm_sec ^ tm.tm_sec)
1288 | (ltm.tm_min ^ tm.tm_min)
1289 | (ltm.tm_hour ^ tm.tm_hour)
1290 | (ltm.tm_mday ^ tm.tm_mday)
1291 | (ltm.tm_mon ^ tm.tm_mon)
1292 | (ltm.tm_year ^ tm.tm_year)))
1293 break;
1296 if (! my_strftime_gmtime_r (&lt, &gtm))
1297 break;
1299 diff = tm_diff (&ltm, &gtm);
1301 #endif
1303 if (diff < 0)
1305 add (1, *p = L_('-'));
1306 diff = -diff;
1308 else
1309 add (1, *p = L_('+'));
1311 diff /= 60;
1312 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1315 case L_('\0'): /* GNU extension: % at end of format. */
1316 --f;
1317 /* Fall through. */
1318 default:
1319 /* Unknown format; output the format, including the '%',
1320 since this is most likely the right thing to do if a
1321 multibyte string has been misparsed. */
1322 bad_format:
1324 int flen;
1325 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1326 continue;
1327 cpy (flen, &f[1 - flen]);
1329 break;
1333 if (p && maxsize != 0)
1334 *p = L_('\0');
1335 return i;
1339 #ifdef emacs
1340 /* For Emacs we have a separate interface which corresponds to the normal
1341 strftime function and does not have the extra information whether the
1342 TP arguments comes from a `gmtime' call or not. */
1343 size_t
1344 emacs_strftime (s, maxsize, format, tp)
1345 char *s;
1346 size_t maxsize;
1347 const char *format;
1348 const struct tm *tp;
1350 return my_strftime (s, maxsize, format, tp, 0);
1352 #endif