(split-string): Implement specification that splitting on explicit separators
[emacs.git] / src / strftime.c
blobe5953152aa0827f2279597b1f24fd0f88ed924cd
1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
2 This file is part of the GNU Emacs.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 #ifdef _LIBC
24 # define HAVE_LIMITS_H 1
25 # define HAVE_MBLEN 1
26 # define HAVE_MBRLEN 1
27 # define HAVE_STRUCT_ERA_ENTRY 1
28 # define HAVE_TM_GMTOFF 1
29 # define HAVE_TM_ZONE 1
30 # define HAVE_TZNAME 1
31 # define HAVE_TZSET 1
32 # define MULTIBYTE_IS_FORMAT_SAFE 1
33 # define STDC_HEADERS 1
34 # include "../locale/localeinfo.h"
35 #endif
37 #if defined emacs && !defined HAVE_BCOPY
38 # define HAVE_MEMCPY 1
39 #endif
41 #include <ctype.h>
42 #include <sys/types.h> /* Some systems define `time_t' here. */
44 #ifdef TIME_WITH_SYS_TIME
45 # include <sys/time.h>
46 # include <time.h>
47 #else
48 # ifdef HAVE_SYS_TIME_H
49 # include <sys/time.h>
50 # else
51 # include <time.h>
52 # endif
53 #endif
54 #if HAVE_TZNAME
55 #ifndef USE_CRT_DLL
56 extern char *tzname[];
57 #endif
58 #endif
60 /* Do multibyte processing if multibytes are supported, unless
61 multibyte sequences are safe in formats. Multibyte sequences are
62 safe if they cannot contain byte sequences that look like format
63 conversion specifications. The GNU C Library uses UTF8 multibyte
64 encoding, which is safe for formats, but strftime.c can be used
65 with other C libraries that use unsafe encodings. */
66 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
68 #if DO_MULTIBYTE
69 # if HAVE_MBRLEN
70 # include <wchar.h>
71 # if __hpux
72 # include <sys/_mbstate_t.h>
73 # endif
74 # if !defined (mbsinit) && !defined (HAVE_MBSINIT)
75 # define mbsinit(ps) 1
76 # endif /* !defined (mbsinit) && !defined (HAVE_MBSINIT) */
77 # else
78 /* Simulate mbrlen with mblen as best we can. */
79 # define mbstate_t int
80 # define mbrlen(s, n, ps) mblen (s, n)
81 # define mbsinit(ps) (*(ps) == 0)
82 # endif
83 static const mbstate_t mbstate_zero;
84 #endif
86 #ifdef HAVE_LIMITS_H
87 # include <limits.h>
88 #endif
90 #ifdef STDC_HEADERS
91 # include <stddef.h>
92 # include <stdlib.h>
93 #else
94 # ifndef HAVE_MEMCPY
95 # define memcpy(d, s, n) bcopy ((s), (d), (n))
96 # endif
97 #endif
99 #ifdef COMPILE_WIDE
100 # include <endian.h>
101 # define CHAR_T wchar_t
102 # define UCHAR_T unsigned int
103 # define L_(Str) L##Str
104 # define NLW(Sym) _NL_W##Sym
106 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
107 # define STRLEN(s) __wcslen (s)
109 #else
110 # define CHAR_T char
111 # define UCHAR_T unsigned char
112 # define L_(Str) Str
113 # define NLW(Sym) Sym
115 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
116 # define MEMCPY(d, s, n) bcopy ((s), (d), (n))
117 # else
118 # define MEMCPY(d, s, n) memcpy ((d), (s), (n))
119 # endif
120 # define STRLEN(s) strlen (s)
122 # ifdef _LIBC
123 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
124 # else
125 # ifndef HAVE_MEMPCPY
126 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
127 # endif
128 # endif
129 #endif
131 #ifndef __P
132 # if defined emacs && defined PROTOTYPES
133 # define __P(args) args
134 # elif defined __GNUC__ || (defined __STDC__ && __STDC__)
135 # define __P(args) args
136 # else
137 # define __P(args) ()
138 # endif /* GCC. */
139 #endif /* Not __P. */
141 #ifndef PTR
142 # ifdef __STDC__
143 # define PTR void *
144 # else
145 # define PTR char *
146 # endif
147 #endif
149 #ifndef CHAR_BIT
150 # define CHAR_BIT 8
151 #endif
153 #ifndef NULL
154 # define NULL 0
155 #endif
157 #define TYPE_SIGNED(t) ((t) -1 < 0)
159 /* Bound on length of the string representing an integer value of type t.
160 Subtract one for the sign bit if t is signed;
161 302 / 1000 is log10 (2) rounded up;
162 add one for integer division truncation;
163 add one more for a minus sign if t is signed. */
164 #define INT_STRLEN_BOUND(t) \
165 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
167 #define TM_YEAR_BASE 1900
169 #ifndef __isleap
170 /* Nonzero if YEAR is a leap year (every 4 years,
171 except every 100th isn't, and every 400th is). */
172 # define __isleap(year) \
173 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
174 #endif
177 #ifdef _LIBC
178 # define my_strftime_gmtime_r __gmtime_r
179 # define my_strftime_localtime_r __localtime_r
180 # define tzname __tzname
181 # define tzset __tzset
182 #else
184 /* If we're a strftime substitute in a GNU program, then prefer gmtime
185 to gmtime_r, since many gmtime_r implementations are buggy.
186 Similarly for localtime_r. */
188 # if ! HAVE_TM_GMTOFF
189 static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
190 static struct tm *
191 my_strftime_gmtime_r (t, tp)
192 const time_t *t;
193 struct tm *tp;
195 struct tm *l = gmtime (t);
196 if (! l)
197 return 0;
198 *tp = *l;
199 return tp;
201 # endif /* ! HAVE_TM_GMTOFF */
203 static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
204 static struct tm *
205 my_strftime_localtime_r (t, tp)
206 const time_t *t;
207 struct tm *tp;
209 struct tm *l = localtime (t);
210 if (! l)
211 return 0;
212 *tp = *l;
213 return tp;
215 #endif /* ! defined _LIBC */
218 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
219 /* Some systems lack the `memset' function and we don't want to
220 introduce additional dependencies. */
221 /* The SGI compiler reportedly barfs on the trailing null
222 if we use a string constant as the initializer. 28 June 1997, rms. */
223 static const CHAR_T spaces[16] = /* " " */
225 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
226 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
228 static const CHAR_T zeroes[16] = /* "0000000000000000" */
230 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
231 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
234 # define memset_space(P, Len) \
235 do { \
236 int _len = (Len); \
238 do \
240 int _this = _len > 16 ? 16 : _len; \
241 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
242 _len -= _this; \
244 while (_len > 0); \
245 } while (0)
247 # define memset_zero(P, Len) \
248 do { \
249 int _len = (Len); \
251 do \
253 int _this = _len > 16 ? 16 : _len; \
254 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
255 _len -= _this; \
257 while (_len > 0); \
258 } while (0)
259 #else
260 # ifdef COMPILE_WIDE
261 # define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
262 # define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
263 # else
264 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
265 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
266 # endif
267 #endif
269 #define add(n, f) \
270 do \
272 int _n = (n); \
273 int _delta = width - _n; \
274 int _incr = _n + (_delta > 0 ? _delta : 0); \
275 if (i + _incr >= maxsize) \
276 return 0; \
277 if (p) \
279 if (_delta > 0) \
281 if (pad == L_('0')) \
282 memset_zero (p, _delta); \
283 else \
284 memset_space (p, _delta); \
286 f; \
287 p += _n; \
289 i += _incr; \
290 } while (0)
292 #define cpy(n, s) \
293 add ((n), \
294 if (to_lowcase) \
295 memcpy_lowcase (p, (s), _n); \
296 else if (to_uppcase) \
297 memcpy_uppcase (p, (s), _n); \
298 else \
299 MEMCPY ((PTR) p, (PTR) (s), _n))
301 #ifdef COMPILE_WIDE
302 # define widen(os, ws, l) \
304 mbstate_t __st; \
305 const char *__s = os; \
306 memset (&__st, '\0', sizeof (__st)); \
307 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
308 ws = alloca ((l + 1) * sizeof (wchar_t)); \
309 (void) __mbsrtowcs (ws, &__s, l, &__st); \
311 #endif
314 #ifdef COMPILE_WIDE
315 # define TOUPPER(Ch) towupper (Ch)
316 # define TOLOWER(Ch) towlower (Ch)
317 #else
318 # ifdef _LIBC
319 # define TOUPPER(Ch) toupper (Ch)
320 # define TOLOWER(Ch) tolower (Ch)
321 # else
322 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
323 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
324 # endif
325 #endif
326 /* We don't use `isdigit' here since the locale dependent
327 interpretation is not what we want here. We only need to accept
328 the arabic digits in the ASCII range. One day there is perhaps a
329 more reliable way to accept other sets of digits. */
330 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
332 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
333 size_t len));
335 static CHAR_T *
336 memcpy_lowcase (dest, src, len)
337 CHAR_T *dest;
338 const CHAR_T *src;
339 size_t len;
341 while (len-- > 0)
342 dest[len] = TOLOWER ((UCHAR_T) src[len]);
343 return dest;
346 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
347 size_t len));
349 static CHAR_T *
350 memcpy_uppcase (dest, src, len)
351 CHAR_T *dest;
352 const CHAR_T *src;
353 size_t len;
355 while (len-- > 0)
356 dest[len] = TOUPPER ((UCHAR_T) src[len]);
357 return dest;
361 #if ! HAVE_TM_GMTOFF
362 /* Yield the difference between *A and *B,
363 measured in seconds, ignoring leap seconds. */
364 # define tm_diff ftime_tm_diff
365 static int tm_diff __P ((const struct tm *, const struct tm *));
366 static int
367 tm_diff (a, b)
368 const struct tm *a;
369 const struct tm *b;
371 /* Compute intervening leap days correctly even if year is negative.
372 Take care to avoid int overflow in leap day calculations,
373 but it's OK to assume that A and B are close to each other. */
374 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
375 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
376 int a100 = a4 / 25 - (a4 % 25 < 0);
377 int b100 = b4 / 25 - (b4 % 25 < 0);
378 int a400 = a100 >> 2;
379 int b400 = b100 >> 2;
380 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
381 int years = a->tm_year - b->tm_year;
382 int days = (365 * years + intervening_leap_days
383 + (a->tm_yday - b->tm_yday));
384 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
385 + (a->tm_min - b->tm_min))
386 + (a->tm_sec - b->tm_sec));
388 #endif /* ! HAVE_TM_GMTOFF */
392 /* The number of days from the first day of the first ISO week of this
393 year to the year day YDAY with week day WDAY. ISO weeks start on
394 Monday; the first ISO week has the year's first Thursday. YDAY may
395 be as small as YDAY_MINIMUM. */
396 #define ISO_WEEK_START_WDAY 1 /* Monday */
397 #define ISO_WEEK1_WDAY 4 /* Thursday */
398 #define YDAY_MINIMUM (-366)
399 static int iso_week_days __P ((int, int));
400 #ifdef __GNUC__
401 __inline__
402 #endif
403 static int
404 iso_week_days (yday, wday)
405 int yday;
406 int wday;
408 /* Add enough to the first operand of % to make it nonnegative. */
409 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
410 return (yday
411 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
412 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
416 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
417 static CHAR_T const weekday_name[][10] =
419 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
420 L_("Thursday"), L_("Friday"), L_("Saturday")
422 static CHAR_T const month_name[][10] =
424 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
425 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
426 L_("November"), L_("December")
428 #endif
431 #ifdef emacs
432 # define my_strftime emacs_strftimeu
433 # define ut_argument , ut
434 # define ut_argument_spec int ut;
435 # define ut_argument_spec_iso , int ut
436 #else
437 # ifdef COMPILE_WIDE
438 # define my_strftime wcsftime
439 # else
440 # define my_strftime strftime
441 # endif
442 # define ut_argument
443 # define ut_argument_spec
444 # define ut_argument_spec_iso
445 /* We don't have this information in general. */
446 # define ut 0
447 #endif
449 #if !defined _LIBC && !defined(WINDOWSNT) && HAVE_TZNAME && HAVE_TZSET
450 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
451 Work around this bug by copying *tp before it might be munged. */
452 size_t _strftime_copytm __P ((char *, size_t, const char *,
453 const struct tm * ut_argument_spec_iso));
454 size_t
455 my_strftime (s, maxsize, format, tp ut_argument)
456 CHAR_T *s;
457 size_t maxsize;
458 const CHAR_T *format;
459 const struct tm *tp;
460 ut_argument_spec
462 struct tm tmcopy;
463 tmcopy = *tp;
464 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
466 # undef my_strftime
467 # define my_strftime _strftime_copytm
468 #endif
471 /* Write information from TP into S according to the format
472 string FORMAT, writing no more that MAXSIZE characters
473 (including the terminating '\0') and returning number of
474 characters written. If S is NULL, nothing will be written
475 anywhere, so to determine how many characters would be
476 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
477 size_t
478 my_strftime (s, maxsize, format, tp ut_argument)
479 CHAR_T *s;
480 size_t maxsize;
481 const CHAR_T *format;
482 const struct tm *tp;
483 ut_argument_spec
485 int hour12 = tp->tm_hour;
486 #ifdef _NL_CURRENT
487 /* We cannot make the following values variables since we must delay
488 the evaluation of these values until really needed since some
489 expressions might not be valid in every situation. The `struct tm'
490 might be generated by a strptime() call that initialized
491 only a few elements. Dereference the pointers only if the format
492 requires this. Then it is ok to fail if the pointers are invalid. */
493 # define a_wkday \
494 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
495 # define f_wkday \
496 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
497 # define a_month \
498 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
499 # define f_month \
500 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
501 # define ampm \
502 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
503 ? NLW(PM_STR) : NLW(AM_STR)))
505 # define aw_len STRLEN (a_wkday)
506 # define am_len STRLEN (a_month)
507 # define ap_len STRLEN (ampm)
508 #else
509 # if !HAVE_STRFTIME
510 # define f_wkday (weekday_name[tp->tm_wday])
511 # define f_month (month_name[tp->tm_mon])
512 # define a_wkday f_wkday
513 # define a_month f_month
514 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
516 size_t aw_len = 3;
517 size_t am_len = 3;
518 size_t ap_len = 2;
519 # endif
520 #endif
521 const char *zone;
522 size_t i = 0;
523 CHAR_T *p = s;
524 const CHAR_T *f;
526 zone = NULL;
527 #if HAVE_TM_ZONE
528 /* The POSIX test suite assumes that setting
529 the environment variable TZ to a new value before calling strftime()
530 will influence the result (the %Z format) even if the information in
531 TP is computed with a totally different time zone.
532 This is bogus: though POSIX allows bad behavior like this,
533 POSIX does not require it. Do the right thing instead. */
534 zone = (const char *) tp->tm_zone;
535 #endif
536 #if HAVE_TZNAME
537 if (ut)
539 if (! (zone && *zone))
540 zone = "UTC";
542 else
544 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
545 time zone names contained in the external variable `tzname' shall
546 be set as if the tzset() function had been called. */
547 # if HAVE_TZSET
548 tzset ();
549 # endif
551 #endif
553 if (hour12 > 12)
554 hour12 -= 12;
555 else
556 if (hour12 == 0)
557 hour12 = 12;
559 for (f = format; *f != '\0'; ++f)
561 int pad = 0; /* Padding for number ('-', '_', or 0). */
562 int modifier; /* Field modifier ('E', 'O', or 0). */
563 int digits; /* Max digits for numeric format. */
564 int number_value; /* Numeric value to be printed. */
565 int negative_number; /* 1 if the number is negative. */
566 const CHAR_T *subfmt;
567 CHAR_T *bufp;
568 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
569 ? INT_STRLEN_BOUND (time_t)
570 : INT_STRLEN_BOUND (int))];
571 int width = -1;
572 int to_lowcase = 0;
573 int to_uppcase = 0;
574 int change_case = 0;
575 int format_char;
577 #if DO_MULTIBYTE && !defined COMPILE_WIDE
578 switch (*f)
580 case L_('%'):
581 break;
583 case L_('\b'): case L_('\t'): case L_('\n'):
584 case L_('\v'): case L_('\f'): case L_('\r'):
585 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
586 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
587 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
588 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
589 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
590 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
591 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
592 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
593 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
594 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
595 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
596 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
597 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
598 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
599 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
600 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
601 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
602 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
603 case L_('~'):
604 /* The C Standard requires these 97 characters (plus '%', `\a') to
605 be in the basic execution character set. None of these
606 characters can start a multibyte sequence, so they need
607 not be analyzed further. Some old compilers object to
608 `\a', so don't bother optimizing for it. */
609 add (1, *p = *f);
610 continue;
612 default:
613 /* Copy this multibyte sequence until we reach its end, find
614 an error, or come back to the initial shift state. */
616 mbstate_t mbstate = mbstate_zero;
617 size_t len = 0;
621 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
623 if (bytes == 0)
624 break;
626 if (bytes == (size_t) -2)
628 len += strlen (f + len);
629 break;
632 if (bytes == (size_t) -1)
634 len++;
635 break;
638 len += bytes;
640 while (! mbsinit (&mbstate));
642 cpy (len, f);
643 f += len - 1;
644 continue;
648 #else /* ! DO_MULTIBYTE */
650 /* Either multibyte encodings are not supported, they are
651 safe for formats, so any non-'%' byte can be copied through,
652 or this is the wide character version. */
653 if (*f != L_('%'))
655 add (1, *p = *f);
656 continue;
659 #endif /* ! DO_MULTIBYTE */
661 /* Check for flags that can modify a format. */
662 while (1)
664 switch (*++f)
666 /* This influences the number formats. */
667 case L_('_'):
668 case L_('-'):
669 case L_('0'):
670 pad = *f;
671 continue;
673 /* This changes textual output. */
674 case L_('^'):
675 to_uppcase = 1;
676 continue;
677 case L_('#'):
678 change_case = 1;
679 continue;
681 default:
682 break;
684 break;
687 /* As a GNU extension we allow to specify the field width. */
688 if (ISDIGIT (*f))
690 width = 0;
693 width *= 10;
694 width += *f - L_('0');
695 ++f;
697 while (ISDIGIT (*f));
700 /* Check for modifiers. */
701 switch (*f)
703 case L_('E'):
704 case L_('O'):
705 modifier = *f++;
706 break;
708 default:
709 modifier = 0;
710 break;
713 /* Now do the specified format. */
714 format_char = *f;
715 switch (format_char)
717 #define DO_NUMBER(d, v) \
718 digits = width == -1 ? d : width; \
719 number_value = v; goto do_number
720 #define DO_NUMBER_SPACEPAD(d, v) \
721 digits = width == -1 ? d : width; \
722 number_value = v; goto do_number_spacepad
724 case L_('%'):
725 if (modifier != 0)
726 goto bad_format;
727 add (1, *p = *f);
728 break;
730 case L_('a'):
731 if (modifier != 0)
732 goto bad_format;
733 if (change_case)
735 to_uppcase = 1;
736 to_lowcase = 0;
738 #if defined _NL_CURRENT || !HAVE_STRFTIME
739 cpy (aw_len, a_wkday);
740 break;
741 #else
742 goto underlying_strftime;
743 #endif
745 case 'A':
746 if (modifier != 0)
747 goto bad_format;
748 if (change_case)
750 to_uppcase = 1;
751 to_lowcase = 0;
753 #if defined _NL_CURRENT || !HAVE_STRFTIME
754 cpy (STRLEN (f_wkday), f_wkday);
755 break;
756 #else
757 goto underlying_strftime;
758 #endif
760 case L_('b'):
761 case L_('h'): /* POSIX.2 extension. */
762 if (change_case)
764 to_uppcase = 1;
765 to_lowcase = 0;
767 if (modifier != 0)
768 goto bad_format;
769 #if defined _NL_CURRENT || !HAVE_STRFTIME
770 cpy (am_len, a_month);
771 break;
772 #else
773 goto underlying_strftime;
774 #endif
776 case L_('B'):
777 if (modifier != 0)
778 goto bad_format;
779 if (change_case)
781 to_uppcase = 1;
782 to_lowcase = 0;
784 #if defined _NL_CURRENT || !HAVE_STRFTIME
785 cpy (STRLEN (f_month), f_month);
786 break;
787 #else
788 goto underlying_strftime;
789 #endif
791 case L_('c'):
792 if (modifier == L_('O'))
793 goto bad_format;
794 #ifdef _NL_CURRENT
795 if (! (modifier == 'E'
796 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
797 NLW(ERA_D_T_FMT)))
798 != '\0')))
799 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
800 #else
801 # if HAVE_STRFTIME
802 goto underlying_strftime;
803 # else
804 subfmt = L_("%a %b %e %H:%M:%S %Y");
805 # endif
806 #endif
808 subformat:
810 CHAR_T *old_start = p;
811 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp, 0);
812 add (len, my_strftime (p, maxsize - i, subfmt, tp, 0));
814 if (to_uppcase)
815 while (old_start < p)
817 *old_start = TOUPPER ((UCHAR_T) *old_start);
818 ++old_start;
821 break;
823 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
824 underlying_strftime:
826 /* The relevant information is available only via the
827 underlying strftime implementation, so use that. */
828 char ufmt[4];
829 char *u = ufmt;
830 char ubuf[1024]; /* enough for any single format in practice */
831 size_t len;
832 /* Make sure we're calling the actual underlying strftime.
833 In some cases, config.h contains something like
834 "#define strftime rpl_strftime". */
835 # ifdef strftime
836 # undef strftime
837 size_t strftime ();
838 # endif
840 #ifdef STRFTIME_NO_POSIX2
841 /* Some system libraries do not support the POSIX.2 extensions.
842 In those cases, convert %h to %b, and strip modifiers. */
843 modifier = 0;
844 if (format_char == 'h')
845 format_char = 'b';
846 #endif
847 *u++ = '%';
848 if (modifier != 0)
849 *u++ = modifier;
850 *u++ = format_char;
851 *u = '\0';
852 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
853 if (len == 0 && ubuf[0] != '\0')
854 return 0;
855 cpy (len, ubuf);
857 break;
858 #endif
860 case L_('C'): /* POSIX.2 extension. */
861 if (modifier == L_('O'))
862 goto bad_format;
863 if (modifier == L_('E'))
865 #if HAVE_STRUCT_ERA_ENTRY
866 struct era_entry *era = _nl_get_era_entry (tp);
867 if (era)
869 # ifdef COMPILE_WIDE
870 size_t len = __wcslen (era->era_wname);
871 cpy (len, era->era_wname);
872 # else
873 size_t len = strlen (era->era_name);
874 cpy (len, era->era_name);
875 # endif
876 break;
878 #else
879 # if HAVE_STRFTIME
880 goto underlying_strftime;
881 # endif
882 #endif
886 int year = tp->tm_year + TM_YEAR_BASE;
887 DO_NUMBER (1, year / 100 - (year % 100 < 0));
890 case L_('x'):
891 if (modifier == L_('O'))
892 goto bad_format;
893 #ifdef _NL_CURRENT
894 if (! (modifier == L_('E')
895 && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
896 NLW(ERA_D_FMT)))
897 != L_('\0'))))
898 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
899 goto subformat;
900 #else
901 # if HAVE_STRFTIME
902 goto underlying_strftime;
903 # else
904 /* Fall through. */
905 # endif
906 #endif
907 case L_('D'): /* POSIX.2 extension. */
908 if (modifier != 0)
909 goto bad_format;
910 subfmt = L_("%m/%d/%y");
911 goto subformat;
913 case L_('d'):
914 if (modifier == L_('E'))
915 goto bad_format;
917 DO_NUMBER (2, tp->tm_mday);
919 case L_('e'): /* POSIX.2 extension. */
920 if (modifier == L_('E'))
921 goto bad_format;
923 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
925 /* All numeric formats set DIGITS and NUMBER_VALUE and then
926 jump to one of these two labels. */
928 do_number_spacepad:
929 /* Force `_' flag unless overwritten by `0' flag. */
930 if (pad != L_('0'))
931 pad = L_('_');
933 do_number:
934 /* Format the number according to the MODIFIER flag. */
936 if (modifier == L_('O') && 0 <= number_value)
938 #ifdef _NL_CURRENT
939 /* Get the locale specific alternate representation of
940 the number NUMBER_VALUE. If none exist NULL is returned. */
941 # ifdef COMPILE_WIDE
942 const wchar_t *cp = _nl_get_walt_digit (number_value);
943 # else
944 const char *cp = _nl_get_alt_digit (number_value);
945 # endif
947 if (cp != NULL)
949 size_t digitlen = STRLEN (cp);
950 if (digitlen != 0)
952 cpy (digitlen, cp);
953 break;
956 #else
957 # if HAVE_STRFTIME
958 goto underlying_strftime;
959 # endif
960 #endif
963 unsigned int u = number_value;
965 bufp = buf + sizeof (buf) / sizeof (buf[0]);
966 negative_number = number_value < 0;
968 if (negative_number)
969 u = -u;
972 *--bufp = u % 10 + L_('0');
973 while ((u /= 10) != 0);
976 do_number_sign_and_padding:
977 if (negative_number)
978 *--bufp = L_('-');
980 if (pad != L_('-'))
982 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
983 - bufp);
985 if (pad == L_('_'))
987 while (0 < padding--)
988 *--bufp = L_(' ');
990 else
992 bufp += negative_number;
993 while (0 < padding--)
994 *--bufp = L_('0');
995 if (negative_number)
996 *--bufp = L_('-');
1000 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
1001 break;
1003 case L_('F'):
1004 if (modifier != 0)
1005 goto bad_format;
1006 subfmt = L_("%Y-%m-%d");
1007 goto subformat;
1009 case L_('H'):
1010 if (modifier == L_('E'))
1011 goto bad_format;
1013 DO_NUMBER (2, tp->tm_hour);
1015 case L_('I'):
1016 if (modifier == L_('E'))
1017 goto bad_format;
1019 DO_NUMBER (2, hour12);
1021 case L_('k'): /* GNU extension. */
1022 if (modifier == L_('E'))
1023 goto bad_format;
1025 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1027 case L_('l'): /* GNU extension. */
1028 if (modifier == L_('E'))
1029 goto bad_format;
1031 DO_NUMBER_SPACEPAD (2, hour12);
1033 case L_('j'):
1034 if (modifier == L_('E'))
1035 goto bad_format;
1037 DO_NUMBER (3, 1 + tp->tm_yday);
1039 case L_('M'):
1040 if (modifier == L_('E'))
1041 goto bad_format;
1043 DO_NUMBER (2, tp->tm_min);
1045 case L_('m'):
1046 if (modifier == L_('E'))
1047 goto bad_format;
1049 DO_NUMBER (2, tp->tm_mon + 1);
1051 case L_('n'): /* POSIX.2 extension. */
1052 add (1, *p = L_('\n'));
1053 break;
1055 case L_('P'):
1056 to_lowcase = 1;
1057 #if !defined _NL_CURRENT && HAVE_STRFTIME
1058 format_char = L_('p');
1059 #endif
1060 /* FALLTHROUGH */
1062 case L_('p'):
1063 if (change_case)
1065 to_uppcase = 0;
1066 to_lowcase = 1;
1068 #if defined _NL_CURRENT || !HAVE_STRFTIME
1069 cpy (ap_len, ampm);
1070 break;
1071 #else
1072 goto underlying_strftime;
1073 #endif
1075 case L_('R'): /* GNU extension. */
1076 subfmt = L_("%H:%M");
1077 goto subformat;
1079 case L_('r'): /* POSIX.2 extension. */
1080 #ifdef _NL_CURRENT
1081 if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1082 NLW(T_FMT_AMPM))) == L_('\0'))
1083 #endif
1084 subfmt = L_("%I:%M:%S %p");
1085 goto subformat;
1087 case L_('S'):
1088 if (modifier == L_('E'))
1089 goto bad_format;
1091 DO_NUMBER (2, tp->tm_sec);
1093 case L_('s'): /* GNU extension. */
1095 struct tm ltm;
1096 time_t t;
1098 ltm = *tp;
1099 t = mktime (&ltm);
1101 /* Generate string value for T using time_t arithmetic;
1102 this works even if sizeof (long) < sizeof (time_t). */
1104 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1105 negative_number = t < 0;
1109 int d = t % 10;
1110 t /= 10;
1112 if (negative_number)
1114 d = -d;
1116 /* Adjust if division truncates to minus infinity. */
1117 if (0 < -1 % 10 && d < 0)
1119 t++;
1120 d += 10;
1124 *--bufp = d + L_('0');
1126 while (t != 0);
1128 digits = 1;
1129 goto do_number_sign_and_padding;
1132 case L_('X'):
1133 if (modifier == L_('O'))
1134 goto bad_format;
1135 #ifdef _NL_CURRENT
1136 if (! (modifier == L_('E')
1137 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1138 NLW(ERA_T_FMT)))
1139 != L_('\0'))))
1140 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1141 goto subformat;
1142 #else
1143 # if HAVE_STRFTIME
1144 goto underlying_strftime;
1145 # else
1146 /* Fall through. */
1147 # endif
1148 #endif
1149 case L_('T'): /* POSIX.2 extension. */
1150 subfmt = L_("%H:%M:%S");
1151 goto subformat;
1153 case L_('t'): /* POSIX.2 extension. */
1154 add (1, *p = L_('\t'));
1155 break;
1157 case L_('u'): /* POSIX.2 extension. */
1158 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1160 case L_('U'):
1161 if (modifier == L_('E'))
1162 goto bad_format;
1164 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1166 case L_('V'):
1167 case L_('g'): /* GNU extension. */
1168 case L_('G'): /* GNU extension. */
1169 if (modifier == L_('E'))
1170 goto bad_format;
1172 int year = tp->tm_year + TM_YEAR_BASE;
1173 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1175 if (days < 0)
1177 /* This ISO week belongs to the previous year. */
1178 year--;
1179 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1180 tp->tm_wday);
1182 else
1184 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1185 tp->tm_wday);
1186 if (0 <= d)
1188 /* This ISO week belongs to the next year. */
1189 year++;
1190 days = d;
1194 switch (*f)
1196 case L_('g'):
1197 DO_NUMBER (2, (year % 100 + 100) % 100);
1199 case L_('G'):
1200 DO_NUMBER (1, year);
1202 default:
1203 DO_NUMBER (2, days / 7 + 1);
1207 case L_('W'):
1208 if (modifier == L_('E'))
1209 goto bad_format;
1211 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1213 case L_('w'):
1214 if (modifier == L_('E'))
1215 goto bad_format;
1217 DO_NUMBER (1, tp->tm_wday);
1219 case L_('Y'):
1220 if (modifier == 'E')
1222 #if HAVE_STRUCT_ERA_ENTRY
1223 struct era_entry *era = _nl_get_era_entry (tp);
1224 if (era)
1226 # ifdef COMPILE_WIDE
1227 subfmt = era->era_wformat;
1228 # else
1229 subfmt = era->era_format;
1230 # endif
1231 goto subformat;
1233 #else
1234 # if HAVE_STRFTIME
1235 goto underlying_strftime;
1236 # endif
1237 #endif
1239 if (modifier == L_('O'))
1240 goto bad_format;
1241 else
1242 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1244 case L_('y'):
1245 if (modifier == L_('E'))
1247 #if HAVE_STRUCT_ERA_ENTRY
1248 struct era_entry *era = _nl_get_era_entry (tp);
1249 if (era)
1251 int delta = tp->tm_year - era->start_date[0];
1252 DO_NUMBER (1, (era->offset
1253 + delta * era->absolute_direction));
1255 #else
1256 # if HAVE_STRFTIME
1257 goto underlying_strftime;
1258 # endif
1259 #endif
1261 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1263 case L_('Z'):
1264 if (change_case)
1266 to_uppcase = 0;
1267 to_lowcase = 1;
1270 #if HAVE_TZNAME
1271 /* The tzset() call might have changed the value. */
1272 if (!(zone && *zone) && tp->tm_isdst >= 0)
1273 zone = tzname[tp->tm_isdst];
1274 #endif
1275 if (! zone)
1276 zone = ""; /* POSIX.2 requires the empty string here. */
1278 #ifdef COMPILE_WIDE
1280 /* The zone string is always given in multibyte form. We have
1281 to transform it first. */
1282 wchar_t *wczone;
1283 size_t len;
1284 widen (zone, wczone, len);
1285 cpy (len, wczone);
1287 #else
1288 cpy (strlen (zone), zone);
1289 #endif
1290 break;
1292 case L_('z'): /* GNU extension. */
1293 if (tp->tm_isdst < 0)
1294 break;
1297 int diff;
1298 #if HAVE_TM_GMTOFF
1299 diff = tp->tm_gmtoff;
1300 #else
1301 if (ut)
1302 diff = 0;
1303 else
1305 struct tm gtm;
1306 struct tm ltm;
1307 time_t lt;
1309 ltm = *tp;
1310 lt = mktime (&ltm);
1312 if (lt == (time_t) -1)
1314 /* mktime returns -1 for errors, but -1 is also a
1315 valid time_t value. Check whether an error really
1316 occurred. */
1317 struct tm tm;
1319 if (! my_strftime_localtime_r (&lt, &tm)
1320 || ((ltm.tm_sec ^ tm.tm_sec)
1321 | (ltm.tm_min ^ tm.tm_min)
1322 | (ltm.tm_hour ^ tm.tm_hour)
1323 | (ltm.tm_mday ^ tm.tm_mday)
1324 | (ltm.tm_mon ^ tm.tm_mon)
1325 | (ltm.tm_year ^ tm.tm_year)))
1326 break;
1329 if (! my_strftime_gmtime_r (&lt, &gtm))
1330 break;
1332 diff = tm_diff (&ltm, &gtm);
1334 #endif
1336 if (diff < 0)
1338 add (1, *p = L_('-'));
1339 diff = -diff;
1341 else
1342 add (1, *p = L_('+'));
1344 diff /= 60;
1345 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1348 case L_('\0'): /* GNU extension: % at end of format. */
1349 --f;
1350 /* Fall through. */
1351 default:
1352 /* Unknown format; output the format, including the '%',
1353 since this is most likely the right thing to do if a
1354 multibyte string has been misparsed. */
1355 bad_format:
1357 int flen;
1358 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1359 continue;
1360 cpy (flen, &f[1 - flen]);
1362 break;
1366 if (p && maxsize != 0)
1367 *p = L_('\0');
1368 return i;
1372 #ifdef emacs
1373 /* For Emacs we have a separate interface which corresponds to the normal
1374 strftime function and does not have the extra information whether the
1375 TP arguments comes from a `gmtime' call or not. */
1376 size_t
1377 emacs_strftime (s, maxsize, format, tp)
1378 char *s;
1379 size_t maxsize;
1380 const char *format;
1381 const struct tm *tp;
1383 return my_strftime (s, maxsize, format, tp, 0);
1385 #endif