Add dl-brk.c, dl-sbrk.c, and sys/personality.h.
[glibc.git] / time / strftime.c
blob986124399bcf00b05c8913c94e3242961f557535
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); \
287 else if (to_uppcase) \
288 memcpy_uppcase (p, (s), _n); \
289 else \
290 MEMCPY ((PTR) p, (const PTR) (s), _n))
292 #ifdef COMPILE_WIDE
293 # define widen(os, ws, l) \
295 mbstate_t __st; \
296 const char *__s = os; \
297 memset (&__st, '\0', sizeof (__st)); \
298 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
299 ws = alloca ((l + 1) * sizeof (wchar_t)); \
300 (void) __mbsrtowcs (ws, &__s, l, &__st); \
302 #endif
305 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
306 /* We use this code also for the extended locale handling where the
307 function gets as an additional argument the locale which has to be
308 used. To access the values we have to redefine the _NL_CURRENT
309 macro. */
310 # define strftime __strftime_l
311 # define wcsftime __wcsftime_l
312 # undef _NL_CURRENT
313 # define _NL_CURRENT(category, item) \
314 (current->values[_NL_ITEM_INDEX (item)].string)
315 # define LOCALE_PARAM , loc
316 # define LOCALE_ARG , loc
317 # define LOCALE_PARAM_DECL __locale_t loc;
318 #else
319 # define LOCALE_PARAM
320 # define LOCALE_ARG
321 # define LOCALE_PARAM_DECL
322 #endif
324 #ifdef COMPILE_WIDE
325 # define TOUPPER(Ch) towupper (Ch)
326 # define TOLOWER(Ch) towlower (Ch)
327 #else
328 # ifdef _LIBC
329 # define TOUPPER(Ch) toupper (Ch)
330 # define TOLOWER(Ch) tolower (Ch)
331 # else
332 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
333 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
334 # endif
335 #endif
336 /* We don't use `isdigit' here since the locale dependent
337 interpretation is not what we want here. We only need to accept
338 the arabic digits in the ASCII range. One day there is perhaps a
339 more reliable way to accept other sets of digits. */
340 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
342 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
343 size_t len));
345 static CHAR_T *
346 memcpy_lowcase (dest, src, len)
347 CHAR_T *dest;
348 const CHAR_T *src;
349 size_t len;
351 while (len-- > 0)
352 dest[len] = TOLOWER ((UCHAR_T) src[len]);
353 return dest;
356 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
357 size_t len));
359 static CHAR_T *
360 memcpy_uppcase (dest, src, len)
361 CHAR_T *dest;
362 const CHAR_T *src;
363 size_t len;
365 while (len-- > 0)
366 dest[len] = TOUPPER ((UCHAR_T) src[len]);
367 return dest;
371 #if ! HAVE_TM_GMTOFF
372 /* Yield the difference between *A and *B,
373 measured in seconds, ignoring leap seconds. */
374 # define tm_diff ftime_tm_diff
375 static int tm_diff __P ((const struct tm *, const struct tm *));
376 static int
377 tm_diff (a, b)
378 const struct tm *a;
379 const struct tm *b;
381 /* Compute intervening leap days correctly even if year is negative.
382 Take care to avoid int overflow in leap day calculations,
383 but it's OK to assume that A and B are close to each other. */
384 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
385 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
386 int a100 = a4 / 25 - (a4 % 25 < 0);
387 int b100 = b4 / 25 - (b4 % 25 < 0);
388 int a400 = a100 >> 2;
389 int b400 = b100 >> 2;
390 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
391 int years = a->tm_year - b->tm_year;
392 int days = (365 * years + intervening_leap_days
393 + (a->tm_yday - b->tm_yday));
394 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
395 + (a->tm_min - b->tm_min))
396 + (a->tm_sec - b->tm_sec));
398 #endif /* ! HAVE_TM_GMTOFF */
402 /* The number of days from the first day of the first ISO week of this
403 year to the year day YDAY with week day WDAY. ISO weeks start on
404 Monday; the first ISO week has the year's first Thursday. YDAY may
405 be as small as YDAY_MINIMUM. */
406 #define ISO_WEEK_START_WDAY 1 /* Monday */
407 #define ISO_WEEK1_WDAY 4 /* Thursday */
408 #define YDAY_MINIMUM (-366)
409 static int iso_week_days __P ((int, int));
410 #ifdef __GNUC__
411 __inline__
412 #endif
413 static int
414 iso_week_days (yday, wday)
415 int yday;
416 int wday;
418 /* Add enough to the first operand of % to make it nonnegative. */
419 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
420 return (yday
421 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
422 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
426 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
427 static CHAR_T const weekday_name[][10] =
429 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
430 L_("Thursday"), L_("Friday"), L_("Saturday")
432 static CHAR_T const month_name[][10] =
434 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
435 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
436 L_("November"), L_("December")
438 #endif
441 #ifdef emacs
442 # define my_strftime emacs_strftimeu
443 # define ut_argument , ut
444 # define ut_argument_spec int ut;
445 # define ut_argument_spec_iso , int ut
446 #else
447 # ifdef COMPILE_WIDE
448 # define my_strftime wcsftime
449 # else
450 # define my_strftime strftime
451 # endif
452 # define ut_argument
453 # define ut_argument_spec
454 # define ut_argument_spec_iso
455 /* We don't have this information in general. */
456 # define ut 0
457 #endif
459 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
460 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
461 Work around this bug by copying *tp before it might be munged. */
462 size_t _strftime_copytm __P ((char *, size_t, const char *,
463 const struct tm * ut_argument_spec_iso));
464 size_t
465 my_strftime (s, maxsize, format, tp ut_argument)
466 CHAR_T *s;
467 size_t maxsize;
468 const CHAR_T *format;
469 const struct tm *tp;
470 ut_argument_spec
472 struct tm tmcopy;
473 tmcopy = *tp;
474 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
476 # undef my_strftime
477 # define my_strftime _strftime_copytm
478 #endif
481 /* Write information from TP into S according to the format
482 string FORMAT, writing no more that MAXSIZE characters
483 (including the terminating '\0') and returning number of
484 characters written. If S is NULL, nothing will be written
485 anywhere, so to determine how many characters would be
486 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
487 size_t
488 my_strftime (s, maxsize, format, tp ut_argument LOCALE_PARAM)
489 CHAR_T *s;
490 size_t maxsize;
491 const CHAR_T *format;
492 const struct tm *tp;
493 ut_argument_spec
494 LOCALE_PARAM_DECL
496 #if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
497 const struct locale_data *const current = loc->__locales[LC_TIME];
498 #endif
500 int hour12 = tp->tm_hour;
501 #ifdef _NL_CURRENT
502 /* We cannot make the following values variables since we must delay
503 the evaluation of these values until really needed since some
504 expressions might not be valid in every situation. The `struct tm'
505 might be generated by a strptime() call that initialized
506 only a few elements. Dereference the pointers only if the format
507 requires this. Then it is ok to fail if the pointers are invalid. */
508 # define a_wkday \
509 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
510 # define f_wkday \
511 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
512 # define a_month \
513 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
514 # define f_month \
515 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
516 # define ampm \
517 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
518 ? NLW(PM_STR) : NLW(AM_STR)))
520 # define aw_len STRLEN (a_wkday)
521 # define am_len STRLEN (a_month)
522 # define ap_len STRLEN (ampm)
523 #else
524 # if !HAVE_STRFTIME
525 # define f_wkday (weekday_name[tp->tm_wday])
526 # define f_month (month_name[tp->tm_mon])
527 # define a_wkday f_wkday
528 # define a_month f_month
529 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
531 size_t aw_len = 3;
532 size_t am_len = 3;
533 size_t ap_len = 2;
534 # endif
535 #endif
536 const char *zone;
537 size_t i = 0;
538 CHAR_T *p = s;
539 const CHAR_T *f;
540 #if DO_MULTIBYTE && !defined COMPILE_WIDE
541 const char *format_end = NULL;
542 #endif
544 zone = NULL;
545 #if HAVE_TM_ZONE
546 /* The POSIX test suite assumes that setting
547 the environment variable TZ to a new value before calling strftime()
548 will influence the result (the %Z format) even if the information in
549 TP is computed with a totally different time zone.
550 This is bogus: though POSIX allows bad behavior like this,
551 POSIX does not require it. Do the right thing instead. */
552 zone = (const char *) tp->tm_zone;
553 #endif
554 #if HAVE_TZNAME
555 if (ut)
557 if (! (zone && *zone))
558 zone = "GMT";
560 else
562 /* POSIX.1 requires that local time zone information is used as
563 though strftime called tzset. */
564 # if HAVE_TZSET
565 tzset ();
566 # endif
568 #endif
570 if (hour12 > 12)
571 hour12 -= 12;
572 else
573 if (hour12 == 0)
574 hour12 = 12;
576 for (f = format; *f != '\0'; ++f)
578 int pad = 0; /* Padding for number ('-', '_', or 0). */
579 int modifier; /* Field modifier ('E', 'O', or 0). */
580 int digits; /* Max digits for numeric format. */
581 int number_value; /* Numeric value to be printed. */
582 int negative_number; /* 1 if the number is negative. */
583 const CHAR_T *subfmt;
584 CHAR_T *bufp;
585 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
586 ? INT_STRLEN_BOUND (time_t)
587 : INT_STRLEN_BOUND (int))];
588 int width = -1;
589 int to_lowcase = 0;
590 int to_uppcase = 0;
591 int change_case = 0;
592 int format_char;
594 #if DO_MULTIBYTE && !defined COMPILE_WIDE
595 switch (*f)
597 case L_('%'):
598 break;
600 case L_('\b'): case L_('\t'): case L_('\n'):
601 case L_('\v'): case L_('\f'): case L_('\r'):
602 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
603 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
604 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
605 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
606 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
607 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
608 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
609 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
610 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
611 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
612 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
613 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
614 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
615 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
616 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
617 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
618 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
619 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
620 case L_('~'):
621 /* The C Standard requires these 98 characters (plus '%') to
622 be in the basic execution character set. None of these
623 characters can start a multibyte sequence, so they need
624 not be analyzed further. */
625 add (1, *p = *f);
626 continue;
628 default:
629 /* Copy this multibyte sequence until we reach its end, find
630 an error, or come back to the initial shift state. */
632 mbstate_t mbstate = mbstate_zero;
633 size_t len = 0;
634 size_t fsize;
636 if (! format_end)
637 format_end = f + strlen (f) + 1;
638 fsize = format_end - f;
642 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
644 if (bytes == 0)
645 break;
647 if (bytes == (size_t) -2)
649 len += strlen (f + len);
650 break;
653 if (bytes == (size_t) -1)
655 len++;
656 break;
659 len += bytes;
661 while (! mbsinit (&mbstate));
663 cpy (len, f);
664 f += len - 1;
665 continue;
669 #else /* ! DO_MULTIBYTE */
671 /* Either multibyte encodings are not supported, they are
672 safe for formats, so any non-'%' byte can be copied through,
673 or this is the wide character version. */
674 if (*f != L_('%'))
676 add (1, *p = *f);
677 continue;
680 #endif /* ! DO_MULTIBYTE */
682 /* Check for flags that can modify a format. */
683 while (1)
685 switch (*++f)
687 /* This influences the number formats. */
688 case L_('_'):
689 case L_('-'):
690 case L_('0'):
691 pad = *f;
692 continue;
694 /* This changes textual output. */
695 case L_('^'):
696 to_uppcase = 1;
697 continue;
698 case L_('#'):
699 change_case = 1;
700 continue;
702 default:
703 break;
705 break;
708 /* As a GNU extension we allow to specify the field width. */
709 if (ISDIGIT (*f))
711 width = 0;
714 width *= 10;
715 width += *f - L_('0');
716 ++f;
718 while (ISDIGIT (*f));
721 /* Check for modifiers. */
722 switch (*f)
724 case L_('E'):
725 case L_('O'):
726 modifier = *f++;
727 break;
729 default:
730 modifier = 0;
731 break;
734 /* Now do the specified format. */
735 format_char = *f;
736 switch (format_char)
738 #define DO_NUMBER(d, v) \
739 digits = width == -1 ? d : width; \
740 number_value = v; goto do_number
741 #define DO_NUMBER_SPACEPAD(d, v) \
742 digits = width == -1 ? d : width; \
743 number_value = v; goto do_number_spacepad
745 case L_('%'):
746 if (modifier != 0)
747 goto bad_format;
748 add (1, *p = *f);
749 break;
751 case L_('a'):
752 if (modifier != 0)
753 goto bad_format;
754 if (change_case)
756 to_uppcase = 1;
757 to_lowcase = 0;
759 #if defined _NL_CURRENT || !HAVE_STRFTIME
760 cpy (aw_len, a_wkday);
761 break;
762 #else
763 goto underlying_strftime;
764 #endif
766 case 'A':
767 if (modifier != 0)
768 goto bad_format;
769 if (change_case)
771 to_uppcase = 1;
772 to_lowcase = 0;
774 #if defined _NL_CURRENT || !HAVE_STRFTIME
775 cpy (STRLEN (f_wkday), f_wkday);
776 break;
777 #else
778 goto underlying_strftime;
779 #endif
781 case L_('b'):
782 case L_('h'):
783 if (change_case)
785 to_uppcase = 1;
786 to_lowcase = 0;
788 if (modifier != 0)
789 goto bad_format;
790 #if defined _NL_CURRENT || !HAVE_STRFTIME
791 cpy (am_len, a_month);
792 break;
793 #else
794 goto underlying_strftime;
795 #endif
797 case L_('B'):
798 if (modifier != 0)
799 goto bad_format;
800 if (change_case)
802 to_uppcase = 1;
803 to_lowcase = 0;
805 #if defined _NL_CURRENT || !HAVE_STRFTIME
806 cpy (STRLEN (f_month), f_month);
807 break;
808 #else
809 goto underlying_strftime;
810 #endif
812 case L_('c'):
813 if (modifier == L_('O'))
814 goto bad_format;
815 #ifdef _NL_CURRENT
816 if (! (modifier == 'E'
817 && (*(subfmt =
818 (const CHAR_T *) _NL_CURRENT (LC_TIME,
819 NLW(ERA_D_T_FMT)))
820 != '\0')))
821 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
822 #else
823 # if HAVE_STRFTIME
824 goto underlying_strftime;
825 # else
826 subfmt = L_("%a %b %e %H:%M:%S %Y");
827 # endif
828 #endif
830 subformat:
832 CHAR_T *old_start = p;
833 size_t len = my_strftime (NULL, (size_t) -1, subfmt,
834 tp ut_argument LOCALE_ARG);
835 add (len, my_strftime (p, maxsize - i, subfmt,
836 tp ut_argument LOCALE_ARG));
838 if (to_uppcase)
839 while (old_start < p)
841 *old_start = TOUPPER ((UCHAR_T) *old_start);
842 ++old_start;
845 break;
847 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
848 underlying_strftime:
850 /* The relevant information is available only via the
851 underlying strftime implementation, so use that. */
852 char ufmt[4];
853 char *u = ufmt;
854 char ubuf[1024]; /* enough for any single format in practice */
855 size_t len;
856 /* Make sure we're calling the actual underlying strftime.
857 In some cases, config.h contains something like
858 "#define strftime rpl_strftime". */
859 # ifdef strftime
860 # undef strftime
861 size_t strftime ();
862 # endif
864 *u++ = '%';
865 if (modifier != 0)
866 *u++ = modifier;
867 *u++ = format_char;
868 *u = '\0';
869 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
870 if (len == 0 && ubuf[0] != '\0')
871 return 0;
872 cpy (len, ubuf);
874 break;
875 #endif
877 case L_('C'):
878 if (modifier == L_('O'))
879 goto bad_format;
880 if (modifier == L_('E'))
882 #if HAVE_STRUCT_ERA_ENTRY
883 struct era_entry *era = _nl_get_era_entry (tp);
884 if (era)
886 # ifdef COMPILE_WIDE
887 size_t len = __wcslen (era->era_wname);
888 cpy (len, era->era_wname);
889 # else
890 size_t len = strlen (era->era_name);
891 cpy (len, era->era_name);
892 # endif
893 break;
895 #else
896 # if HAVE_STRFTIME
897 goto underlying_strftime;
898 # endif
899 #endif
903 int year = tp->tm_year + TM_YEAR_BASE;
904 DO_NUMBER (1, year / 100 - (year % 100 < 0));
907 case L_('x'):
908 if (modifier == L_('O'))
909 goto bad_format;
910 #ifdef _NL_CURRENT
911 if (! (modifier == L_('E')
912 && (*(subfmt =
913 (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
914 != L_('\0'))))
915 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
916 goto subformat;
917 #else
918 # if HAVE_STRFTIME
919 goto underlying_strftime;
920 # else
921 /* Fall through. */
922 # endif
923 #endif
924 case L_('D'):
925 if (modifier != 0)
926 goto bad_format;
927 subfmt = L_("%m/%d/%y");
928 goto subformat;
930 case L_('d'):
931 if (modifier == L_('E'))
932 goto bad_format;
934 DO_NUMBER (2, tp->tm_mday);
936 case L_('e'):
937 if (modifier == L_('E'))
938 goto bad_format;
940 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
942 /* All numeric formats set DIGITS and NUMBER_VALUE and then
943 jump to one of these two labels. */
945 do_number_spacepad:
946 /* Force `_' flag unless overwritten by `0' flag. */
947 if (pad != L_('0'))
948 pad = L_('_');
950 do_number:
951 /* Format the number according to the MODIFIER flag. */
953 if (modifier == L_('O') && 0 <= number_value)
955 #ifdef _NL_CURRENT
956 /* Get the locale specific alternate representation of
957 the number NUMBER_VALUE. If none exist NULL is returned. */
958 # ifdef COMPILE_WIDE
959 const wchar_t *cp = _nl_get_walt_digit (number_value);
960 # else
961 const char *cp = _nl_get_alt_digit (number_value);
962 # endif
964 if (cp != NULL)
966 size_t digitlen = STRLEN (cp);
967 if (digitlen != 0)
969 cpy (digitlen, cp);
970 break;
973 #else
974 # if HAVE_STRFTIME
975 goto underlying_strftime;
976 # endif
977 #endif
980 unsigned int u = number_value;
982 bufp = buf + sizeof (buf) / sizeof (buf[0]);
983 negative_number = number_value < 0;
985 if (negative_number)
986 u = -u;
989 *--bufp = u % 10 + L_('0');
990 while ((u /= 10) != 0);
993 do_number_sign_and_padding:
994 if (negative_number)
995 *--bufp = L_('-');
997 if (pad != L_('-'))
999 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
1000 - bufp);
1002 if (pad == L_('_'))
1004 while (0 < padding--)
1005 *--bufp = L_(' ');
1007 else
1009 bufp += negative_number;
1010 while (0 < padding--)
1011 *--bufp = L_('0');
1012 if (negative_number)
1013 *--bufp = L_('-');
1017 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1018 break;
1020 case L_('F'):
1021 if (modifier != 0)
1022 goto bad_format;
1023 subfmt = L_("%Y-%m-%d");
1024 goto subformat;
1026 case L_('H'):
1027 if (modifier == L_('E'))
1028 goto bad_format;
1030 DO_NUMBER (2, tp->tm_hour);
1032 case L_('I'):
1033 if (modifier == L_('E'))
1034 goto bad_format;
1036 DO_NUMBER (2, hour12);
1038 case L_('k'): /* GNU extension. */
1039 if (modifier == L_('E'))
1040 goto bad_format;
1042 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1044 case L_('l'): /* GNU extension. */
1045 if (modifier == L_('E'))
1046 goto bad_format;
1048 DO_NUMBER_SPACEPAD (2, hour12);
1050 case L_('j'):
1051 if (modifier == L_('E'))
1052 goto bad_format;
1054 DO_NUMBER (3, 1 + tp->tm_yday);
1056 case L_('M'):
1057 if (modifier == L_('E'))
1058 goto bad_format;
1060 DO_NUMBER (2, tp->tm_min);
1062 case L_('m'):
1063 if (modifier == L_('E'))
1064 goto bad_format;
1066 DO_NUMBER (2, tp->tm_mon + 1);
1068 case L_('n'):
1069 add (1, *p = L_('\n'));
1070 break;
1072 case L_('P'):
1073 to_lowcase = 1;
1074 #if !defined _NL_CURRENT && HAVE_STRFTIME
1075 format_char = L_('p');
1076 #endif
1077 /* FALLTHROUGH */
1079 case L_('p'):
1080 if (change_case)
1082 to_uppcase = 0;
1083 to_lowcase = 1;
1085 #if defined _NL_CURRENT || !HAVE_STRFTIME
1086 cpy (ap_len, ampm);
1087 break;
1088 #else
1089 goto underlying_strftime;
1090 #endif
1092 case L_('R'):
1093 subfmt = L_("%H:%M");
1094 goto subformat;
1096 case L_('r'):
1097 #ifdef _NL_CURRENT
1098 if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1099 NLW(T_FMT_AMPM)))
1100 == L_('\0'))
1101 #endif
1102 subfmt = L_("%I:%M:%S %p");
1103 goto subformat;
1105 case L_('S'):
1106 if (modifier == L_('E'))
1107 goto bad_format;
1109 DO_NUMBER (2, tp->tm_sec);
1111 case L_('s'): /* GNU extension. */
1113 struct tm ltm;
1114 time_t t;
1116 ltm = *tp;
1117 t = mktime (&ltm);
1119 /* Generate string value for T using time_t arithmetic;
1120 this works even if sizeof (long) < sizeof (time_t). */
1122 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1123 negative_number = t < 0;
1127 int d = t % 10;
1128 t /= 10;
1130 if (negative_number)
1132 d = -d;
1134 /* Adjust if division truncates to minus infinity. */
1135 if (0 < -1 % 10 && d < 0)
1137 t++;
1138 d += 10;
1142 *--bufp = d + L_('0');
1144 while (t != 0);
1146 digits = 1;
1147 goto do_number_sign_and_padding;
1150 case L_('X'):
1151 if (modifier == L_('O'))
1152 goto bad_format;
1153 #ifdef _NL_CURRENT
1154 if (! (modifier == L_('E')
1155 && (*(subfmt =
1156 (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1157 != L_('\0'))))
1158 subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1159 goto subformat;
1160 #else
1161 # if HAVE_STRFTIME
1162 goto underlying_strftime;
1163 # else
1164 /* Fall through. */
1165 # endif
1166 #endif
1167 case L_('T'):
1168 subfmt = L_("%H:%M:%S");
1169 goto subformat;
1171 case L_('t'):
1172 add (1, *p = L_('\t'));
1173 break;
1175 case L_('u'):
1176 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1178 case L_('U'):
1179 if (modifier == L_('E'))
1180 goto bad_format;
1182 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1184 case L_('V'):
1185 case L_('g'):
1186 case L_('G'):
1187 if (modifier == L_('E'))
1188 goto bad_format;
1190 int year = tp->tm_year + TM_YEAR_BASE;
1191 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1193 if (days < 0)
1195 /* This ISO week belongs to the previous year. */
1196 year--;
1197 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1198 tp->tm_wday);
1200 else
1202 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1203 tp->tm_wday);
1204 if (0 <= d)
1206 /* This ISO week belongs to the next year. */
1207 year++;
1208 days = d;
1212 switch (*f)
1214 case L_('g'):
1215 DO_NUMBER (2, (year % 100 + 100) % 100);
1217 case L_('G'):
1218 DO_NUMBER (1, year);
1220 default:
1221 DO_NUMBER (2, days / 7 + 1);
1225 case L_('W'):
1226 if (modifier == L_('E'))
1227 goto bad_format;
1229 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1231 case L_('w'):
1232 if (modifier == L_('E'))
1233 goto bad_format;
1235 DO_NUMBER (1, tp->tm_wday);
1237 case L_('Y'):
1238 if (modifier == 'E')
1240 #if HAVE_STRUCT_ERA_ENTRY
1241 struct era_entry *era = _nl_get_era_entry (tp);
1242 if (era)
1244 # ifdef COMPILE_WIDE
1245 subfmt = era->era_wformat;
1246 # else
1247 subfmt = era->era_format;
1248 # endif
1249 goto subformat;
1251 #else
1252 # if HAVE_STRFTIME
1253 goto underlying_strftime;
1254 # endif
1255 #endif
1257 if (modifier == L_('O'))
1258 goto bad_format;
1259 else
1260 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1262 case L_('y'):
1263 if (modifier == L_('E'))
1265 #if HAVE_STRUCT_ERA_ENTRY
1266 struct era_entry *era = _nl_get_era_entry (tp);
1267 if (era)
1269 int delta = tp->tm_year - era->start_date[0];
1270 DO_NUMBER (1, (era->offset
1271 + delta * era->absolute_direction));
1273 #else
1274 # if HAVE_STRFTIME
1275 goto underlying_strftime;
1276 # endif
1277 #endif
1279 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1281 case L_('Z'):
1282 if (change_case)
1284 to_uppcase = 0;
1285 to_lowcase = 1;
1288 #if HAVE_TZNAME
1289 /* The tzset() call might have changed the value. */
1290 if (!(zone && *zone) && tp->tm_isdst >= 0)
1291 zone = tzname[tp->tm_isdst];
1292 #endif
1293 if (! zone)
1294 zone = "";
1296 #ifdef COMPILE_WIDE
1298 /* The zone string is always given in multibyte form. We have
1299 to transform it first. */
1300 wchar_t *wczone;
1301 size_t len;
1302 widen (zone, wczone, len);
1303 cpy (len, wczone);
1305 #else
1306 cpy (strlen (zone), zone);
1307 #endif
1308 break;
1310 case L_('z'):
1311 if (tp->tm_isdst < 0)
1312 break;
1315 int diff;
1316 #if HAVE_TM_GMTOFF
1317 diff = tp->tm_gmtoff;
1318 #else
1319 if (ut)
1320 diff = 0;
1321 else
1323 struct tm gtm;
1324 struct tm ltm;
1325 time_t lt;
1327 ltm = *tp;
1328 lt = mktime (&ltm);
1330 if (lt == (time_t) -1)
1332 /* mktime returns -1 for errors, but -1 is also a
1333 valid time_t value. Check whether an error really
1334 occurred. */
1335 struct tm tm;
1337 if (! my_strftime_localtime_r (&lt, &tm)
1338 || ((ltm.tm_sec ^ tm.tm_sec)
1339 | (ltm.tm_min ^ tm.tm_min)
1340 | (ltm.tm_hour ^ tm.tm_hour)
1341 | (ltm.tm_mday ^ tm.tm_mday)
1342 | (ltm.tm_mon ^ tm.tm_mon)
1343 | (ltm.tm_year ^ tm.tm_year)))
1344 break;
1347 if (! my_strftime_gmtime_r (&lt, &gtm))
1348 break;
1350 diff = tm_diff (&ltm, &gtm);
1352 #endif
1354 if (diff < 0)
1356 add (1, *p = L_('-'));
1357 diff = -diff;
1359 else
1360 add (1, *p = L_('+'));
1362 diff /= 60;
1363 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1366 case L_('\0'): /* GNU extension: % at end of format. */
1367 --f;
1368 /* Fall through. */
1369 default:
1370 /* Unknown format; output the format, including the '%',
1371 since this is most likely the right thing to do if a
1372 multibyte string has been misparsed. */
1373 bad_format:
1375 int flen;
1376 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1377 continue;
1378 cpy (flen, &f[1 - flen]);
1380 break;
1384 if (p && maxsize != 0)
1385 *p = L_('\0');
1386 return i;
1388 #if defined _LIBC && !defined USE_IN_EXTENDED_LOCALE_MODEL
1389 libc_hidden_def (my_strftime)
1390 #endif
1393 #ifdef emacs
1394 /* For Emacs we have a separate interface which corresponds to the normal
1395 strftime function and does not have the extra information whether the
1396 TP arguments comes from a `gmtime' call or not. */
1397 size_t
1398 emacs_strftime (s, maxsize, format, tp)
1399 char *s;
1400 size_t maxsize;
1401 const char *format;
1402 const struct tm *tp;
1404 return my_strftime (s, maxsize, format, tp, 0);
1406 #endif