(elf_get_dynamic_info): Also relocate DT_HASH entry if necessary.
[glibc.git] / time / strftime.c
blobe5eabf9d1c4ab71d4e0208757603c56fd5f5375d
1 /* Copyright (C) 1991-1999, 2000, 2001, 2002 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 Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 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 LOCALE_ARG); \
287 else if (to_uppcase) \
288 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
289 else \
290 MEMCPY ((PTR) p, (const PTR) (s), _n))
292 #ifdef COMPILE_WIDE
293 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
294 # define widen(os, ws, l) \
296 mbstate_t __st; \
297 const char *__s = os; \
298 memset (&__st, '\0', sizeof (__st)); \
299 l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
300 ws = alloca ((l + 1) * sizeof (wchar_t)); \
301 (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
303 # else
304 # define widen(os, ws, l) \
306 mbstate_t __st; \
307 const char *__s = os; \
308 memset (&__st, '\0', sizeof (__st)); \
309 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
310 ws = alloca ((l + 1) * sizeof (wchar_t)); \
311 (void) __mbsrtowcs (ws, &__s, l, &__st); \
313 # endif
314 #endif
317 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
318 /* We use this code also for the extended locale handling where the
319 function gets as an additional argument the locale which has to be
320 used. To access the values we have to redefine the _NL_CURRENT
321 macro. */
322 # define strftime __strftime_l
323 # define wcsftime __wcsftime_l
324 # undef _NL_CURRENT
325 # define _NL_CURRENT(category, item) \
326 (current->values[_NL_ITEM_INDEX (item)].string)
327 # define LOCALE_PARAM , loc
328 # define LOCALE_ARG , loc
329 # define LOCALE_PARAM_DECL __locale_t loc;
330 # define LOCALE_PARAM_PROTO , __locale_t loc
331 # define HELPER_LOCALE_ARG , current
332 #else
333 # define LOCALE_PARAM
334 # define LOCALE_PARAM_PROTO
335 # define LOCALE_ARG
336 # define LOCALE_PARAM_DECL
337 # ifdef _LIBC
338 # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
339 # else
340 # define HELPER_LOCALE_ARG
341 # endif
342 #endif
344 #ifdef COMPILE_WIDE
345 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
346 # define TOUPPER(Ch, L) __towupper_l (Ch, L)
347 # define TOLOWER(Ch, L) __towlower_l (Ch, L)
348 # else
349 # define TOUPPER(Ch, L) towupper (Ch)
350 # define TOLOWER(Ch, L) towlower (Ch)
351 # endif
352 #else
353 # ifdef _LIBC
354 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
355 # define TOUPPER(Ch, L) __toupper_l (Ch, L)
356 # define TOLOWER(Ch, L) __tolower_l (Ch, L)
357 # else
358 # define TOUPPER(Ch, L) toupper (Ch)
359 # define TOLOWER(Ch, L) tolower (Ch)
360 # endif
361 # else
362 # define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
363 # define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
364 # endif
365 #endif
366 /* We don't use `isdigit' here since the locale dependent
367 interpretation is not what we want here. We only need to accept
368 the arabic digits in the ASCII range. One day there is perhaps a
369 more reliable way to accept other sets of digits. */
370 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
372 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
373 size_t len LOCALE_PARAM_PROTO));
375 static CHAR_T *
376 memcpy_lowcase (dest, src, len LOCALE_PARAM)
377 CHAR_T *dest;
378 const CHAR_T *src;
379 size_t len;
380 LOCALE_PARAM_DECL
382 while (len-- > 0)
383 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
384 return dest;
387 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
388 size_t len LOCALE_PARAM_PROTO));
390 static CHAR_T *
391 memcpy_uppcase (dest, src, len LOCALE_PARAM)
392 CHAR_T *dest;
393 const CHAR_T *src;
394 size_t len;
395 LOCALE_PARAM_DECL
397 while (len-- > 0)
398 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
399 return dest;
403 #if ! HAVE_TM_GMTOFF
404 /* Yield the difference between *A and *B,
405 measured in seconds, ignoring leap seconds. */
406 # define tm_diff ftime_tm_diff
407 static int tm_diff __P ((const struct tm *, const struct tm *));
408 static int
409 tm_diff (a, b)
410 const struct tm *a;
411 const struct tm *b;
413 /* Compute intervening leap days correctly even if year is negative.
414 Take care to avoid int overflow in leap day calculations,
415 but it's OK to assume that A and B are close to each other. */
416 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
417 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
418 int a100 = a4 / 25 - (a4 % 25 < 0);
419 int b100 = b4 / 25 - (b4 % 25 < 0);
420 int a400 = a100 >> 2;
421 int b400 = b100 >> 2;
422 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
423 int years = a->tm_year - b->tm_year;
424 int days = (365 * years + intervening_leap_days
425 + (a->tm_yday - b->tm_yday));
426 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
427 + (a->tm_min - b->tm_min))
428 + (a->tm_sec - b->tm_sec));
430 #endif /* ! HAVE_TM_GMTOFF */
434 /* The number of days from the first day of the first ISO week of this
435 year to the year day YDAY with week day WDAY. ISO weeks start on
436 Monday; the first ISO week has the year's first Thursday. YDAY may
437 be as small as YDAY_MINIMUM. */
438 #define ISO_WEEK_START_WDAY 1 /* Monday */
439 #define ISO_WEEK1_WDAY 4 /* Thursday */
440 #define YDAY_MINIMUM (-366)
441 static int iso_week_days __P ((int, int));
442 #ifdef __GNUC__
443 __inline__
444 #endif
445 static int
446 iso_week_days (yday, wday)
447 int yday;
448 int wday;
450 /* Add enough to the first operand of % to make it nonnegative. */
451 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
452 return (yday
453 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
454 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
458 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
459 static CHAR_T const weekday_name[][10] =
461 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
462 L_("Thursday"), L_("Friday"), L_("Saturday")
464 static CHAR_T const month_name[][10] =
466 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
467 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
468 L_("November"), L_("December")
470 #endif
473 #ifdef emacs
474 # define my_strftime emacs_strftimeu
475 # define ut_argument , ut
476 # define ut_argument_spec int ut;
477 # define ut_argument_spec_iso , int ut
478 #else
479 # ifdef COMPILE_WIDE
480 # define my_strftime wcsftime
481 # else
482 # define my_strftime strftime
483 # endif
484 # define ut_argument
485 # define ut_argument_spec
486 # define ut_argument_spec_iso
487 /* We don't have this information in general. */
488 # define ut 0
489 #endif
491 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
492 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
493 Work around this bug by copying *tp before it might be munged. */
494 size_t _strftime_copytm __P ((char *, size_t, const char *,
495 const struct tm * ut_argument_spec_iso));
496 size_t
497 my_strftime (s, maxsize, format, tp ut_argument)
498 CHAR_T *s;
499 size_t maxsize;
500 const CHAR_T *format;
501 const struct tm *tp;
502 ut_argument_spec
504 struct tm tmcopy;
505 tmcopy = *tp;
506 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
508 # undef my_strftime
509 # define my_strftime _strftime_copytm
510 #endif
513 /* Write information from TP into S according to the format
514 string FORMAT, writing no more that MAXSIZE characters
515 (including the terminating '\0') and returning number of
516 characters written. If S is NULL, nothing will be written
517 anywhere, so to determine how many characters would be
518 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
519 size_t
520 my_strftime (s, maxsize, format, tp ut_argument LOCALE_PARAM)
521 CHAR_T *s;
522 size_t maxsize;
523 const CHAR_T *format;
524 const struct tm *tp;
525 ut_argument_spec
526 LOCALE_PARAM_DECL
528 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
529 struct locale_data *const current = loc->__locales[LC_TIME];
530 #endif
532 int hour12 = tp->tm_hour;
533 #ifdef _NL_CURRENT
534 /* We cannot make the following values variables since we must delay
535 the evaluation of these values until really needed since some
536 expressions might not be valid in every situation. The `struct tm'
537 might be generated by a strptime() call that initialized
538 only a few elements. Dereference the pointers only if the format
539 requires this. Then it is ok to fail if the pointers are invalid. */
540 # define a_wkday \
541 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
542 # define f_wkday \
543 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
544 # define a_month \
545 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
546 # define f_month \
547 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
548 # define ampm \
549 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
550 ? NLW(PM_STR) : NLW(AM_STR)))
552 # define aw_len STRLEN (a_wkday)
553 # define am_len STRLEN (a_month)
554 # define ap_len STRLEN (ampm)
555 #else
556 # if !HAVE_STRFTIME
557 # define f_wkday (weekday_name[tp->tm_wday])
558 # define f_month (month_name[tp->tm_mon])
559 # define a_wkday f_wkday
560 # define a_month f_month
561 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
563 size_t aw_len = 3;
564 size_t am_len = 3;
565 size_t ap_len = 2;
566 # endif
567 #endif
568 const char *zone;
569 size_t i = 0;
570 CHAR_T *p = s;
571 const CHAR_T *f;
572 #if DO_MULTIBYTE && !defined COMPILE_WIDE
573 const char *format_end = NULL;
574 #endif
576 zone = NULL;
577 #if HAVE_TM_ZONE
578 /* The POSIX test suite assumes that setting
579 the environment variable TZ to a new value before calling strftime()
580 will influence the result (the %Z format) even if the information in
581 TP is computed with a totally different time zone.
582 This is bogus: though POSIX allows bad behavior like this,
583 POSIX does not require it. Do the right thing instead. */
584 zone = (const char *) tp->tm_zone;
585 #endif
586 #if HAVE_TZNAME
587 if (ut)
589 if (! (zone && *zone))
590 zone = "GMT";
592 else
594 /* POSIX.1 requires that local time zone information is used as
595 though strftime called tzset. */
596 # if HAVE_TZSET
597 tzset ();
598 # endif
600 #endif
602 if (hour12 > 12)
603 hour12 -= 12;
604 else
605 if (hour12 == 0)
606 hour12 = 12;
608 for (f = format; *f != '\0'; ++f)
610 int pad = 0; /* Padding for number ('-', '_', or 0). */
611 int modifier; /* Field modifier ('E', 'O', or 0). */
612 int digits; /* Max digits for numeric format. */
613 int number_value; /* Numeric value to be printed. */
614 int negative_number; /* 1 if the number is negative. */
615 const CHAR_T *subfmt;
616 CHAR_T *bufp;
617 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
618 ? INT_STRLEN_BOUND (time_t)
619 : INT_STRLEN_BOUND (int))];
620 int width = -1;
621 int to_lowcase = 0;
622 int to_uppcase = 0;
623 int change_case = 0;
624 int format_char;
626 #if DO_MULTIBYTE && !defined COMPILE_WIDE
627 switch (*f)
629 case L_('%'):
630 break;
632 case L_('\b'): case L_('\t'): case L_('\n'):
633 case L_('\v'): case L_('\f'): case L_('\r'):
634 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
635 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
636 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
637 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
638 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
639 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
640 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
641 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
642 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
643 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
644 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
645 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
646 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
647 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
648 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
649 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
650 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
651 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
652 case L_('~'):
653 /* The C Standard requires these 98 characters (plus '%') to
654 be in the basic execution character set. None of these
655 characters can start a multibyte sequence, so they need
656 not be analyzed further. */
657 add (1, *p = *f);
658 continue;
660 default:
661 /* Copy this multibyte sequence until we reach its end, find
662 an error, or come back to the initial shift state. */
664 mbstate_t mbstate = mbstate_zero;
665 size_t len = 0;
666 size_t fsize;
668 if (! format_end)
669 format_end = f + strlen (f) + 1;
670 fsize = format_end - f;
674 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
676 if (bytes == 0)
677 break;
679 if (bytes == (size_t) -2)
681 len += strlen (f + len);
682 break;
685 if (bytes == (size_t) -1)
687 len++;
688 break;
691 len += bytes;
693 while (! mbsinit (&mbstate));
695 cpy (len, f);
696 f += len - 1;
697 continue;
701 #else /* ! DO_MULTIBYTE */
703 /* Either multibyte encodings are not supported, they are
704 safe for formats, so any non-'%' byte can be copied through,
705 or this is the wide character version. */
706 if (*f != L_('%'))
708 add (1, *p = *f);
709 continue;
712 #endif /* ! DO_MULTIBYTE */
714 /* Check for flags that can modify a format. */
715 while (1)
717 switch (*++f)
719 /* This influences the number formats. */
720 case L_('_'):
721 case L_('-'):
722 case L_('0'):
723 pad = *f;
724 continue;
726 /* This changes textual output. */
727 case L_('^'):
728 to_uppcase = 1;
729 continue;
730 case L_('#'):
731 change_case = 1;
732 continue;
734 default:
735 break;
737 break;
740 /* As a GNU extension we allow to specify the field width. */
741 if (ISDIGIT (*f))
743 width = 0;
746 width *= 10;
747 width += *f - L_('0');
748 ++f;
750 while (ISDIGIT (*f));
753 /* Check for modifiers. */
754 switch (*f)
756 case L_('E'):
757 case L_('O'):
758 modifier = *f++;
759 break;
761 default:
762 modifier = 0;
763 break;
766 /* Now do the specified format. */
767 format_char = *f;
768 switch (format_char)
770 #define DO_NUMBER(d, v) \
771 digits = width == -1 ? d : width; \
772 number_value = v; goto do_number
773 #define DO_NUMBER_SPACEPAD(d, v) \
774 digits = width == -1 ? d : width; \
775 number_value = v; goto do_number_spacepad
777 case L_('%'):
778 if (modifier != 0)
779 goto bad_format;
780 add (1, *p = *f);
781 break;
783 case L_('a'):
784 if (modifier != 0)
785 goto bad_format;
786 if (change_case)
788 to_uppcase = 1;
789 to_lowcase = 0;
791 #if defined _NL_CURRENT || !HAVE_STRFTIME
792 cpy (aw_len, a_wkday);
793 break;
794 #else
795 goto underlying_strftime;
796 #endif
798 case 'A':
799 if (modifier != 0)
800 goto bad_format;
801 if (change_case)
803 to_uppcase = 1;
804 to_lowcase = 0;
806 #if defined _NL_CURRENT || !HAVE_STRFTIME
807 cpy (STRLEN (f_wkday), f_wkday);
808 break;
809 #else
810 goto underlying_strftime;
811 #endif
813 case L_('b'):
814 case L_('h'):
815 if (change_case)
817 to_uppcase = 1;
818 to_lowcase = 0;
820 if (modifier != 0)
821 goto bad_format;
822 #if defined _NL_CURRENT || !HAVE_STRFTIME
823 cpy (am_len, a_month);
824 break;
825 #else
826 goto underlying_strftime;
827 #endif
829 case L_('B'):
830 if (modifier != 0)
831 goto bad_format;
832 if (change_case)
834 to_uppcase = 1;
835 to_lowcase = 0;
837 #if defined _NL_CURRENT || !HAVE_STRFTIME
838 cpy (STRLEN (f_month), f_month);
839 break;
840 #else
841 goto underlying_strftime;
842 #endif
844 case L_('c'):
845 if (modifier == L_('O'))
846 goto bad_format;
847 #ifdef _NL_CURRENT
848 if (! (modifier == 'E'
849 && (*(subfmt =
850 (const CHAR_T *) _NL_CURRENT (LC_TIME,
851 NLW(ERA_D_T_FMT)))
852 != '\0')))
853 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
854 #else
855 # if HAVE_STRFTIME
856 goto underlying_strftime;
857 # else
858 subfmt = L_("%a %b %e %H:%M:%S %Y");
859 # endif
860 #endif
862 subformat:
864 CHAR_T *old_start = p;
865 size_t len = my_strftime (NULL, (size_t) -1, subfmt,
866 tp ut_argument LOCALE_ARG);
867 add (len, my_strftime (p, maxsize - i, subfmt,
868 tp ut_argument LOCALE_ARG));
870 if (to_uppcase)
871 while (old_start < p)
873 *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
874 ++old_start;
877 break;
879 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
880 underlying_strftime:
882 /* The relevant information is available only via the
883 underlying strftime implementation, so use that. */
884 char ufmt[4];
885 char *u = ufmt;
886 char ubuf[1024]; /* enough for any single format in practice */
887 size_t len;
888 /* Make sure we're calling the actual underlying strftime.
889 In some cases, config.h contains something like
890 "#define strftime rpl_strftime". */
891 # ifdef strftime
892 # undef strftime
893 size_t strftime ();
894 # endif
896 *u++ = '%';
897 if (modifier != 0)
898 *u++ = modifier;
899 *u++ = format_char;
900 *u = '\0';
901 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
902 if (len == 0 && ubuf[0] != '\0')
903 return 0;
904 cpy (len, ubuf);
906 break;
907 #endif
909 case L_('C'):
910 if (modifier == L_('O'))
911 goto bad_format;
912 if (modifier == L_('E'))
914 #if HAVE_STRUCT_ERA_ENTRY
915 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
916 if (era)
918 # ifdef COMPILE_WIDE
919 size_t len = __wcslen (era->era_wname);
920 cpy (len, era->era_wname);
921 # else
922 size_t len = strlen (era->era_name);
923 cpy (len, era->era_name);
924 # endif
925 break;
927 #else
928 # if HAVE_STRFTIME
929 goto underlying_strftime;
930 # endif
931 #endif
935 int year = tp->tm_year + TM_YEAR_BASE;
936 DO_NUMBER (1, year / 100 - (year % 100 < 0));
939 case L_('x'):
940 if (modifier == L_('O'))
941 goto bad_format;
942 #ifdef _NL_CURRENT
943 if (! (modifier == L_('E')
944 && (*(subfmt =
945 (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
946 != L_('\0'))))
947 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
948 goto subformat;
949 #else
950 # if HAVE_STRFTIME
951 goto underlying_strftime;
952 # else
953 /* Fall through. */
954 # endif
955 #endif
956 case L_('D'):
957 if (modifier != 0)
958 goto bad_format;
959 subfmt = L_("%m/%d/%y");
960 goto subformat;
962 case L_('d'):
963 if (modifier == L_('E'))
964 goto bad_format;
966 DO_NUMBER (2, tp->tm_mday);
968 case L_('e'):
969 if (modifier == L_('E'))
970 goto bad_format;
972 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
974 /* All numeric formats set DIGITS and NUMBER_VALUE and then
975 jump to one of these two labels. */
977 do_number_spacepad:
978 /* Force `_' flag unless overwritten by `0' flag. */
979 if (pad != L_('0'))
980 pad = L_('_');
982 do_number:
983 /* Format the number according to the MODIFIER flag. */
985 if (modifier == L_('O') && 0 <= number_value)
987 #ifdef _NL_CURRENT
988 /* Get the locale specific alternate representation of
989 the number NUMBER_VALUE. If none exist NULL is returned. */
990 # ifdef COMPILE_WIDE
991 const wchar_t *cp = _nl_get_walt_digit (number_value
992 HELPER_LOCALE_ARG);
993 # else
994 const char *cp = _nl_get_alt_digit (number_value
995 HELPER_LOCALE_ARG);
996 # endif
998 if (cp != NULL)
1000 size_t digitlen = STRLEN (cp);
1001 if (digitlen != 0)
1003 cpy (digitlen, cp);
1004 break;
1007 #else
1008 # if HAVE_STRFTIME
1009 goto underlying_strftime;
1010 # endif
1011 #endif
1014 unsigned int u = number_value;
1016 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1017 negative_number = number_value < 0;
1019 if (negative_number)
1020 u = -u;
1023 *--bufp = u % 10 + L_('0');
1024 while ((u /= 10) != 0);
1027 do_number_sign_and_padding:
1028 if (negative_number)
1029 *--bufp = L_('-');
1031 if (pad != L_('-'))
1033 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
1034 - bufp);
1036 if (pad == L_('_'))
1038 while (0 < padding--)
1039 *--bufp = L_(' ');
1041 else
1043 bufp += negative_number;
1044 while (0 < padding--)
1045 *--bufp = L_('0');
1046 if (negative_number)
1047 *--bufp = L_('-');
1051 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1052 break;
1054 case L_('F'):
1055 if (modifier != 0)
1056 goto bad_format;
1057 subfmt = L_("%Y-%m-%d");
1058 goto subformat;
1060 case L_('H'):
1061 if (modifier == L_('E'))
1062 goto bad_format;
1064 DO_NUMBER (2, tp->tm_hour);
1066 case L_('I'):
1067 if (modifier == L_('E'))
1068 goto bad_format;
1070 DO_NUMBER (2, hour12);
1072 case L_('k'): /* GNU extension. */
1073 if (modifier == L_('E'))
1074 goto bad_format;
1076 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1078 case L_('l'): /* GNU extension. */
1079 if (modifier == L_('E'))
1080 goto bad_format;
1082 DO_NUMBER_SPACEPAD (2, hour12);
1084 case L_('j'):
1085 if (modifier == L_('E'))
1086 goto bad_format;
1088 DO_NUMBER (3, 1 + tp->tm_yday);
1090 case L_('M'):
1091 if (modifier == L_('E'))
1092 goto bad_format;
1094 DO_NUMBER (2, tp->tm_min);
1096 case L_('m'):
1097 if (modifier == L_('E'))
1098 goto bad_format;
1100 DO_NUMBER (2, tp->tm_mon + 1);
1102 case L_('n'):
1103 add (1, *p = L_('\n'));
1104 break;
1106 case L_('P'):
1107 to_lowcase = 1;
1108 #if !defined _NL_CURRENT && HAVE_STRFTIME
1109 format_char = L_('p');
1110 #endif
1111 /* FALLTHROUGH */
1113 case L_('p'):
1114 if (change_case)
1116 to_uppcase = 0;
1117 to_lowcase = 1;
1119 #if defined _NL_CURRENT || !HAVE_STRFTIME
1120 cpy (ap_len, ampm);
1121 break;
1122 #else
1123 goto underlying_strftime;
1124 #endif
1126 case L_('R'):
1127 subfmt = L_("%H:%M");
1128 goto subformat;
1130 case L_('r'):
1131 #ifdef _NL_CURRENT
1132 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1133 NLW(T_FMT_AMPM)))
1134 == L_('\0'))
1135 #endif
1136 subfmt = L_("%I:%M:%S %p");
1137 goto subformat;
1139 case L_('S'):
1140 if (modifier == L_('E'))
1141 goto bad_format;
1143 DO_NUMBER (2, tp->tm_sec);
1145 case L_('s'): /* GNU extension. */
1147 struct tm ltm;
1148 time_t t;
1150 ltm = *tp;
1151 t = mktime (&ltm);
1153 /* Generate string value for T using time_t arithmetic;
1154 this works even if sizeof (long) < sizeof (time_t). */
1156 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1157 negative_number = t < 0;
1161 int d = t % 10;
1162 t /= 10;
1164 if (negative_number)
1166 d = -d;
1168 /* Adjust if division truncates to minus infinity. */
1169 if (0 < -1 % 10 && d < 0)
1171 t++;
1172 d += 10;
1176 *--bufp = d + L_('0');
1178 while (t != 0);
1180 digits = 1;
1181 goto do_number_sign_and_padding;
1184 case L_('X'):
1185 if (modifier == L_('O'))
1186 goto bad_format;
1187 #ifdef _NL_CURRENT
1188 if (! (modifier == L_('E')
1189 && (*(subfmt =
1190 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1191 != L_('\0'))))
1192 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1193 goto subformat;
1194 #else
1195 # if HAVE_STRFTIME
1196 goto underlying_strftime;
1197 # else
1198 /* Fall through. */
1199 # endif
1200 #endif
1201 case L_('T'):
1202 subfmt = L_("%H:%M:%S");
1203 goto subformat;
1205 case L_('t'):
1206 add (1, *p = L_('\t'));
1207 break;
1209 case L_('u'):
1210 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1212 case L_('U'):
1213 if (modifier == L_('E'))
1214 goto bad_format;
1216 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1218 case L_('V'):
1219 case L_('g'):
1220 case L_('G'):
1221 if (modifier == L_('E'))
1222 goto bad_format;
1224 int year = tp->tm_year + TM_YEAR_BASE;
1225 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1227 if (days < 0)
1229 /* This ISO week belongs to the previous year. */
1230 year--;
1231 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1232 tp->tm_wday);
1234 else
1236 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1237 tp->tm_wday);
1238 if (0 <= d)
1240 /* This ISO week belongs to the next year. */
1241 year++;
1242 days = d;
1246 switch (*f)
1248 case L_('g'):
1249 DO_NUMBER (2, (year % 100 + 100) % 100);
1251 case L_('G'):
1252 DO_NUMBER (1, year);
1254 default:
1255 DO_NUMBER (2, days / 7 + 1);
1259 case L_('W'):
1260 if (modifier == L_('E'))
1261 goto bad_format;
1263 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1265 case L_('w'):
1266 if (modifier == L_('E'))
1267 goto bad_format;
1269 DO_NUMBER (1, tp->tm_wday);
1271 case L_('Y'):
1272 if (modifier == 'E')
1274 #if HAVE_STRUCT_ERA_ENTRY
1275 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1276 if (era)
1278 # ifdef COMPILE_WIDE
1279 subfmt = era->era_wformat;
1280 # else
1281 subfmt = era->era_format;
1282 # endif
1283 goto subformat;
1285 #else
1286 # if HAVE_STRFTIME
1287 goto underlying_strftime;
1288 # endif
1289 #endif
1291 if (modifier == L_('O'))
1292 goto bad_format;
1293 else
1294 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1296 case L_('y'):
1297 if (modifier == L_('E'))
1299 #if HAVE_STRUCT_ERA_ENTRY
1300 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1301 if (era)
1303 int delta = tp->tm_year - era->start_date[0];
1304 DO_NUMBER (1, (era->offset
1305 + delta * era->absolute_direction));
1307 #else
1308 # if HAVE_STRFTIME
1309 goto underlying_strftime;
1310 # endif
1311 #endif
1313 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1315 case L_('Z'):
1316 if (change_case)
1318 to_uppcase = 0;
1319 to_lowcase = 1;
1322 #if HAVE_TZNAME
1323 /* The tzset() call might have changed the value. */
1324 if (!(zone && *zone) && tp->tm_isdst >= 0)
1325 zone = tzname[tp->tm_isdst];
1326 #endif
1327 if (! zone)
1328 zone = "";
1330 #ifdef COMPILE_WIDE
1332 /* The zone string is always given in multibyte form. We have
1333 to transform it first. */
1334 wchar_t *wczone;
1335 size_t len;
1336 widen (zone, wczone, len);
1337 cpy (len, wczone);
1339 #else
1340 cpy (strlen (zone), zone);
1341 #endif
1342 break;
1344 case L_('z'):
1345 if (tp->tm_isdst < 0)
1346 break;
1349 int diff;
1350 #if HAVE_TM_GMTOFF
1351 diff = tp->tm_gmtoff;
1352 #else
1353 if (ut)
1354 diff = 0;
1355 else
1357 struct tm gtm;
1358 struct tm ltm;
1359 time_t lt;
1361 ltm = *tp;
1362 lt = mktime (&ltm);
1364 if (lt == (time_t) -1)
1366 /* mktime returns -1 for errors, but -1 is also a
1367 valid time_t value. Check whether an error really
1368 occurred. */
1369 struct tm tm;
1371 if (! my_strftime_localtime_r (&lt, &tm)
1372 || ((ltm.tm_sec ^ tm.tm_sec)
1373 | (ltm.tm_min ^ tm.tm_min)
1374 | (ltm.tm_hour ^ tm.tm_hour)
1375 | (ltm.tm_mday ^ tm.tm_mday)
1376 | (ltm.tm_mon ^ tm.tm_mon)
1377 | (ltm.tm_year ^ tm.tm_year)))
1378 break;
1381 if (! my_strftime_gmtime_r (&lt, &gtm))
1382 break;
1384 diff = tm_diff (&ltm, &gtm);
1386 #endif
1388 if (diff < 0)
1390 add (1, *p = L_('-'));
1391 diff = -diff;
1393 else
1394 add (1, *p = L_('+'));
1396 diff /= 60;
1397 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1400 case L_('\0'): /* GNU extension: % at end of format. */
1401 --f;
1402 /* Fall through. */
1403 default:
1404 /* Unknown format; output the format, including the '%',
1405 since this is most likely the right thing to do if a
1406 multibyte string has been misparsed. */
1407 bad_format:
1409 int flen;
1410 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1411 continue;
1412 cpy (flen, &f[1 - flen]);
1414 break;
1418 if (p && maxsize != 0)
1419 *p = L_('\0');
1420 return i;
1422 #if defined _LIBC && !defined USE_IN_EXTENDED_LOCALE_MODEL
1423 libc_hidden_def (my_strftime)
1424 #endif
1427 #ifdef emacs
1428 /* For Emacs we have a separate interface which corresponds to the normal
1429 strftime function and does not have the extra information whether the
1430 TP arguments comes from a `gmtime' call or not. */
1431 size_t
1432 emacs_strftime (s, maxsize, format, tp)
1433 char *s;
1434 size_t maxsize;
1435 const char *format;
1436 const struct tm *tp;
1438 return my_strftime (s, maxsize, format, tp, 0);
1440 #endif