[BZ #375]
[glibc.git] / time / strftime_l.c
blob6cae85d32fe486be13d865f9e264b0b671e7967c
1 /* Copyright (C) 2002, 2004 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 USE_IN_EXTENDED_LOCALE_MODEL 1
25 # define HAVE_LIMITS_H 1
26 # define HAVE_MBLEN 1
27 # define HAVE_MBRLEN 1
28 # define HAVE_STRUCT_ERA_ENTRY 1
29 # define HAVE_TM_GMTOFF 1
30 # define HAVE_TM_ZONE 1
31 # define HAVE_TZNAME 1
32 # define HAVE_TZSET 1
33 # define MULTIBYTE_IS_FORMAT_SAFE 1
34 # define STDC_HEADERS 1
35 # include "../locale/localeinfo.h"
36 #endif
38 #if defined emacs && !defined HAVE_BCOPY
39 # define HAVE_MEMCPY 1
40 #endif
42 #include <ctype.h>
43 #include <sys/types.h> /* Some systems define `time_t' here. */
45 #ifdef TIME_WITH_SYS_TIME
46 # include <sys/time.h>
47 # include <time.h>
48 #else
49 # ifdef HAVE_SYS_TIME_H
50 # include <sys/time.h>
51 # else
52 # include <time.h>
53 # endif
54 #endif
55 #if HAVE_TZNAME
56 extern char *tzname[];
57 #endif
59 /* Do multibyte processing if multibytes are supported, unless
60 multibyte sequences are safe in formats. Multibyte sequences are
61 safe if they cannot contain byte sequences that look like format
62 conversion specifications. The GNU C Library uses UTF8 multibyte
63 encoding, which is safe for formats, but strftime.c can be used
64 with other C libraries that use unsafe encodings. */
65 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
67 #if DO_MULTIBYTE
68 # if HAVE_MBRLEN
69 # include <wchar.h>
70 # else
71 /* Simulate mbrlen with mblen as best we can. */
72 # define mbstate_t int
73 # define mbrlen(s, n, ps) mblen (s, n)
74 # define mbsinit(ps) (*(ps) == 0)
75 # endif
76 static const mbstate_t mbstate_zero;
77 #endif
79 #if HAVE_LIMITS_H
80 # include <limits.h>
81 #endif
83 #if STDC_HEADERS
84 # include <stddef.h>
85 # include <stdlib.h>
86 # include <string.h>
87 #else
88 # ifndef HAVE_MEMCPY
89 # define memcpy(d, s, n) bcopy ((s), (d), (n))
90 # endif
91 #endif
93 #ifdef COMPILE_WIDE
94 # include <endian.h>
95 # define CHAR_T wchar_t
96 # define UCHAR_T unsigned int
97 # define L_(Str) L##Str
98 # define NLW(Sym) _NL_W##Sym
100 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
101 # define STRLEN(s) __wcslen (s)
103 #else
104 # define CHAR_T char
105 # define UCHAR_T unsigned char
106 # define L_(Str) Str
107 # define NLW(Sym) Sym
109 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
110 # define MEMCPY(d, s, n) bcopy ((s), (d), (n))
111 # else
112 # define MEMCPY(d, s, n) memcpy ((d), (s), (n))
113 # endif
114 # define STRLEN(s) strlen (s)
116 # ifdef _LIBC
117 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
118 # else
119 # ifndef HAVE_MEMPCPY
120 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
121 # endif
122 # endif
123 #endif
125 #ifndef __P
126 # if defined __GNUC__ || (defined __STDC__ && __STDC__)
127 # define __P(args) args
128 # else
129 # define __P(args) ()
130 # endif /* GCC. */
131 #endif /* Not __P. */
133 #ifndef PTR
134 # ifdef __STDC__
135 # define PTR void *
136 # else
137 # define PTR char *
138 # endif
139 #endif
141 #ifndef CHAR_BIT
142 # define CHAR_BIT 8
143 #endif
145 #ifndef NULL
146 # define NULL 0
147 #endif
149 #define TYPE_SIGNED(t) ((t) -1 < 0)
151 /* Bound on length of the string representing an integer value of type t.
152 Subtract one for the sign bit if t is signed;
153 302 / 1000 is log10 (2) rounded up;
154 add one for integer division truncation;
155 add one more for a minus sign if t is signed. */
156 #define INT_STRLEN_BOUND(t) \
157 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
159 #define TM_YEAR_BASE 1900
161 #ifndef __isleap
162 /* Nonzero if YEAR is a leap year (every 4 years,
163 except every 100th isn't, and every 400th is). */
164 # define __isleap(year) \
165 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
166 #endif
169 #ifdef _LIBC
170 # define tzname __tzname
171 # define tzset __tzset
172 #endif
174 #if !HAVE_TM_GMTOFF
175 /* Portable standalone applications should supply a "time_r.h" that
176 declares a POSIX-compliant localtime_r, for the benefit of older
177 implementations that lack localtime_r or have a nonstandard one.
178 Similarly for gmtime_r. See the gnulib time_r module for one way
179 to implement this. */
180 # include "time_r.h"
181 # undef __gmtime_r
182 # undef __localtime_r
183 # define __gmtime_r gmtime_r
184 # define __localtime_r localtime_r
185 #endif
188 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
189 /* Some systems lack the `memset' function and we don't want to
190 introduce additional dependencies. */
191 /* The SGI compiler reportedly barfs on the trailing null
192 if we use a string constant as the initializer. 28 June 1997, rms. */
193 static const CHAR_T spaces[16] = /* " " */
195 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
196 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
198 static const CHAR_T zeroes[16] = /* "0000000000000000" */
200 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
201 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
204 # define memset_space(P, Len) \
205 do { \
206 int _len = (Len); \
208 do \
210 int _this = _len > 16 ? 16 : _len; \
211 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
212 _len -= _this; \
214 while (_len > 0); \
215 } while (0)
217 # define memset_zero(P, Len) \
218 do { \
219 int _len = (Len); \
221 do \
223 int _this = _len > 16 ? 16 : _len; \
224 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
225 _len -= _this; \
227 while (_len > 0); \
228 } while (0)
229 #else
230 # ifdef COMPILE_WIDE
231 # define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
232 # define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
233 # else
234 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
235 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
236 # endif
237 #endif
239 #define add(n, f) \
240 do \
242 int _n = (n); \
243 int _delta = width - _n; \
244 int _incr = _n + (_delta > 0 ? _delta : 0); \
245 if ((size_t) _incr >= maxsize - i) \
246 return 0; \
247 if (p) \
249 if (_delta > 0) \
251 if (pad == L_('0')) \
252 memset_zero (p, _delta); \
253 else \
254 memset_space (p, _delta); \
256 f; \
257 p += _n; \
259 i += _incr; \
260 } while (0)
262 #define cpy(n, s) \
263 add ((n), \
264 if (to_lowcase) \
265 memcpy_lowcase (p, (s), _n LOCALE_ARG); \
266 else if (to_uppcase) \
267 memcpy_uppcase (p, (s), _n LOCALE_ARG); \
268 else \
269 MEMCPY ((PTR) p, (const PTR) (s), _n))
271 #ifdef COMPILE_WIDE
272 # ifndef USE_IN_EXTENDED_LOCALE_MODEL
273 # undef __mbsrtowcs_l
274 # define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
275 # endif
276 # define widen(os, ws, l) \
278 mbstate_t __st; \
279 const char *__s = os; \
280 memset (&__st, '\0', sizeof (__st)); \
281 l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
282 ws = alloca ((l + 1) * sizeof (wchar_t)); \
283 (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
285 #endif
288 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
289 /* We use this code also for the extended locale handling where the
290 function gets as an additional argument the locale which has to be
291 used. To access the values we have to redefine the _NL_CURRENT
292 macro. */
293 # define strftime __strftime_l
294 # define wcsftime __wcsftime_l
295 # undef _NL_CURRENT
296 # define _NL_CURRENT(category, item) \
297 (current->values[_NL_ITEM_INDEX (item)].string)
298 # define LOCALE_PARAM , loc
299 # define LOCALE_ARG , loc
300 # define LOCALE_PARAM_DECL __locale_t loc;
301 # define LOCALE_PARAM_PROTO , __locale_t loc
302 # define HELPER_LOCALE_ARG , current
303 #else
304 # define LOCALE_PARAM
305 # define LOCALE_PARAM_PROTO
306 # define LOCALE_ARG
307 # define LOCALE_PARAM_DECL
308 # ifdef _LIBC
309 # define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
310 # else
311 # define HELPER_LOCALE_ARG
312 # endif
313 #endif
315 #ifdef COMPILE_WIDE
316 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
317 # define TOUPPER(Ch, L) __towupper_l (Ch, L)
318 # define TOLOWER(Ch, L) __towlower_l (Ch, L)
319 # else
320 # define TOUPPER(Ch, L) towupper (Ch)
321 # define TOLOWER(Ch, L) towlower (Ch)
322 # endif
323 #else
324 # ifdef _LIBC
325 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
326 # define TOUPPER(Ch, L) __toupper_l (Ch, L)
327 # define TOLOWER(Ch, L) __tolower_l (Ch, L)
328 # else
329 # define TOUPPER(Ch, L) toupper (Ch)
330 # define TOLOWER(Ch, L) tolower (Ch)
331 # endif
332 # else
333 # define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
334 # define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
335 # endif
336 #endif
337 /* We don't use `isdigit' here since the locale dependent
338 interpretation is not what we want here. We only need to accept
339 the arabic digits in the ASCII range. One day there is perhaps a
340 more reliable way to accept other sets of digits. */
341 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
343 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
344 size_t len LOCALE_PARAM_PROTO));
346 static CHAR_T *
347 memcpy_lowcase (dest, src, len LOCALE_PARAM)
348 CHAR_T *dest;
349 const CHAR_T *src;
350 size_t len;
351 LOCALE_PARAM_DECL
353 while (len-- > 0)
354 dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
355 return dest;
358 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
359 size_t len LOCALE_PARAM_PROTO));
361 static CHAR_T *
362 memcpy_uppcase (dest, src, len LOCALE_PARAM)
363 CHAR_T *dest;
364 const CHAR_T *src;
365 size_t len;
366 LOCALE_PARAM_DECL
368 while (len-- > 0)
369 dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
370 return dest;
374 #if ! HAVE_TM_GMTOFF
375 /* Yield the difference between *A and *B,
376 measured in seconds, ignoring leap seconds. */
377 # define tm_diff ftime_tm_diff
378 static int tm_diff __P ((const struct tm *, const struct tm *));
379 static int
380 tm_diff (a, b)
381 const struct tm *a;
382 const struct tm *b;
384 /* Compute intervening leap days correctly even if year is negative.
385 Take care to avoid int overflow in leap day calculations,
386 but it's OK to assume that A and B are close to each other. */
387 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
388 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
389 int a100 = a4 / 25 - (a4 % 25 < 0);
390 int b100 = b4 / 25 - (b4 % 25 < 0);
391 int a400 = a100 >> 2;
392 int b400 = b100 >> 2;
393 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
394 int years = a->tm_year - b->tm_year;
395 int days = (365 * years + intervening_leap_days
396 + (a->tm_yday - b->tm_yday));
397 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
398 + (a->tm_min - b->tm_min))
399 + (a->tm_sec - b->tm_sec));
401 #endif /* ! HAVE_TM_GMTOFF */
405 /* The number of days from the first day of the first ISO week of this
406 year to the year day YDAY with week day WDAY. ISO weeks start on
407 Monday; the first ISO week has the year's first Thursday. YDAY may
408 be as small as YDAY_MINIMUM. */
409 #define ISO_WEEK_START_WDAY 1 /* Monday */
410 #define ISO_WEEK1_WDAY 4 /* Thursday */
411 #define YDAY_MINIMUM (-366)
412 static int iso_week_days __P ((int, int));
413 #ifdef __GNUC__
414 __inline__
415 #endif
416 static int
417 iso_week_days (yday, wday)
418 int yday;
419 int wday;
421 /* Add enough to the first operand of % to make it nonnegative. */
422 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
423 return (yday
424 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
425 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
429 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
430 static CHAR_T const weekday_name[][10] =
432 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
433 L_("Thursday"), L_("Friday"), L_("Saturday")
435 static CHAR_T const month_name[][10] =
437 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
438 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
439 L_("November"), L_("December")
441 #endif
444 #ifdef emacs
445 # define my_strftime emacs_strftimeu
446 # define ut_argument , ut
447 # define ut_argument_spec int ut;
448 # define ut_argument_spec_iso , int ut
449 #else
450 # ifdef COMPILE_WIDE
451 # define my_strftime wcsftime
452 # define nl_get_alt_digit _nl_get_walt_digit
453 # else
454 # define my_strftime strftime
455 # define nl_get_alt_digit _nl_get_alt_digit
456 # endif
457 # define ut_argument
458 # define ut_argument_spec
459 # define ut_argument_spec_iso
460 /* We don't have this information in general. */
461 # define ut 0
462 #endif
464 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
465 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
466 Work around this bug by copying *tp before it might be munged. */
467 size_t _strftime_copytm __P ((char *, size_t, const char *,
468 const struct tm * ut_argument_spec_iso));
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 struct tm tmcopy;
478 tmcopy = *tp;
479 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
481 # undef my_strftime
482 # define my_strftime _strftime_copytm
483 #endif
486 /* Write information from TP into S according to the format
487 string FORMAT, writing no more that MAXSIZE characters
488 (including the terminating '\0') and returning number of
489 characters written. If S is NULL, nothing will be written
490 anywhere, so to determine how many characters would be
491 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
492 size_t
493 my_strftime (s, maxsize, format, tp ut_argument LOCALE_PARAM)
494 CHAR_T *s;
495 size_t maxsize;
496 const CHAR_T *format;
497 const struct tm *tp;
498 ut_argument_spec
499 LOCALE_PARAM_DECL
501 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
502 struct locale_data *const current = loc->__locales[LC_TIME];
503 #endif
505 int hour12 = tp->tm_hour;
506 #ifdef _NL_CURRENT
507 /* We cannot make the following values variables since we must delay
508 the evaluation of these values until really needed since some
509 expressions might not be valid in every situation. The `struct tm'
510 might be generated by a strptime() call that initialized
511 only a few elements. Dereference the pointers only if the format
512 requires this. Then it is ok to fail if the pointers are invalid. */
513 # define a_wkday \
514 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
515 # define f_wkday \
516 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
517 # define a_month \
518 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
519 # define f_month \
520 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
521 # define ampm \
522 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
523 ? NLW(PM_STR) : NLW(AM_STR)))
525 # define aw_len STRLEN (a_wkday)
526 # define am_len STRLEN (a_month)
527 # define ap_len STRLEN (ampm)
528 #else
529 # if !HAVE_STRFTIME
530 # define f_wkday (weekday_name[tp->tm_wday])
531 # define f_month (month_name[tp->tm_mon])
532 # define a_wkday f_wkday
533 # define a_month f_month
534 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
536 size_t aw_len = 3;
537 size_t am_len = 3;
538 size_t ap_len = 2;
539 # endif
540 #endif
541 const char *zone;
542 size_t i = 0;
543 CHAR_T *p = s;
544 const CHAR_T *f;
545 #if DO_MULTIBYTE && !defined COMPILE_WIDE
546 const char *format_end = NULL;
547 #endif
549 zone = NULL;
550 #if HAVE_TM_ZONE
551 /* The POSIX test suite assumes that setting
552 the environment variable TZ to a new value before calling strftime()
553 will influence the result (the %Z format) even if the information in
554 TP is computed with a totally different time zone.
555 This is bogus: though POSIX allows bad behavior like this,
556 POSIX does not require it. Do the right thing instead. */
557 zone = (const char *) tp->tm_zone;
558 #endif
559 #if HAVE_TZNAME
560 if (ut)
562 if (! (zone && *zone))
563 zone = "GMT";
565 else
567 /* POSIX.1 requires that local time zone information is used as
568 though strftime called tzset. */
569 # if HAVE_TZSET
570 tzset ();
571 # endif
573 #endif
575 if (hour12 > 12)
576 hour12 -= 12;
577 else
578 if (hour12 == 0)
579 hour12 = 12;
581 for (f = format; *f != '\0'; ++f)
583 int pad = 0; /* Padding for number ('-', '_', or 0). */
584 int modifier; /* Field modifier ('E', 'O', or 0). */
585 int digits; /* Max digits for numeric format. */
586 int number_value; /* Numeric value to be printed. */
587 int negative_number; /* 1 if the number is negative. */
588 const CHAR_T *subfmt;
589 CHAR_T *bufp;
590 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
591 ? INT_STRLEN_BOUND (time_t)
592 : INT_STRLEN_BOUND (int))];
593 int width = -1;
594 int to_lowcase = 0;
595 int to_uppcase = 0;
596 int change_case = 0;
597 int format_char;
599 #if DO_MULTIBYTE && !defined COMPILE_WIDE
600 switch (*f)
602 case L_('%'):
603 break;
605 case L_('\b'): case L_('\t'): case L_('\n'):
606 case L_('\v'): case L_('\f'): case L_('\r'):
607 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
608 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
609 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
610 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
611 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
612 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
613 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
614 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
615 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
616 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
617 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
618 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
619 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
620 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
621 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
622 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
623 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
624 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
625 case L_('~'):
626 /* The C Standard requires these 98 characters (plus '%') to
627 be in the basic execution character set. None of these
628 characters can start a multibyte sequence, so they need
629 not be analyzed further. */
630 add (1, *p = *f);
631 continue;
633 default:
634 /* Copy this multibyte sequence until we reach its end, find
635 an error, or come back to the initial shift state. */
637 mbstate_t mbstate = mbstate_zero;
638 size_t len = 0;
639 size_t fsize;
641 if (! format_end)
642 format_end = f + strlen (f) + 1;
643 fsize = format_end - f;
647 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
649 if (bytes == 0)
650 break;
652 if (bytes == (size_t) -2)
654 len += strlen (f + len);
655 break;
658 if (bytes == (size_t) -1)
660 len++;
661 break;
664 len += bytes;
666 while (! mbsinit (&mbstate));
668 cpy (len, f);
669 f += len - 1;
670 continue;
674 #else /* ! DO_MULTIBYTE */
676 /* Either multibyte encodings are not supported, they are
677 safe for formats, so any non-'%' byte can be copied through,
678 or this is the wide character version. */
679 if (*f != L_('%'))
681 add (1, *p = *f);
682 continue;
685 #endif /* ! DO_MULTIBYTE */
687 /* Check for flags that can modify a format. */
688 while (1)
690 switch (*++f)
692 /* This influences the number formats. */
693 case L_('_'):
694 case L_('-'):
695 case L_('0'):
696 pad = *f;
697 continue;
699 /* This changes textual output. */
700 case L_('^'):
701 to_uppcase = 1;
702 continue;
703 case L_('#'):
704 change_case = 1;
705 continue;
707 default:
708 break;
710 break;
713 /* As a GNU extension we allow to specify the field width. */
714 if (ISDIGIT (*f))
716 width = 0;
719 if (width > INT_MAX / 10
720 || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
721 /* Avoid overflow. */
722 width = INT_MAX;
723 else
725 width *= 10;
726 width += *f - L_('0');
728 ++f;
730 while (ISDIGIT (*f));
733 /* Check for modifiers. */
734 switch (*f)
736 case L_('E'):
737 case L_('O'):
738 modifier = *f++;
739 break;
741 default:
742 modifier = 0;
743 break;
746 /* Now do the specified format. */
747 format_char = *f;
748 switch (format_char)
750 #define DO_NUMBER(d, v) \
751 digits = d > width ? d : width; \
752 number_value = v; goto do_number
753 #define DO_NUMBER_SPACEPAD(d, v) \
754 digits = d > width ? d : width; \
755 number_value = v; goto do_number_spacepad
757 case L_('%'):
758 if (modifier != 0)
759 goto bad_format;
760 add (1, *p = *f);
761 break;
763 case L_('a'):
764 if (modifier != 0)
765 goto bad_format;
766 if (change_case)
768 to_uppcase = 1;
769 to_lowcase = 0;
771 #if defined _NL_CURRENT || !HAVE_STRFTIME
772 cpy (aw_len, a_wkday);
773 break;
774 #else
775 goto underlying_strftime;
776 #endif
778 case 'A':
779 if (modifier != 0)
780 goto bad_format;
781 if (change_case)
783 to_uppcase = 1;
784 to_lowcase = 0;
786 #if defined _NL_CURRENT || !HAVE_STRFTIME
787 cpy (STRLEN (f_wkday), f_wkday);
788 break;
789 #else
790 goto underlying_strftime;
791 #endif
793 case L_('b'):
794 case L_('h'):
795 if (change_case)
797 to_uppcase = 1;
798 to_lowcase = 0;
800 if (modifier != 0)
801 goto bad_format;
802 #if defined _NL_CURRENT || !HAVE_STRFTIME
803 cpy (am_len, a_month);
804 break;
805 #else
806 goto underlying_strftime;
807 #endif
809 case L_('B'):
810 if (modifier != 0)
811 goto bad_format;
812 if (change_case)
814 to_uppcase = 1;
815 to_lowcase = 0;
817 #if defined _NL_CURRENT || !HAVE_STRFTIME
818 cpy (STRLEN (f_month), f_month);
819 break;
820 #else
821 goto underlying_strftime;
822 #endif
824 case L_('c'):
825 if (modifier == L_('O'))
826 goto bad_format;
827 #ifdef _NL_CURRENT
828 if (! (modifier == 'E'
829 && (*(subfmt =
830 (const CHAR_T *) _NL_CURRENT (LC_TIME,
831 NLW(ERA_D_T_FMT)))
832 != '\0')))
833 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
834 #else
835 # if HAVE_STRFTIME
836 goto underlying_strftime;
837 # else
838 subfmt = L_("%a %b %e %H:%M:%S %Y");
839 # endif
840 #endif
842 subformat:
844 CHAR_T *old_start = p;
845 size_t len = my_strftime (NULL, (size_t) -1, subfmt,
846 tp ut_argument LOCALE_ARG);
847 add (len, my_strftime (p, maxsize - i, subfmt,
848 tp ut_argument LOCALE_ARG));
850 if (to_uppcase)
851 while (old_start < p)
853 *old_start = TOUPPER ((UCHAR_T) *old_start, loc);
854 ++old_start;
857 break;
859 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
860 underlying_strftime:
862 /* The relevant information is available only via the
863 underlying strftime implementation, so use that. */
864 char ufmt[4];
865 char *u = ufmt;
866 char ubuf[1024]; /* enough for any single format in practice */
867 size_t len;
868 /* Make sure we're calling the actual underlying strftime.
869 In some cases, config.h contains something like
870 "#define strftime rpl_strftime". */
871 # ifdef strftime
872 # undef strftime
873 size_t strftime ();
874 # endif
876 *u++ = '%';
877 if (modifier != 0)
878 *u++ = modifier;
879 *u++ = format_char;
880 *u = '\0';
881 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
882 if (len == 0 && ubuf[0] != '\0')
883 return 0;
884 cpy (len, ubuf);
886 break;
887 #endif
889 case L_('C'):
890 if (modifier == L_('O'))
891 goto bad_format;
892 if (modifier == L_('E'))
894 #if HAVE_STRUCT_ERA_ENTRY
895 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
896 if (era)
898 # ifdef COMPILE_WIDE
899 size_t len = __wcslen (era->era_wname);
900 cpy (len, era->era_wname);
901 # else
902 size_t len = strlen (era->era_name);
903 cpy (len, era->era_name);
904 # endif
905 break;
907 #else
908 # if HAVE_STRFTIME
909 goto underlying_strftime;
910 # endif
911 #endif
915 int year = tp->tm_year + TM_YEAR_BASE;
916 DO_NUMBER (1, year / 100 - (year % 100 < 0));
919 case L_('x'):
920 if (modifier == L_('O'))
921 goto bad_format;
922 #ifdef _NL_CURRENT
923 if (! (modifier == L_('E')
924 && (*(subfmt =
925 (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
926 != L_('\0'))))
927 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
928 goto subformat;
929 #else
930 # if HAVE_STRFTIME
931 goto underlying_strftime;
932 # else
933 /* Fall through. */
934 # endif
935 #endif
936 case L_('D'):
937 if (modifier != 0)
938 goto bad_format;
939 subfmt = L_("%m/%d/%y");
940 goto subformat;
942 case L_('d'):
943 if (modifier == L_('E'))
944 goto bad_format;
946 DO_NUMBER (2, tp->tm_mday);
948 case L_('e'):
949 if (modifier == L_('E'))
950 goto bad_format;
952 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
954 /* All numeric formats set DIGITS and NUMBER_VALUE and then
955 jump to one of these two labels. */
957 do_number_spacepad:
958 /* Force `_' flag unless overwritten by `0' or '-' flag. */
959 if (pad != L_('0') && pad != L_('-'))
960 pad = L_('_');
962 do_number:
963 /* Format the number according to the MODIFIER flag. */
965 if (modifier == L_('O') && 0 <= number_value)
967 #ifdef _NL_CURRENT
968 /* Get the locale specific alternate representation of
969 the number NUMBER_VALUE. If none exist NULL is returned. */
970 const CHAR_T *cp = nl_get_alt_digit (number_value
971 HELPER_LOCALE_ARG);
973 if (cp != NULL)
975 size_t digitlen = STRLEN (cp);
976 if (digitlen != 0)
978 cpy (digitlen, cp);
979 break;
982 #else
983 # if HAVE_STRFTIME
984 goto underlying_strftime;
985 # endif
986 #endif
989 unsigned int u = number_value;
991 bufp = buf + sizeof (buf) / sizeof (buf[0]);
992 negative_number = number_value < 0;
994 if (negative_number)
995 u = -u;
998 *--bufp = u % 10 + L_('0');
999 while ((u /= 10) != 0);
1002 do_number_sign_and_padding:
1003 if (negative_number)
1004 *--bufp = L_('-');
1006 if (pad != L_('-'))
1008 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
1009 - bufp);
1011 if (padding > 0)
1013 if (pad == L_('_'))
1015 if ((size_t) padding >= maxsize - i)
1016 return 0;
1018 if (p)
1019 memset_space (p, padding);
1020 i += padding;
1021 width = width > padding ? width - padding : 0;
1023 else
1025 if ((size_t) digits >= maxsize - i)
1026 return 0;
1028 if (negative_number)
1030 ++bufp;
1032 if (p)
1033 *p++ = L_('-');
1034 ++i;
1037 if (p)
1038 memset_zero (p, padding);
1039 i += padding;
1040 width = 0;
1045 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1046 break;
1048 case L_('F'):
1049 if (modifier != 0)
1050 goto bad_format;
1051 subfmt = L_("%Y-%m-%d");
1052 goto subformat;
1054 case L_('H'):
1055 if (modifier == L_('E'))
1056 goto bad_format;
1058 DO_NUMBER (2, tp->tm_hour);
1060 case L_('I'):
1061 if (modifier == L_('E'))
1062 goto bad_format;
1064 DO_NUMBER (2, hour12);
1066 case L_('k'): /* GNU extension. */
1067 if (modifier == L_('E'))
1068 goto bad_format;
1070 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1072 case L_('l'): /* GNU extension. */
1073 if (modifier == L_('E'))
1074 goto bad_format;
1076 DO_NUMBER_SPACEPAD (2, hour12);
1078 case L_('j'):
1079 if (modifier == L_('E'))
1080 goto bad_format;
1082 DO_NUMBER (3, 1 + tp->tm_yday);
1084 case L_('M'):
1085 if (modifier == L_('E'))
1086 goto bad_format;
1088 DO_NUMBER (2, tp->tm_min);
1090 case L_('m'):
1091 if (modifier == L_('E'))
1092 goto bad_format;
1094 DO_NUMBER (2, tp->tm_mon + 1);
1096 case L_('n'):
1097 add (1, *p = L_('\n'));
1098 break;
1100 case L_('P'):
1101 to_lowcase = 1;
1102 #if !defined _NL_CURRENT && HAVE_STRFTIME
1103 format_char = L_('p');
1104 #endif
1105 /* FALLTHROUGH */
1107 case L_('p'):
1108 if (change_case)
1110 to_uppcase = 0;
1111 to_lowcase = 1;
1113 #if defined _NL_CURRENT || !HAVE_STRFTIME
1114 cpy (ap_len, ampm);
1115 break;
1116 #else
1117 goto underlying_strftime;
1118 #endif
1120 case L_('R'):
1121 subfmt = L_("%H:%M");
1122 goto subformat;
1124 case L_('r'):
1125 #if !defined _NL_CURRENT && HAVE_STRFTIME
1126 goto underlying_strftime;
1127 #else
1128 # ifdef _NL_CURRENT
1129 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1130 NLW(T_FMT_AMPM)))
1131 == L_('\0'))
1132 # endif
1133 subfmt = L_("%I:%M:%S %p");
1134 goto subformat;
1135 #endif
1137 case L_('S'):
1138 if (modifier == L_('E'))
1139 goto bad_format;
1141 DO_NUMBER (2, tp->tm_sec);
1143 case L_('s'): /* GNU extension. */
1145 struct tm ltm;
1146 time_t t;
1148 ltm = *tp;
1149 t = mktime (&ltm);
1151 /* Generate string value for T using time_t arithmetic;
1152 this works even if sizeof (long) < sizeof (time_t). */
1154 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1155 negative_number = t < 0;
1159 int d = t % 10;
1160 t /= 10;
1162 if (negative_number)
1164 d = -d;
1166 /* Adjust if division truncates to minus infinity. */
1167 if (0 < -1 % 10 && d < 0)
1169 t++;
1170 d += 10;
1174 *--bufp = d + L_('0');
1176 while (t != 0);
1178 digits = 1;
1179 goto do_number_sign_and_padding;
1182 case L_('X'):
1183 if (modifier == L_('O'))
1184 goto bad_format;
1185 #ifdef _NL_CURRENT
1186 if (! (modifier == L_('E')
1187 && (*(subfmt =
1188 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1189 != L_('\0'))))
1190 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1191 goto subformat;
1192 #else
1193 # if HAVE_STRFTIME
1194 goto underlying_strftime;
1195 # else
1196 /* Fall through. */
1197 # endif
1198 #endif
1199 case L_('T'):
1200 subfmt = L_("%H:%M:%S");
1201 goto subformat;
1203 case L_('t'):
1204 add (1, *p = L_('\t'));
1205 break;
1207 case L_('u'):
1208 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1210 case L_('U'):
1211 if (modifier == L_('E'))
1212 goto bad_format;
1214 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1216 case L_('V'):
1217 case L_('g'):
1218 case L_('G'):
1219 if (modifier == L_('E'))
1220 goto bad_format;
1222 int year = tp->tm_year + TM_YEAR_BASE;
1223 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1225 if (days < 0)
1227 /* This ISO week belongs to the previous year. */
1228 year--;
1229 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1230 tp->tm_wday);
1232 else
1234 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1235 tp->tm_wday);
1236 if (0 <= d)
1238 /* This ISO week belongs to the next year. */
1239 year++;
1240 days = d;
1244 switch (*f)
1246 case L_('g'):
1247 DO_NUMBER (2, (year % 100 + 100) % 100);
1249 case L_('G'):
1250 DO_NUMBER (1, year);
1252 default:
1253 DO_NUMBER (2, days / 7 + 1);
1257 case L_('W'):
1258 if (modifier == L_('E'))
1259 goto bad_format;
1261 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1263 case L_('w'):
1264 if (modifier == L_('E'))
1265 goto bad_format;
1267 DO_NUMBER (1, tp->tm_wday);
1269 case L_('Y'):
1270 if (modifier == 'E')
1272 #if HAVE_STRUCT_ERA_ENTRY
1273 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1274 if (era)
1276 # ifdef COMPILE_WIDE
1277 subfmt = era->era_wformat;
1278 # else
1279 subfmt = era->era_format;
1280 # endif
1281 goto subformat;
1283 #else
1284 # if HAVE_STRFTIME
1285 goto underlying_strftime;
1286 # endif
1287 #endif
1289 if (modifier == L_('O'))
1290 goto bad_format;
1291 else
1292 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1294 case L_('y'):
1295 if (modifier == L_('E'))
1297 #if HAVE_STRUCT_ERA_ENTRY
1298 struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
1299 if (era)
1301 int delta = tp->tm_year - era->start_date[0];
1302 DO_NUMBER (1, (era->offset
1303 + delta * era->absolute_direction));
1305 #else
1306 # if HAVE_STRFTIME
1307 goto underlying_strftime;
1308 # endif
1309 #endif
1311 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1313 case L_('Z'):
1314 if (change_case)
1316 to_uppcase = 0;
1317 to_lowcase = 1;
1320 #if HAVE_TZNAME
1321 /* The tzset() call might have changed the value. */
1322 if (!(zone && *zone) && tp->tm_isdst >= 0)
1323 zone = tzname[tp->tm_isdst];
1324 #endif
1325 if (! zone)
1326 zone = "";
1328 #ifdef COMPILE_WIDE
1330 /* The zone string is always given in multibyte form. We have
1331 to transform it first. */
1332 wchar_t *wczone;
1333 size_t len;
1334 widen (zone, wczone, len);
1335 cpy (len, wczone);
1337 #else
1338 cpy (strlen (zone), zone);
1339 #endif
1340 break;
1342 case L_('z'):
1343 if (tp->tm_isdst < 0)
1344 break;
1347 int diff;
1348 #if HAVE_TM_GMTOFF
1349 diff = tp->tm_gmtoff;
1350 #else
1351 if (ut)
1352 diff = 0;
1353 else
1355 struct tm gtm;
1356 struct tm ltm;
1357 time_t lt;
1359 ltm = *tp;
1360 lt = mktime (&ltm);
1362 if (lt == (time_t) -1)
1364 /* mktime returns -1 for errors, but -1 is also a
1365 valid time_t value. Check whether an error really
1366 occurred. */
1367 struct tm tm;
1369 if (! __localtime_r (&lt, &tm)
1370 || ((ltm.tm_sec ^ tm.tm_sec)
1371 | (ltm.tm_min ^ tm.tm_min)
1372 | (ltm.tm_hour ^ tm.tm_hour)
1373 | (ltm.tm_mday ^ tm.tm_mday)
1374 | (ltm.tm_mon ^ tm.tm_mon)
1375 | (ltm.tm_year ^ tm.tm_year)))
1376 break;
1379 if (! __gmtime_r (&lt, &gtm))
1380 break;
1382 diff = tm_diff (&ltm, &gtm);
1384 #endif
1386 if (diff < 0)
1388 add (1, *p = L_('-'));
1389 diff = -diff;
1391 else
1392 add (1, *p = L_('+'));
1394 diff /= 60;
1395 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1398 case L_('\0'): /* GNU extension: % at end of format. */
1399 --f;
1400 /* Fall through. */
1401 default:
1402 /* Unknown format; output the format, including the '%',
1403 since this is most likely the right thing to do if a
1404 multibyte string has been misparsed. */
1405 bad_format:
1407 int flen;
1408 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1409 continue;
1410 cpy (flen, &f[1 - flen]);
1412 break;
1416 if (p && maxsize != 0)
1417 *p = L_('\0');
1418 return i;
1420 #ifdef _LIBC
1421 libc_hidden_def (my_strftime)
1422 #endif
1425 #ifdef emacs
1426 /* For Emacs we have a separate interface which corresponds to the normal
1427 strftime function and does not have the extra information whether the
1428 TP arguments comes from a `gmtime' call or not. */
1429 size_t
1430 emacs_strftime (s, maxsize, format, tp)
1431 char *s;
1432 size_t maxsize;
1433 const char *format;
1434 const struct tm *tp;
1436 return my_strftime (s, maxsize, format, tp, 0);
1438 #endif
1440 #if defined _LIBC && !defined COMPILE_WIDE
1441 weak_alias (__strftime_l, strftime_l)
1442 #endif