Revert changes of 2003-03-03 and 2003-05-28.
[emacs.git] / src / strftime.c
blobecfed2af3986793b4e4326bb6a16a8528cd9b20a
1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000,2003
2 Free Software Foundation, Inc.
4 This file is part of the GNU Emacs.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #ifdef _LIBC
26 # define HAVE_LIMITS_H 1
27 # define HAVE_MBLEN 1
28 # define HAVE_MBRLEN 1
29 # define HAVE_STRUCT_ERA_ENTRY 1
30 # define HAVE_TM_GMTOFF 1
31 # define HAVE_TM_ZONE 1
32 # define HAVE_TZNAME 1
33 # define HAVE_TZSET 1
34 # define MULTIBYTE_IS_FORMAT_SAFE 1
35 # define STDC_HEADERS 1
36 # include "../locale/localeinfo.h"
37 #endif
39 #if defined emacs && !defined HAVE_BCOPY
40 # define HAVE_MEMCPY 1
41 #endif
43 #include <ctype.h>
44 #include <sys/types.h> /* Some systems define `time_t' here. */
46 #ifdef TIME_WITH_SYS_TIME
47 # include <sys/time.h>
48 # include <time.h>
49 #else
50 # ifdef HAVE_SYS_TIME_H
51 # include <sys/time.h>
52 # else
53 # include <time.h>
54 # endif
55 #endif
56 #if HAVE_TZNAME
57 #ifndef USE_CRT_DLL
58 extern char *tzname[];
59 #endif
60 #endif
62 /* Do multibyte processing if multibytes are supported, unless
63 multibyte sequences are safe in formats. Multibyte sequences are
64 safe if they cannot contain byte sequences that look like format
65 conversion specifications. The GNU C Library uses UTF8 multibyte
66 encoding, which is safe for formats, but strftime.c can be used
67 with other C libraries that use unsafe encodings. */
68 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
70 #if DO_MULTIBYTE
71 # if HAVE_MBRLEN
72 # include <wchar.h>
73 # if __hpux
74 # include <sys/_mbstate_t.h>
75 # endif
76 # if !defined (mbsinit) && !defined (HAVE_MBSINIT)
77 # define mbsinit(ps) 1
78 # endif /* !defined (mbsinit) && !defined (HAVE_MBSINIT) */
79 # else
80 /* Simulate mbrlen with mblen as best we can. */
81 # define mbstate_t int
82 # define mbrlen(s, n, ps) mblen (s, n)
83 # define mbsinit(ps) (*(ps) == 0)
84 # endif
85 static const mbstate_t mbstate_zero;
86 #endif
88 #ifdef HAVE_LIMITS_H
89 # include <limits.h>
90 #endif
92 #ifdef STDC_HEADERS
93 # include <stddef.h>
94 # include <stdlib.h>
95 #else
96 # ifndef HAVE_MEMCPY
97 # define memcpy(d, s, n) bcopy ((s), (d), (n))
98 # endif
99 #endif
101 #ifdef COMPILE_WIDE
102 # include <endian.h>
103 # define CHAR_T wchar_t
104 # define UCHAR_T unsigned int
105 # define L_(Str) L##Str
106 # define NLW(Sym) _NL_W##Sym
108 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
109 # define STRLEN(s) __wcslen (s)
111 #else
112 # define CHAR_T char
113 # define UCHAR_T unsigned char
114 # define L_(Str) Str
115 # define NLW(Sym) Sym
117 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
118 # define MEMCPY(d, s, n) bcopy ((s), (d), (n))
119 # else
120 # define MEMCPY(d, s, n) memcpy ((d), (s), (n))
121 # endif
122 # define STRLEN(s) strlen (s)
124 # ifdef _LIBC
125 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
126 # else
127 # ifndef HAVE_MEMPCPY
128 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
129 # endif
130 # endif
131 #endif
133 #ifndef __P
134 # if defined emacs && defined PROTOTYPES
135 # define __P(args) args
136 # elif defined __GNUC__ || (defined __STDC__ && __STDC__)
137 # define __P(args) args
138 # else
139 # define __P(args) ()
140 # endif /* GCC. */
141 #endif /* Not __P. */
143 #ifndef PTR
144 # ifdef __STDC__
145 # define PTR void *
146 # else
147 # define PTR char *
148 # endif
149 #endif
151 #ifndef CHAR_BIT
152 # define CHAR_BIT 8
153 #endif
155 #ifndef NULL
156 # define NULL 0
157 #endif
159 #define TYPE_SIGNED(t) ((t) -1 < 0)
161 /* Bound on length of the string representing an integer value of type t.
162 Subtract one for the sign bit if t is signed;
163 302 / 1000 is log10 (2) rounded up;
164 add one for integer division truncation;
165 add one more for a minus sign if t is signed. */
166 #define INT_STRLEN_BOUND(t) \
167 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
169 #define TM_YEAR_BASE 1900
171 #ifndef __isleap
172 /* Nonzero if YEAR is a leap year (every 4 years,
173 except every 100th isn't, and every 400th is). */
174 # define __isleap(year) \
175 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
176 #endif
179 #ifdef _LIBC
180 # define my_strftime_gmtime_r __gmtime_r
181 # define my_strftime_localtime_r __localtime_r
182 # define tzname __tzname
183 # define tzset __tzset
184 #else
186 /* If we're a strftime substitute in a GNU program, then prefer gmtime
187 to gmtime_r, since many gmtime_r implementations are buggy.
188 Similarly for localtime_r. */
190 # if ! HAVE_TM_GMTOFF
191 static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
192 static struct tm *
193 my_strftime_gmtime_r (t, tp)
194 const time_t *t;
195 struct tm *tp;
197 struct tm *l = gmtime (t);
198 if (! l)
199 return 0;
200 *tp = *l;
201 return tp;
204 static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
205 static struct tm *
206 my_strftime_localtime_r (t, tp)
207 const time_t *t;
208 struct tm *tp;
210 struct tm *l = localtime (t);
211 if (! l)
212 return 0;
213 *tp = *l;
214 return tp;
216 # endif /* ! HAVE_TM_GMTOFF */
218 #endif /* ! defined _LIBC */
221 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
222 /* Some systems lack the `memset' function and we don't want to
223 introduce additional dependencies. */
224 /* The SGI compiler reportedly barfs on the trailing null
225 if we use a string constant as the initializer. 28 June 1997, rms. */
226 static const CHAR_T spaces[16] = /* " " */
228 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
229 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
231 static const CHAR_T zeroes[16] = /* "0000000000000000" */
233 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
234 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
237 # define memset_space(P, Len) \
238 do { \
239 int _len = (Len); \
241 do \
243 int _this = _len > 16 ? 16 : _len; \
244 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
245 _len -= _this; \
247 while (_len > 0); \
248 } while (0)
250 # define memset_zero(P, Len) \
251 do { \
252 int _len = (Len); \
254 do \
256 int _this = _len > 16 ? 16 : _len; \
257 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
258 _len -= _this; \
260 while (_len > 0); \
261 } while (0)
262 #else
263 # ifdef COMPILE_WIDE
264 # define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
265 # define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
266 # else
267 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
268 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
269 # endif
270 #endif
272 #define add(n, f) \
273 do \
275 int _n = (n); \
276 int _delta = width - _n; \
277 int _incr = _n + (_delta > 0 ? _delta : 0); \
278 if (i + _incr >= maxsize) \
279 return 0; \
280 if (p) \
282 if (_delta > 0) \
284 if (pad == L_('0')) \
285 memset_zero (p, _delta); \
286 else \
287 memset_space (p, _delta); \
289 f; \
290 p += _n; \
292 i += _incr; \
293 } while (0)
295 #define cpy(n, s) \
296 add ((n), \
297 if (to_lowcase) \
298 memcpy_lowcase (p, (s), _n); \
299 else if (to_uppcase) \
300 memcpy_uppcase (p, (s), _n); \
301 else \
302 MEMCPY ((PTR) p, (PTR) (s), _n))
304 #ifdef COMPILE_WIDE
305 # define widen(os, ws, l) \
307 mbstate_t __st; \
308 const char *__s = os; \
309 memset (&__st, '\0', sizeof (__st)); \
310 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
311 ws = alloca ((l + 1) * sizeof (wchar_t)); \
312 (void) __mbsrtowcs (ws, &__s, l, &__st); \
314 #endif
317 #ifdef COMPILE_WIDE
318 # define TOUPPER(Ch) towupper (Ch)
319 # define TOLOWER(Ch) towlower (Ch)
320 #else
321 # ifdef _LIBC
322 # define TOUPPER(Ch) toupper (Ch)
323 # define TOLOWER(Ch) tolower (Ch)
324 # else
325 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
326 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
327 # endif
328 #endif
329 /* We don't use `isdigit' here since the locale dependent
330 interpretation is not what we want here. We only need to accept
331 the arabic digits in the ASCII range. One day there is perhaps a
332 more reliable way to accept other sets of digits. */
333 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
335 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
336 size_t len));
338 static CHAR_T *
339 memcpy_lowcase (dest, src, len)
340 CHAR_T *dest;
341 const CHAR_T *src;
342 size_t len;
344 while (len-- > 0)
345 dest[len] = TOLOWER ((UCHAR_T) src[len]);
346 return dest;
349 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
350 size_t len));
352 static CHAR_T *
353 memcpy_uppcase (dest, src, len)
354 CHAR_T *dest;
355 const CHAR_T *src;
356 size_t len;
358 while (len-- > 0)
359 dest[len] = TOUPPER ((UCHAR_T) src[len]);
360 return dest;
364 #if ! HAVE_TM_GMTOFF
365 /* Yield the difference between *A and *B,
366 measured in seconds, ignoring leap seconds. */
367 # define tm_diff ftime_tm_diff
368 static int tm_diff __P ((const struct tm *, const struct tm *));
369 static int
370 tm_diff (a, b)
371 const struct tm *a;
372 const struct tm *b;
374 /* Compute intervening leap days correctly even if year is negative.
375 Take care to avoid int overflow in leap day calculations,
376 but it's OK to assume that A and B are close to each other. */
377 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
378 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
379 int a100 = a4 / 25 - (a4 % 25 < 0);
380 int b100 = b4 / 25 - (b4 % 25 < 0);
381 int a400 = a100 >> 2;
382 int b400 = b100 >> 2;
383 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
384 int years = a->tm_year - b->tm_year;
385 int days = (365 * years + intervening_leap_days
386 + (a->tm_yday - b->tm_yday));
387 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
388 + (a->tm_min - b->tm_min))
389 + (a->tm_sec - b->tm_sec));
391 #endif /* ! HAVE_TM_GMTOFF */
395 /* The number of days from the first day of the first ISO week of this
396 year to the year day YDAY with week day WDAY. ISO weeks start on
397 Monday; the first ISO week has the year's first Thursday. YDAY may
398 be as small as YDAY_MINIMUM. */
399 #define ISO_WEEK_START_WDAY 1 /* Monday */
400 #define ISO_WEEK1_WDAY 4 /* Thursday */
401 #define YDAY_MINIMUM (-366)
402 static int iso_week_days __P ((int, int));
403 #ifdef __GNUC__
404 __inline__
405 #endif
406 static int
407 iso_week_days (yday, wday)
408 int yday;
409 int wday;
411 /* Add enough to the first operand of % to make it nonnegative. */
412 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
413 return (yday
414 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
415 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
419 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
420 static CHAR_T const weekday_name[][10] =
422 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
423 L_("Thursday"), L_("Friday"), L_("Saturday")
425 static CHAR_T const month_name[][10] =
427 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
428 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
429 L_("November"), L_("December")
431 #endif
434 #ifdef emacs
435 # define my_strftime emacs_strftimeu
436 # define ut_argument , ut
437 # define ut_argument_spec int ut;
438 # define ut_argument_spec_iso , int ut
439 #else
440 # ifdef COMPILE_WIDE
441 # define my_strftime wcsftime
442 # else
443 # define my_strftime strftime
444 # endif
445 # define ut_argument
446 # define ut_argument_spec
447 # define ut_argument_spec_iso
448 /* We don't have this information in general. */
449 # define ut 0
450 #endif
452 #if !defined _LIBC && !defined(WINDOWSNT) && HAVE_TZNAME && HAVE_TZSET
453 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
454 Work around this bug by copying *tp before it might be munged. */
455 size_t _strftime_copytm __P ((char *, size_t, const char *,
456 const struct tm * ut_argument_spec_iso));
457 size_t
458 my_strftime (s, maxsize, format, tp ut_argument)
459 CHAR_T *s;
460 size_t maxsize;
461 const CHAR_T *format;
462 const struct tm *tp;
463 ut_argument_spec
465 struct tm tmcopy;
466 tmcopy = *tp;
467 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
469 # undef my_strftime
470 # define my_strftime _strftime_copytm
471 #endif
474 /* Write information from TP into S according to the format
475 string FORMAT, writing no more that MAXSIZE characters
476 (including the terminating '\0') and returning number of
477 characters written. If S is NULL, nothing will be written
478 anywhere, so to determine how many characters would be
479 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
480 size_t
481 my_strftime (s, maxsize, format, tp ut_argument)
482 CHAR_T *s;
483 size_t maxsize;
484 const CHAR_T *format;
485 const struct tm *tp;
486 ut_argument_spec
488 int hour12 = tp->tm_hour;
489 #ifdef _NL_CURRENT
490 /* We cannot make the following values variables since we must delay
491 the evaluation of these values until really needed since some
492 expressions might not be valid in every situation. The `struct tm'
493 might be generated by a strptime() call that initialized
494 only a few elements. Dereference the pointers only if the format
495 requires this. Then it is ok to fail if the pointers are invalid. */
496 # define a_wkday \
497 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
498 # define f_wkday \
499 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
500 # define a_month \
501 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
502 # define f_month \
503 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
504 # define ampm \
505 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
506 ? NLW(PM_STR) : NLW(AM_STR)))
508 # define aw_len STRLEN (a_wkday)
509 # define am_len STRLEN (a_month)
510 # define ap_len STRLEN (ampm)
511 #else
512 # if !HAVE_STRFTIME
513 # define f_wkday (weekday_name[tp->tm_wday])
514 # define f_month (month_name[tp->tm_mon])
515 # define a_wkday f_wkday
516 # define a_month f_month
517 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
519 size_t aw_len = 3;
520 size_t am_len = 3;
521 size_t ap_len = 2;
522 # endif
523 #endif
524 const char *zone;
525 size_t i = 0;
526 CHAR_T *p = s;
527 const CHAR_T *f;
529 zone = NULL;
530 #if HAVE_TM_ZONE
531 /* The POSIX test suite assumes that setting
532 the environment variable TZ to a new value before calling strftime()
533 will influence the result (the %Z format) even if the information in
534 TP is computed with a totally different time zone.
535 This is bogus: though POSIX allows bad behavior like this,
536 POSIX does not require it. Do the right thing instead. */
537 zone = (const char *) tp->tm_zone;
538 #endif
539 #if HAVE_TZNAME
540 if (ut)
542 if (! (zone && *zone))
543 zone = "UTC";
545 else
547 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
548 time zone names contained in the external variable `tzname' shall
549 be set as if the tzset() function had been called. */
550 # if HAVE_TZSET
551 tzset ();
552 # endif
554 #endif
556 if (hour12 > 12)
557 hour12 -= 12;
558 else
559 if (hour12 == 0)
560 hour12 = 12;
562 for (f = format; *f != '\0'; ++f)
564 int pad = 0; /* Padding for number ('-', '_', or 0). */
565 int modifier; /* Field modifier ('E', 'O', or 0). */
566 int digits; /* Max digits for numeric format. */
567 int number_value; /* Numeric value to be printed. */
568 int negative_number; /* 1 if the number is negative. */
569 const CHAR_T *subfmt;
570 CHAR_T *bufp;
571 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
572 ? INT_STRLEN_BOUND (time_t)
573 : INT_STRLEN_BOUND (int))];
574 int width = -1;
575 int to_lowcase = 0;
576 int to_uppcase = 0;
577 int change_case = 0;
578 int format_char;
580 #if DO_MULTIBYTE && !defined COMPILE_WIDE
581 switch (*f)
583 case L_('%'):
584 break;
586 case L_('\b'): case L_('\t'): case L_('\n'):
587 case L_('\v'): case L_('\f'): case L_('\r'):
588 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
589 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
590 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
591 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
592 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
593 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
594 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
595 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
596 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
597 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
598 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
599 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
600 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
601 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
602 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
603 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
604 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
605 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
606 case L_('~'):
607 /* The C Standard requires these 97 characters (plus '%', `\a') to
608 be in the basic execution character set. None of these
609 characters can start a multibyte sequence, so they need
610 not be analyzed further. Some old compilers object to
611 `\a', so don't bother optimizing for it. */
612 add (1, *p = *f);
613 continue;
615 default:
616 /* Copy this multibyte sequence until we reach its end, find
617 an error, or come back to the initial shift state. */
619 mbstate_t mbstate = mbstate_zero;
620 size_t len = 0;
624 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
626 if (bytes == 0)
627 break;
629 if (bytes == (size_t) -2)
631 len += strlen (f + len);
632 break;
635 if (bytes == (size_t) -1)
637 len++;
638 break;
641 len += bytes;
643 while (! mbsinit (&mbstate));
645 cpy (len, f);
646 f += len - 1;
647 continue;
651 #else /* ! DO_MULTIBYTE */
653 /* Either multibyte encodings are not supported, they are
654 safe for formats, so any non-'%' byte can be copied through,
655 or this is the wide character version. */
656 if (*f != L_('%'))
658 add (1, *p = *f);
659 continue;
662 #endif /* ! DO_MULTIBYTE */
664 /* Check for flags that can modify a format. */
665 while (1)
667 switch (*++f)
669 /* This influences the number formats. */
670 case L_('_'):
671 case L_('-'):
672 case L_('0'):
673 pad = *f;
674 continue;
676 /* This changes textual output. */
677 case L_('^'):
678 to_uppcase = 1;
679 continue;
680 case L_('#'):
681 change_case = 1;
682 continue;
684 default:
685 break;
687 break;
690 /* As a GNU extension we allow to specify the field width. */
691 if (ISDIGIT (*f))
693 width = 0;
696 width *= 10;
697 width += *f - L_('0');
698 ++f;
700 while (ISDIGIT (*f));
703 /* Check for modifiers. */
704 switch (*f)
706 case L_('E'):
707 case L_('O'):
708 modifier = *f++;
709 break;
711 default:
712 modifier = 0;
713 break;
716 /* Now do the specified format. */
717 format_char = *f;
718 switch (format_char)
720 #define DO_NUMBER(d, v) \
721 digits = width == -1 ? d : width; \
722 number_value = v; goto do_number
723 #define DO_NUMBER_SPACEPAD(d, v) \
724 digits = width == -1 ? d : width; \
725 number_value = v; goto do_number_spacepad
727 case L_('%'):
728 if (modifier != 0)
729 goto bad_format;
730 add (1, *p = *f);
731 break;
733 case L_('a'):
734 if (modifier != 0)
735 goto bad_format;
736 if (change_case)
738 to_uppcase = 1;
739 to_lowcase = 0;
741 #if defined _NL_CURRENT || !HAVE_STRFTIME
742 cpy (aw_len, a_wkday);
743 break;
744 #else
745 goto underlying_strftime;
746 #endif
748 case 'A':
749 if (modifier != 0)
750 goto bad_format;
751 if (change_case)
753 to_uppcase = 1;
754 to_lowcase = 0;
756 #if defined _NL_CURRENT || !HAVE_STRFTIME
757 cpy (STRLEN (f_wkday), f_wkday);
758 break;
759 #else
760 goto underlying_strftime;
761 #endif
763 case L_('b'):
764 case L_('h'): /* POSIX.2 extension. */
765 if (change_case)
767 to_uppcase = 1;
768 to_lowcase = 0;
770 if (modifier != 0)
771 goto bad_format;
772 #if defined _NL_CURRENT || !HAVE_STRFTIME
773 cpy (am_len, a_month);
774 break;
775 #else
776 goto underlying_strftime;
777 #endif
779 case L_('B'):
780 if (modifier != 0)
781 goto bad_format;
782 if (change_case)
784 to_uppcase = 1;
785 to_lowcase = 0;
787 #if defined _NL_CURRENT || !HAVE_STRFTIME
788 cpy (STRLEN (f_month), f_month);
789 break;
790 #else
791 goto underlying_strftime;
792 #endif
794 case L_('c'):
795 if (modifier == L_('O'))
796 goto bad_format;
797 #ifdef _NL_CURRENT
798 if (! (modifier == 'E'
799 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
800 NLW(ERA_D_T_FMT)))
801 != '\0')))
802 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
803 #else
804 # if HAVE_STRFTIME
805 goto underlying_strftime;
806 # else
807 subfmt = L_("%a %b %e %H:%M:%S %Y");
808 # endif
809 #endif
811 subformat:
813 CHAR_T *old_start = p;
814 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp, 0);
815 add (len, my_strftime (p, maxsize - i, subfmt, tp, 0));
817 if (to_uppcase)
818 while (old_start < p)
820 *old_start = TOUPPER ((UCHAR_T) *old_start);
821 ++old_start;
824 break;
826 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
827 underlying_strftime:
829 /* The relevant information is available only via the
830 underlying strftime implementation, so use that. */
831 char ufmt[4];
832 char *u = ufmt;
833 char ubuf[1024]; /* enough for any single format in practice */
834 size_t len;
835 /* Make sure we're calling the actual underlying strftime.
836 In some cases, config.h contains something like
837 "#define strftime rpl_strftime". */
838 # ifdef strftime
839 # undef strftime
840 size_t strftime ();
841 # endif
843 #ifdef STRFTIME_NO_POSIX2
844 /* Some system libraries do not support the POSIX.2 extensions.
845 In those cases, convert %h to %b, and strip modifiers. */
846 modifier = 0;
847 if (format_char == 'h')
848 format_char = 'b';
849 #endif
850 *u++ = '%';
851 if (modifier != 0)
852 *u++ = modifier;
853 *u++ = format_char;
854 *u = '\0';
855 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
856 if (len == 0 && ubuf[0] != '\0')
857 return 0;
858 cpy (len, ubuf);
860 break;
861 #endif
863 case L_('C'): /* POSIX.2 extension. */
864 if (modifier == L_('O'))
865 goto bad_format;
866 if (modifier == L_('E'))
868 #if HAVE_STRUCT_ERA_ENTRY
869 struct era_entry *era = _nl_get_era_entry (tp);
870 if (era)
872 # ifdef COMPILE_WIDE
873 size_t len = __wcslen (era->era_wname);
874 cpy (len, era->era_wname);
875 # else
876 size_t len = strlen (era->era_name);
877 cpy (len, era->era_name);
878 # endif
879 break;
881 #else
882 # if HAVE_STRFTIME
883 goto underlying_strftime;
884 # endif
885 #endif
889 int year = tp->tm_year + TM_YEAR_BASE;
890 DO_NUMBER (1, year / 100 - (year % 100 < 0));
893 case L_('x'):
894 if (modifier == L_('O'))
895 goto bad_format;
896 #ifdef _NL_CURRENT
897 if (! (modifier == L_('E')
898 && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
899 NLW(ERA_D_FMT)))
900 != L_('\0'))))
901 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
902 goto subformat;
903 #else
904 # if HAVE_STRFTIME
905 goto underlying_strftime;
906 # else
907 /* Fall through. */
908 # endif
909 #endif
910 case L_('D'): /* POSIX.2 extension. */
911 if (modifier != 0)
912 goto bad_format;
913 subfmt = L_("%m/%d/%y");
914 goto subformat;
916 case L_('d'):
917 if (modifier == L_('E'))
918 goto bad_format;
920 DO_NUMBER (2, tp->tm_mday);
922 case L_('e'): /* POSIX.2 extension. */
923 if (modifier == L_('E'))
924 goto bad_format;
926 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
928 /* All numeric formats set DIGITS and NUMBER_VALUE and then
929 jump to one of these two labels. */
931 do_number_spacepad:
932 /* Force `_' flag unless overwritten by `0' flag. */
933 if (pad != L_('0'))
934 pad = L_('_');
936 do_number:
937 /* Format the number according to the MODIFIER flag. */
939 if (modifier == L_('O') && 0 <= number_value)
941 #ifdef _NL_CURRENT
942 /* Get the locale specific alternate representation of
943 the number NUMBER_VALUE. If none exist NULL is returned. */
944 # ifdef COMPILE_WIDE
945 const wchar_t *cp = _nl_get_walt_digit (number_value);
946 # else
947 const char *cp = _nl_get_alt_digit (number_value);
948 # endif
950 if (cp != NULL)
952 size_t digitlen = STRLEN (cp);
953 if (digitlen != 0)
955 cpy (digitlen, cp);
956 break;
959 #else
960 # if HAVE_STRFTIME
961 goto underlying_strftime;
962 # endif
963 #endif
966 unsigned int u = number_value;
968 bufp = buf + sizeof (buf) / sizeof (buf[0]);
969 negative_number = number_value < 0;
971 if (negative_number)
972 u = -u;
975 *--bufp = u % 10 + L_('0');
976 while ((u /= 10) != 0);
979 do_number_sign_and_padding:
980 if (negative_number)
981 *--bufp = L_('-');
983 if (pad != L_('-'))
985 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
986 - bufp);
988 if (pad == L_('_'))
990 while (0 < padding--)
991 *--bufp = L_(' ');
993 else
995 bufp += negative_number;
996 while (0 < padding--)
997 *--bufp = L_('0');
998 if (negative_number)
999 *--bufp = L_('-');
1003 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1004 break;
1006 case L_('F'):
1007 if (modifier != 0)
1008 goto bad_format;
1009 subfmt = L_("%Y-%m-%d");
1010 goto subformat;
1012 case L_('H'):
1013 if (modifier == L_('E'))
1014 goto bad_format;
1016 DO_NUMBER (2, tp->tm_hour);
1018 case L_('I'):
1019 if (modifier == L_('E'))
1020 goto bad_format;
1022 DO_NUMBER (2, hour12);
1024 case L_('k'): /* GNU extension. */
1025 if (modifier == L_('E'))
1026 goto bad_format;
1028 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1030 case L_('l'): /* GNU extension. */
1031 if (modifier == L_('E'))
1032 goto bad_format;
1034 DO_NUMBER_SPACEPAD (2, hour12);
1036 case L_('j'):
1037 if (modifier == L_('E'))
1038 goto bad_format;
1040 DO_NUMBER (3, 1 + tp->tm_yday);
1042 case L_('M'):
1043 if (modifier == L_('E'))
1044 goto bad_format;
1046 DO_NUMBER (2, tp->tm_min);
1048 case L_('m'):
1049 if (modifier == L_('E'))
1050 goto bad_format;
1052 DO_NUMBER (2, tp->tm_mon + 1);
1054 case L_('n'): /* POSIX.2 extension. */
1055 add (1, *p = L_('\n'));
1056 break;
1058 case L_('P'):
1059 to_lowcase = 1;
1060 #if !defined _NL_CURRENT && HAVE_STRFTIME
1061 format_char = L_('p');
1062 #endif
1063 /* FALLTHROUGH */
1065 case L_('p'):
1066 if (change_case)
1068 to_uppcase = 0;
1069 to_lowcase = 1;
1071 #if defined _NL_CURRENT || !HAVE_STRFTIME
1072 cpy (ap_len, ampm);
1073 break;
1074 #else
1075 goto underlying_strftime;
1076 #endif
1078 case L_('R'): /* GNU extension. */
1079 subfmt = L_("%H:%M");
1080 goto subformat;
1082 case L_('r'): /* POSIX.2 extension. */
1083 #ifdef _NL_CURRENT
1084 if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1085 NLW(T_FMT_AMPM))) == L_('\0'))
1086 #endif
1087 subfmt = L_("%I:%M:%S %p");
1088 goto subformat;
1090 case L_('S'):
1091 if (modifier == L_('E'))
1092 goto bad_format;
1094 DO_NUMBER (2, tp->tm_sec);
1096 case L_('s'): /* GNU extension. */
1098 struct tm ltm;
1099 time_t t;
1101 ltm = *tp;
1102 t = mktime (&ltm);
1104 /* Generate string value for T using time_t arithmetic;
1105 this works even if sizeof (long) < sizeof (time_t). */
1107 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1108 negative_number = t < 0;
1112 int d = t % 10;
1113 t /= 10;
1115 if (negative_number)
1117 d = -d;
1119 /* Adjust if division truncates to minus infinity. */
1120 if (0 < -1 % 10 && d < 0)
1122 t++;
1123 d += 10;
1127 *--bufp = d + L_('0');
1129 while (t != 0);
1131 digits = 1;
1132 goto do_number_sign_and_padding;
1135 case L_('X'):
1136 if (modifier == L_('O'))
1137 goto bad_format;
1138 #ifdef _NL_CURRENT
1139 if (! (modifier == L_('E')
1140 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1141 NLW(ERA_T_FMT)))
1142 != L_('\0'))))
1143 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1144 goto subformat;
1145 #else
1146 # if HAVE_STRFTIME
1147 goto underlying_strftime;
1148 # else
1149 /* Fall through. */
1150 # endif
1151 #endif
1152 case L_('T'): /* POSIX.2 extension. */
1153 subfmt = L_("%H:%M:%S");
1154 goto subformat;
1156 case L_('t'): /* POSIX.2 extension. */
1157 add (1, *p = L_('\t'));
1158 break;
1160 case L_('u'): /* POSIX.2 extension. */
1161 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1163 case L_('U'):
1164 if (modifier == L_('E'))
1165 goto bad_format;
1167 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1169 case L_('V'):
1170 case L_('g'): /* GNU extension. */
1171 case L_('G'): /* GNU extension. */
1172 if (modifier == L_('E'))
1173 goto bad_format;
1175 int year = tp->tm_year + TM_YEAR_BASE;
1176 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1178 if (days < 0)
1180 /* This ISO week belongs to the previous year. */
1181 year--;
1182 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1183 tp->tm_wday);
1185 else
1187 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1188 tp->tm_wday);
1189 if (0 <= d)
1191 /* This ISO week belongs to the next year. */
1192 year++;
1193 days = d;
1197 switch (*f)
1199 case L_('g'):
1200 DO_NUMBER (2, (year % 100 + 100) % 100);
1202 case L_('G'):
1203 DO_NUMBER (1, year);
1205 default:
1206 DO_NUMBER (2, days / 7 + 1);
1210 case L_('W'):
1211 if (modifier == L_('E'))
1212 goto bad_format;
1214 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1216 case L_('w'):
1217 if (modifier == L_('E'))
1218 goto bad_format;
1220 DO_NUMBER (1, tp->tm_wday);
1222 case L_('Y'):
1223 if (modifier == 'E')
1225 #if HAVE_STRUCT_ERA_ENTRY
1226 struct era_entry *era = _nl_get_era_entry (tp);
1227 if (era)
1229 # ifdef COMPILE_WIDE
1230 subfmt = era->era_wformat;
1231 # else
1232 subfmt = era->era_format;
1233 # endif
1234 goto subformat;
1236 #else
1237 # if HAVE_STRFTIME
1238 goto underlying_strftime;
1239 # endif
1240 #endif
1242 if (modifier == L_('O'))
1243 goto bad_format;
1244 else
1245 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1247 case L_('y'):
1248 if (modifier == L_('E'))
1250 #if HAVE_STRUCT_ERA_ENTRY
1251 struct era_entry *era = _nl_get_era_entry (tp);
1252 if (era)
1254 int delta = tp->tm_year - era->start_date[0];
1255 DO_NUMBER (1, (era->offset
1256 + delta * era->absolute_direction));
1258 #else
1259 # if HAVE_STRFTIME
1260 goto underlying_strftime;
1261 # endif
1262 #endif
1264 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1266 case L_('Z'):
1267 if (change_case)
1269 to_uppcase = 0;
1270 to_lowcase = 1;
1273 #if HAVE_TZNAME
1274 /* The tzset() call might have changed the value. */
1275 if (!(zone && *zone) && tp->tm_isdst >= 0)
1276 zone = tzname[tp->tm_isdst];
1277 #endif
1278 if (! zone)
1279 zone = ""; /* POSIX.2 requires the empty string here. */
1281 #ifdef COMPILE_WIDE
1283 /* The zone string is always given in multibyte form. We have
1284 to transform it first. */
1285 wchar_t *wczone;
1286 size_t len;
1287 widen (zone, wczone, len);
1288 cpy (len, wczone);
1290 #else
1291 cpy (strlen (zone), zone);
1292 #endif
1293 break;
1295 case L_('z'): /* GNU extension. */
1296 if (tp->tm_isdst < 0)
1297 break;
1300 int diff;
1301 #if HAVE_TM_GMTOFF
1302 diff = tp->tm_gmtoff;
1303 #else
1304 if (ut)
1305 diff = 0;
1306 else
1308 struct tm gtm;
1309 struct tm ltm;
1310 time_t lt;
1312 ltm = *tp;
1313 lt = mktime (&ltm);
1315 if (lt == (time_t) -1)
1317 /* mktime returns -1 for errors, but -1 is also a
1318 valid time_t value. Check whether an error really
1319 occurred. */
1320 struct tm tm;
1322 if (! my_strftime_localtime_r (&lt, &tm)
1323 || ((ltm.tm_sec ^ tm.tm_sec)
1324 | (ltm.tm_min ^ tm.tm_min)
1325 | (ltm.tm_hour ^ tm.tm_hour)
1326 | (ltm.tm_mday ^ tm.tm_mday)
1327 | (ltm.tm_mon ^ tm.tm_mon)
1328 | (ltm.tm_year ^ tm.tm_year)))
1329 break;
1332 if (! my_strftime_gmtime_r (&lt, &gtm))
1333 break;
1335 diff = tm_diff (&ltm, &gtm);
1337 #endif
1339 if (diff < 0)
1341 add (1, *p = L_('-'));
1342 diff = -diff;
1344 else
1345 add (1, *p = L_('+'));
1347 diff /= 60;
1348 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1351 case L_('\0'): /* GNU extension: % at end of format. */
1352 --f;
1353 /* Fall through. */
1354 default:
1355 /* Unknown format; output the format, including the '%',
1356 since this is most likely the right thing to do if a
1357 multibyte string has been misparsed. */
1358 bad_format:
1360 int flen;
1361 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1362 continue;
1363 cpy (flen, &f[1 - flen]);
1365 break;
1369 if (p && maxsize != 0)
1370 *p = L_('\0');
1371 return i;
1375 #ifdef emacs
1376 /* For Emacs we have a separate interface which corresponds to the normal
1377 strftime function and does not have the extra information whether the
1378 TP arguments comes from a `gmtime' call or not. */
1379 size_t
1380 emacs_strftime (s, maxsize, format, tp)
1381 char *s;
1382 size_t maxsize;
1383 const char *format;
1384 const struct tm *tp;
1386 return my_strftime (s, maxsize, format, tp, 0);
1388 #endif