(Frecenter): If ARG < 0, and on a window system
[emacs.git] / src / strftime.c
blob61047bf9578af17277954f93df0c3449a72dec08
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 # else
72 /* Simulate mbrlen with mblen as best we can. */
73 # define mbstate_t int
74 # define mbrlen(s, n, ps) mblen (s, n)
75 # define mbsinit(ps) (*(ps) == 0)
76 # endif
77 static const mbstate_t mbstate_zero;
78 #endif
80 #ifdef HAVE_LIMITS_H
81 # include <limits.h>
82 #endif
84 #ifdef STDC_HEADERS
85 # include <stddef.h>
86 # include <stdlib.h>
87 #else
88 # ifndef HAVE_MEMCPY
89 # define memcpy(d, s, n) bcopy ((s), (d), (n))
90 # endif
91 #endif
93 #ifdef COMPILE_WIDE
94 # include <endian.h>
95 # define CHAR_T wchar_t
96 # define UCHAR_T unsigned int
97 # define L_(Str) L##Str
98 # define NLW(Sym) _NL_W##Sym
100 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
101 # define STRLEN(s) __wcslen (s)
103 #else
104 # define CHAR_T char
105 # define UCHAR_T unsigned char
106 # define L_(Str) Str
107 # define NLW(Sym) Sym
109 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
110 # define MEMCPY(d, s, n) bcopy ((s), (d), (n))
111 # else
112 # define MEMCPY(d, s, n) memcpy ((d), (s), (n))
113 # endif
114 # define STRLEN(s) strlen (s)
116 # ifdef _LIBC
117 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
118 # else
119 # ifndef HAVE_MEMPCPY
120 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
121 # endif
122 # endif
123 #endif
125 #ifndef __P
126 # if defined emacs && defined PROTOTYPES
127 # define __P(args) args
128 # elif defined __GNUC__ || (defined __STDC__ && __STDC__)
129 # define __P(args) args
130 # else
131 # define __P(args) ()
132 # endif /* GCC. */
133 #endif /* Not __P. */
135 #ifndef PTR
136 # ifdef __STDC__
137 # define PTR void *
138 # else
139 # define PTR char *
140 # endif
141 #endif
143 #ifndef CHAR_BIT
144 # define CHAR_BIT 8
145 #endif
147 #ifndef NULL
148 # define NULL 0
149 #endif
151 #define TYPE_SIGNED(t) ((t) -1 < 0)
153 /* Bound on length of the string representing an integer value of type t.
154 Subtract one for the sign bit if t is signed;
155 302 / 1000 is log10 (2) rounded up;
156 add one for integer division truncation;
157 add one more for a minus sign if t is signed. */
158 #define INT_STRLEN_BOUND(t) \
159 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
161 #define TM_YEAR_BASE 1900
163 #ifndef __isleap
164 /* Nonzero if YEAR is a leap year (every 4 years,
165 except every 100th isn't, and every 400th is). */
166 # define __isleap(year) \
167 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
168 #endif
171 #ifdef _LIBC
172 # define my_strftime_gmtime_r __gmtime_r
173 # define my_strftime_localtime_r __localtime_r
174 # define tzname __tzname
175 # define tzset __tzset
176 #else
178 /* If we're a strftime substitute in a GNU program, then prefer gmtime
179 to gmtime_r, since many gmtime_r implementations are buggy.
180 Similarly for localtime_r. */
182 # if ! HAVE_TM_GMTOFF
183 static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
184 static struct tm *
185 my_strftime_gmtime_r (t, tp)
186 const time_t *t;
187 struct tm *tp;
189 struct tm *l = gmtime (t);
190 if (! l)
191 return 0;
192 *tp = *l;
193 return tp;
195 # endif /* ! HAVE_TM_GMTOFF */
197 static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
198 static struct tm *
199 my_strftime_localtime_r (t, tp)
200 const time_t *t;
201 struct tm *tp;
203 struct tm *l = localtime (t);
204 if (! l)
205 return 0;
206 *tp = *l;
207 return tp;
209 #endif /* ! defined _LIBC */
212 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
213 /* Some systems lack the `memset' function and we don't want to
214 introduce additional dependencies. */
215 /* The SGI compiler reportedly barfs on the trailing null
216 if we use a string constant as the initializer. 28 June 1997, rms. */
217 static const CHAR_T spaces[16] = /* " " */
219 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
220 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
222 static const CHAR_T zeroes[16] = /* "0000000000000000" */
224 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
225 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
228 # define memset_space(P, Len) \
229 do { \
230 int _len = (Len); \
232 do \
234 int _this = _len > 16 ? 16 : _len; \
235 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
236 _len -= _this; \
238 while (_len > 0); \
239 } while (0)
241 # define memset_zero(P, Len) \
242 do { \
243 int _len = (Len); \
245 do \
247 int _this = _len > 16 ? 16 : _len; \
248 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
249 _len -= _this; \
251 while (_len > 0); \
252 } while (0)
253 #else
254 # ifdef COMPILE_WIDE
255 # define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
256 # define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
257 # else
258 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
259 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
260 # endif
261 #endif
263 #define add(n, f) \
264 do \
266 int _n = (n); \
267 int _delta = width - _n; \
268 int _incr = _n + (_delta > 0 ? _delta : 0); \
269 if (i + _incr >= maxsize) \
270 return 0; \
271 if (p) \
273 if (_delta > 0) \
275 if (pad == L_('0')) \
276 memset_zero (p, _delta); \
277 else \
278 memset_space (p, _delta); \
280 f; \
281 p += _n; \
283 i += _incr; \
284 } while (0)
286 #define cpy(n, s) \
287 add ((n), \
288 if (to_lowcase) \
289 memcpy_lowcase (p, (s), _n); \
290 else if (to_uppcase) \
291 memcpy_uppcase (p, (s), _n); \
292 else \
293 MEMCPY ((PTR) p, (PTR) (s), _n))
295 #ifdef COMPILE_WIDE
296 # define widen(os, ws, l) \
298 mbstate_t __st; \
299 const char *__s = os; \
300 memset (&__st, '\0', sizeof (__st)); \
301 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
302 ws = alloca ((l + 1) * sizeof (wchar_t)); \
303 (void) __mbsrtowcs (ws, &__s, l, &__st); \
305 #endif
308 #ifdef COMPILE_WIDE
309 # define TOUPPER(Ch) towupper (Ch)
310 # define TOLOWER(Ch) towlower (Ch)
311 #else
312 # ifdef _LIBC
313 # define TOUPPER(Ch) toupper (Ch)
314 # define TOLOWER(Ch) tolower (Ch)
315 # else
316 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
317 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
318 # endif
319 #endif
320 /* We don't use `isdigit' here since the locale dependent
321 interpretation is not what we want here. We only need to accept
322 the arabic digits in the ASCII range. One day there is perhaps a
323 more reliable way to accept other sets of digits. */
324 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
326 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
327 size_t len));
329 static CHAR_T *
330 memcpy_lowcase (dest, src, len)
331 CHAR_T *dest;
332 const CHAR_T *src;
333 size_t len;
335 while (len-- > 0)
336 dest[len] = TOLOWER ((UCHAR_T) src[len]);
337 return dest;
340 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
341 size_t len));
343 static CHAR_T *
344 memcpy_uppcase (dest, src, len)
345 CHAR_T *dest;
346 const CHAR_T *src;
347 size_t len;
349 while (len-- > 0)
350 dest[len] = TOUPPER ((UCHAR_T) src[len]);
351 return dest;
355 #if ! HAVE_TM_GMTOFF
356 /* Yield the difference between *A and *B,
357 measured in seconds, ignoring leap seconds. */
358 # define tm_diff ftime_tm_diff
359 static int tm_diff __P ((const struct tm *, const struct tm *));
360 static int
361 tm_diff (a, b)
362 const struct tm *a;
363 const struct tm *b;
365 /* Compute intervening leap days correctly even if year is negative.
366 Take care to avoid int overflow in leap day calculations,
367 but it's OK to assume that A and B are close to each other. */
368 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
369 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
370 int a100 = a4 / 25 - (a4 % 25 < 0);
371 int b100 = b4 / 25 - (b4 % 25 < 0);
372 int a400 = a100 >> 2;
373 int b400 = b100 >> 2;
374 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
375 int years = a->tm_year - b->tm_year;
376 int days = (365 * years + intervening_leap_days
377 + (a->tm_yday - b->tm_yday));
378 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
379 + (a->tm_min - b->tm_min))
380 + (a->tm_sec - b->tm_sec));
382 #endif /* ! HAVE_TM_GMTOFF */
386 /* The number of days from the first day of the first ISO week of this
387 year to the year day YDAY with week day WDAY. ISO weeks start on
388 Monday; the first ISO week has the year's first Thursday. YDAY may
389 be as small as YDAY_MINIMUM. */
390 #define ISO_WEEK_START_WDAY 1 /* Monday */
391 #define ISO_WEEK1_WDAY 4 /* Thursday */
392 #define YDAY_MINIMUM (-366)
393 static int iso_week_days __P ((int, int));
394 #ifdef __GNUC__
395 __inline__
396 #endif
397 static int
398 iso_week_days (yday, wday)
399 int yday;
400 int wday;
402 /* Add enough to the first operand of % to make it nonnegative. */
403 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
404 return (yday
405 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
406 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
410 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
411 static CHAR_T const weekday_name[][10] =
413 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
414 L_("Thursday"), L_("Friday"), L_("Saturday")
416 static CHAR_T const month_name[][10] =
418 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
419 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
420 L_("November"), L_("December")
422 #endif
425 #ifdef emacs
426 # define my_strftime emacs_strftimeu
427 # define ut_argument , ut
428 # define ut_argument_spec int ut;
429 # define ut_argument_spec_iso , int ut
430 #else
431 # ifdef COMPILE_WIDE
432 # define my_strftime wcsftime
433 # else
434 # define my_strftime strftime
435 # endif
436 # define ut_argument
437 # define ut_argument_spec
438 # define ut_argument_spec_iso
439 /* We don't have this information in general. */
440 # define ut 0
441 #endif
443 #if !defined _LIBC && !defined(WINDOWSNT) && HAVE_TZNAME && HAVE_TZSET
444 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
445 Work around this bug by copying *tp before it might be munged. */
446 size_t _strftime_copytm __P ((char *, size_t, const char *,
447 const struct tm * ut_argument_spec_iso));
448 size_t
449 my_strftime (s, maxsize, format, tp ut_argument)
450 CHAR_T *s;
451 size_t maxsize;
452 const CHAR_T *format;
453 const struct tm *tp;
454 ut_argument_spec
456 struct tm tmcopy;
457 tmcopy = *tp;
458 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
460 # undef my_strftime
461 # define my_strftime _strftime_copytm
462 #endif
465 /* Write information from TP into S according to the format
466 string FORMAT, writing no more that MAXSIZE characters
467 (including the terminating '\0') and returning number of
468 characters written. If S is NULL, nothing will be written
469 anywhere, so to determine how many characters would be
470 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
471 size_t
472 my_strftime (s, maxsize, format, tp ut_argument)
473 CHAR_T *s;
474 size_t maxsize;
475 const CHAR_T *format;
476 const struct tm *tp;
477 ut_argument_spec
479 int hour12 = tp->tm_hour;
480 #ifdef _NL_CURRENT
481 /* We cannot make the following values variables since we must delay
482 the evaluation of these values until really needed since some
483 expressions might not be valid in every situation. The `struct tm'
484 might be generated by a strptime() call that initialized
485 only a few elements. Dereference the pointers only if the format
486 requires this. Then it is ok to fail if the pointers are invalid. */
487 # define a_wkday \
488 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
489 # define f_wkday \
490 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
491 # define a_month \
492 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
493 # define f_month \
494 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
495 # define ampm \
496 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
497 ? NLW(PM_STR) : NLW(AM_STR)))
499 # define aw_len STRLEN (a_wkday)
500 # define am_len STRLEN (a_month)
501 # define ap_len STRLEN (ampm)
502 #else
503 # if !HAVE_STRFTIME
504 # define f_wkday (weekday_name[tp->tm_wday])
505 # define f_month (month_name[tp->tm_mon])
506 # define a_wkday f_wkday
507 # define a_month f_month
508 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
510 size_t aw_len = 3;
511 size_t am_len = 3;
512 size_t ap_len = 2;
513 # endif
514 #endif
515 const char *zone;
516 size_t i = 0;
517 CHAR_T *p = s;
518 const CHAR_T *f;
520 zone = NULL;
521 #if HAVE_TM_ZONE
522 /* The POSIX test suite assumes that setting
523 the environment variable TZ to a new value before calling strftime()
524 will influence the result (the %Z format) even if the information in
525 TP is computed with a totally different time zone.
526 This is bogus: though POSIX allows bad behavior like this,
527 POSIX does not require it. Do the right thing instead. */
528 zone = (const char *) tp->tm_zone;
529 #endif
530 #if HAVE_TZNAME
531 if (ut)
533 if (! (zone && *zone))
534 zone = "UTC";
536 else
538 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
539 time zone names contained in the external variable `tzname' shall
540 be set as if the tzset() function had been called. */
541 # if HAVE_TZSET
542 tzset ();
543 # endif
545 #endif
547 if (hour12 > 12)
548 hour12 -= 12;
549 else
550 if (hour12 == 0)
551 hour12 = 12;
553 for (f = format; *f != '\0'; ++f)
555 int pad = 0; /* Padding for number ('-', '_', or 0). */
556 int modifier; /* Field modifier ('E', 'O', or 0). */
557 int digits; /* Max digits for numeric format. */
558 int number_value; /* Numeric value to be printed. */
559 int negative_number; /* 1 if the number is negative. */
560 const CHAR_T *subfmt;
561 CHAR_T *bufp;
562 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
563 ? INT_STRLEN_BOUND (time_t)
564 : INT_STRLEN_BOUND (int))];
565 int width = -1;
566 int to_lowcase = 0;
567 int to_uppcase = 0;
568 int change_case = 0;
569 int format_char;
571 #if DO_MULTIBYTE && !defined COMPILE_WIDE
572 switch (*f)
574 case L_('%'):
575 break;
577 case L_('\b'): case L_('\t'): case L_('\n'):
578 case L_('\v'): case L_('\f'): case L_('\r'):
579 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
580 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
581 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
582 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
583 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
584 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
585 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
586 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
587 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
588 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
589 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
590 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
591 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
592 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
593 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
594 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
595 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
596 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
597 case L_('~'):
598 /* The C Standard requires these 97 characters (plus '%', `\a') to
599 be in the basic execution character set. None of these
600 characters can start a multibyte sequence, so they need
601 not be analyzed further. Some old compilers object to
602 `\a', so don't bother optimizing for it. */
603 add (1, *p = *f);
604 continue;
606 default:
607 /* Copy this multibyte sequence until we reach its end, find
608 an error, or come back to the initial shift state. */
610 mbstate_t mbstate = mbstate_zero;
611 size_t len = 0;
615 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
617 if (bytes == 0)
618 break;
620 if (bytes == (size_t) -2)
622 len += strlen (f + len);
623 break;
626 if (bytes == (size_t) -1)
628 len++;
629 break;
632 len += bytes;
634 while (! mbsinit (&mbstate));
636 cpy (len, f);
637 f += len - 1;
638 continue;
642 #else /* ! DO_MULTIBYTE */
644 /* Either multibyte encodings are not supported, they are
645 safe for formats, so any non-'%' byte can be copied through,
646 or this is the wide character version. */
647 if (*f != L_('%'))
649 add (1, *p = *f);
650 continue;
653 #endif /* ! DO_MULTIBYTE */
655 /* Check for flags that can modify a format. */
656 while (1)
658 switch (*++f)
660 /* This influences the number formats. */
661 case L_('_'):
662 case L_('-'):
663 case L_('0'):
664 pad = *f;
665 continue;
667 /* This changes textual output. */
668 case L_('^'):
669 to_uppcase = 1;
670 continue;
671 case L_('#'):
672 change_case = 1;
673 continue;
675 default:
676 break;
678 break;
681 /* As a GNU extension we allow to specify the field width. */
682 if (ISDIGIT (*f))
684 width = 0;
687 width *= 10;
688 width += *f - L_('0');
689 ++f;
691 while (ISDIGIT (*f));
694 /* Check for modifiers. */
695 switch (*f)
697 case L_('E'):
698 case L_('O'):
699 modifier = *f++;
700 break;
702 default:
703 modifier = 0;
704 break;
707 /* Now do the specified format. */
708 format_char = *f;
709 switch (format_char)
711 #define DO_NUMBER(d, v) \
712 digits = width == -1 ? d : width; \
713 number_value = v; goto do_number
714 #define DO_NUMBER_SPACEPAD(d, v) \
715 digits = width == -1 ? d : width; \
716 number_value = v; goto do_number_spacepad
718 case L_('%'):
719 if (modifier != 0)
720 goto bad_format;
721 add (1, *p = *f);
722 break;
724 case L_('a'):
725 if (modifier != 0)
726 goto bad_format;
727 if (change_case)
729 to_uppcase = 1;
730 to_lowcase = 0;
732 #if defined _NL_CURRENT || !HAVE_STRFTIME
733 cpy (aw_len, a_wkday);
734 break;
735 #else
736 goto underlying_strftime;
737 #endif
739 case 'A':
740 if (modifier != 0)
741 goto bad_format;
742 if (change_case)
744 to_uppcase = 1;
745 to_lowcase = 0;
747 #if defined _NL_CURRENT || !HAVE_STRFTIME
748 cpy (STRLEN (f_wkday), f_wkday);
749 break;
750 #else
751 goto underlying_strftime;
752 #endif
754 case L_('b'):
755 case L_('h'): /* POSIX.2 extension. */
756 if (change_case)
758 to_uppcase = 1;
759 to_lowcase = 0;
761 if (modifier != 0)
762 goto bad_format;
763 #if defined _NL_CURRENT || !HAVE_STRFTIME
764 cpy (am_len, a_month);
765 break;
766 #else
767 goto underlying_strftime;
768 #endif
770 case L_('B'):
771 if (modifier != 0)
772 goto bad_format;
773 if (change_case)
775 to_uppcase = 1;
776 to_lowcase = 0;
778 #if defined _NL_CURRENT || !HAVE_STRFTIME
779 cpy (STRLEN (f_month), f_month);
780 break;
781 #else
782 goto underlying_strftime;
783 #endif
785 case L_('c'):
786 if (modifier == L_('O'))
787 goto bad_format;
788 #ifdef _NL_CURRENT
789 if (! (modifier == 'E'
790 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
791 NLW(ERA_D_T_FMT)))
792 != '\0')))
793 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
794 #else
795 # if HAVE_STRFTIME
796 goto underlying_strftime;
797 # else
798 subfmt = L_("%a %b %e %H:%M:%S %Y");
799 # endif
800 #endif
802 subformat:
804 CHAR_T *old_start = p;
805 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp, 0);
806 add (len, my_strftime (p, maxsize - i, subfmt, tp, 0));
808 if (to_uppcase)
809 while (old_start < p)
811 *old_start = TOUPPER ((UCHAR_T) *old_start);
812 ++old_start;
815 break;
817 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
818 underlying_strftime:
820 /* The relevant information is available only via the
821 underlying strftime implementation, so use that. */
822 char ufmt[4];
823 char *u = ufmt;
824 char ubuf[1024]; /* enough for any single format in practice */
825 size_t len;
826 /* Make sure we're calling the actual underlying strftime.
827 In some cases, config.h contains something like
828 "#define strftime rpl_strftime". */
829 # ifdef strftime
830 # undef strftime
831 size_t strftime ();
832 # endif
834 *u++ = '%';
835 if (modifier != 0)
836 *u++ = modifier;
837 *u++ = format_char;
838 *u = '\0';
839 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
840 if (len == 0 && ubuf[0] != '\0')
841 return 0;
842 cpy (len, ubuf);
844 break;
845 #endif
847 case L_('C'): /* POSIX.2 extension. */
848 if (modifier == L_('O'))
849 goto bad_format;
850 if (modifier == L_('E'))
852 #if HAVE_STRUCT_ERA_ENTRY
853 struct era_entry *era = _nl_get_era_entry (tp);
854 if (era)
856 # ifdef COMPILE_WIDE
857 size_t len = __wcslen (era->era_wname);
858 cpy (len, era->era_wname);
859 # else
860 size_t len = strlen (era->era_name);
861 cpy (len, era->era_name);
862 # endif
863 break;
865 #else
866 # if HAVE_STRFTIME
867 goto underlying_strftime;
868 # endif
869 #endif
873 int year = tp->tm_year + TM_YEAR_BASE;
874 DO_NUMBER (1, year / 100 - (year % 100 < 0));
877 case L_('x'):
878 if (modifier == L_('O'))
879 goto bad_format;
880 #ifdef _NL_CURRENT
881 if (! (modifier == L_('E')
882 && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
883 NLW(ERA_D_FMT)))
884 != L_('\0'))))
885 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
886 goto subformat;
887 #else
888 # if HAVE_STRFTIME
889 goto underlying_strftime;
890 # else
891 /* Fall through. */
892 # endif
893 #endif
894 case L_('D'): /* POSIX.2 extension. */
895 if (modifier != 0)
896 goto bad_format;
897 subfmt = L_("%m/%d/%y");
898 goto subformat;
900 case L_('d'):
901 if (modifier == L_('E'))
902 goto bad_format;
904 DO_NUMBER (2, tp->tm_mday);
906 case L_('e'): /* POSIX.2 extension. */
907 if (modifier == L_('E'))
908 goto bad_format;
910 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
912 /* All numeric formats set DIGITS and NUMBER_VALUE and then
913 jump to one of these two labels. */
915 do_number_spacepad:
916 /* Force `_' flag unless overwritten by `0' flag. */
917 if (pad != L_('0'))
918 pad = L_('_');
920 do_number:
921 /* Format the number according to the MODIFIER flag. */
923 if (modifier == L_('O') && 0 <= number_value)
925 #ifdef _NL_CURRENT
926 /* Get the locale specific alternate representation of
927 the number NUMBER_VALUE. If none exist NULL is returned. */
928 # ifdef COMPILE_WIDE
929 const wchar_t *cp = _nl_get_walt_digit (number_value);
930 # else
931 const char *cp = _nl_get_alt_digit (number_value);
932 # endif
934 if (cp != NULL)
936 size_t digitlen = STRLEN (cp);
937 if (digitlen != 0)
939 cpy (digitlen, cp);
940 break;
943 #else
944 # if HAVE_STRFTIME
945 goto underlying_strftime;
946 # endif
947 #endif
950 unsigned int u = number_value;
952 bufp = buf + sizeof (buf) / sizeof (buf[0]);
953 negative_number = number_value < 0;
955 if (negative_number)
956 u = -u;
959 *--bufp = u % 10 + L_('0');
960 while ((u /= 10) != 0);
963 do_number_sign_and_padding:
964 if (negative_number)
965 *--bufp = L_('-');
967 if (pad != L_('-'))
969 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
970 - bufp);
972 if (pad == L_('_'))
974 while (0 < padding--)
975 *--bufp = L_(' ');
977 else
979 bufp += negative_number;
980 while (0 < padding--)
981 *--bufp = L_('0');
982 if (negative_number)
983 *--bufp = L_('-');
987 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
988 break;
990 case L_('F'):
991 if (modifier != 0)
992 goto bad_format;
993 subfmt = L_("%Y-%m-%d");
994 goto subformat;
996 case L_('H'):
997 if (modifier == L_('E'))
998 goto bad_format;
1000 DO_NUMBER (2, tp->tm_hour);
1002 case L_('I'):
1003 if (modifier == L_('E'))
1004 goto bad_format;
1006 DO_NUMBER (2, hour12);
1008 case L_('k'): /* GNU extension. */
1009 if (modifier == L_('E'))
1010 goto bad_format;
1012 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1014 case L_('l'): /* GNU extension. */
1015 if (modifier == L_('E'))
1016 goto bad_format;
1018 DO_NUMBER_SPACEPAD (2, hour12);
1020 case L_('j'):
1021 if (modifier == L_('E'))
1022 goto bad_format;
1024 DO_NUMBER (3, 1 + tp->tm_yday);
1026 case L_('M'):
1027 if (modifier == L_('E'))
1028 goto bad_format;
1030 DO_NUMBER (2, tp->tm_min);
1032 case L_('m'):
1033 if (modifier == L_('E'))
1034 goto bad_format;
1036 DO_NUMBER (2, tp->tm_mon + 1);
1038 case L_('n'): /* POSIX.2 extension. */
1039 add (1, *p = L_('\n'));
1040 break;
1042 case L_('P'):
1043 to_lowcase = 1;
1044 #if !defined _NL_CURRENT && HAVE_STRFTIME
1045 format_char = L_('p');
1046 #endif
1047 /* FALLTHROUGH */
1049 case L_('p'):
1050 if (change_case)
1052 to_uppcase = 0;
1053 to_lowcase = 1;
1055 #if defined _NL_CURRENT || !HAVE_STRFTIME
1056 cpy (ap_len, ampm);
1057 break;
1058 #else
1059 goto underlying_strftime;
1060 #endif
1062 case L_('R'): /* GNU extension. */
1063 subfmt = L_("%H:%M");
1064 goto subformat;
1066 case L_('r'): /* POSIX.2 extension. */
1067 #ifdef _NL_CURRENT
1068 if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1069 NLW(T_FMT_AMPM))) == L_('\0'))
1070 #endif
1071 subfmt = L_("%I:%M:%S %p");
1072 goto subformat;
1074 case L_('S'):
1075 if (modifier == L_('E'))
1076 goto bad_format;
1078 DO_NUMBER (2, tp->tm_sec);
1080 case L_('s'): /* GNU extension. */
1082 struct tm ltm;
1083 time_t t;
1085 ltm = *tp;
1086 t = mktime (&ltm);
1088 /* Generate string value for T using time_t arithmetic;
1089 this works even if sizeof (long) < sizeof (time_t). */
1091 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1092 negative_number = t < 0;
1096 int d = t % 10;
1097 t /= 10;
1099 if (negative_number)
1101 d = -d;
1103 /* Adjust if division truncates to minus infinity. */
1104 if (0 < -1 % 10 && d < 0)
1106 t++;
1107 d += 10;
1111 *--bufp = d + L_('0');
1113 while (t != 0);
1115 digits = 1;
1116 goto do_number_sign_and_padding;
1119 case L_('X'):
1120 if (modifier == L_('O'))
1121 goto bad_format;
1122 #ifdef _NL_CURRENT
1123 if (! (modifier == L_('E')
1124 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1125 NLW(ERA_T_FMT)))
1126 != L_('\0'))))
1127 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1128 goto subformat;
1129 #else
1130 # if HAVE_STRFTIME
1131 goto underlying_strftime;
1132 # else
1133 /* Fall through. */
1134 # endif
1135 #endif
1136 case L_('T'): /* POSIX.2 extension. */
1137 subfmt = L_("%H:%M:%S");
1138 goto subformat;
1140 case L_('t'): /* POSIX.2 extension. */
1141 add (1, *p = L_('\t'));
1142 break;
1144 case L_('u'): /* POSIX.2 extension. */
1145 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1147 case L_('U'):
1148 if (modifier == L_('E'))
1149 goto bad_format;
1151 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1153 case L_('V'):
1154 case L_('g'): /* GNU extension. */
1155 case L_('G'): /* GNU extension. */
1156 if (modifier == L_('E'))
1157 goto bad_format;
1159 int year = tp->tm_year + TM_YEAR_BASE;
1160 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1162 if (days < 0)
1164 /* This ISO week belongs to the previous year. */
1165 year--;
1166 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1167 tp->tm_wday);
1169 else
1171 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1172 tp->tm_wday);
1173 if (0 <= d)
1175 /* This ISO week belongs to the next year. */
1176 year++;
1177 days = d;
1181 switch (*f)
1183 case L_('g'):
1184 DO_NUMBER (2, (year % 100 + 100) % 100);
1186 case L_('G'):
1187 DO_NUMBER (1, year);
1189 default:
1190 DO_NUMBER (2, days / 7 + 1);
1194 case L_('W'):
1195 if (modifier == L_('E'))
1196 goto bad_format;
1198 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1200 case L_('w'):
1201 if (modifier == L_('E'))
1202 goto bad_format;
1204 DO_NUMBER (1, tp->tm_wday);
1206 case L_('Y'):
1207 if (modifier == 'E')
1209 #if HAVE_STRUCT_ERA_ENTRY
1210 struct era_entry *era = _nl_get_era_entry (tp);
1211 if (era)
1213 # ifdef COMPILE_WIDE
1214 subfmt = era->era_wformat;
1215 # else
1216 subfmt = era->era_format;
1217 # endif
1218 goto subformat;
1220 #else
1221 # if HAVE_STRFTIME
1222 goto underlying_strftime;
1223 # endif
1224 #endif
1226 if (modifier == L_('O'))
1227 goto bad_format;
1228 else
1229 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1231 case L_('y'):
1232 if (modifier == L_('E'))
1234 #if HAVE_STRUCT_ERA_ENTRY
1235 struct era_entry *era = _nl_get_era_entry (tp);
1236 if (era)
1238 int delta = tp->tm_year - era->start_date[0];
1239 DO_NUMBER (1, (era->offset
1240 + delta * era->absolute_direction));
1242 #else
1243 # if HAVE_STRFTIME
1244 goto underlying_strftime;
1245 # endif
1246 #endif
1248 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1250 case L_('Z'):
1251 if (change_case)
1253 to_uppcase = 0;
1254 to_lowcase = 1;
1257 #if HAVE_TZNAME
1258 /* The tzset() call might have changed the value. */
1259 if (!(zone && *zone) && tp->tm_isdst >= 0)
1260 zone = tzname[tp->tm_isdst];
1261 #endif
1262 if (! zone)
1263 zone = ""; /* POSIX.2 requires the empty string here. */
1265 #ifdef COMPILE_WIDE
1267 /* The zone string is always given in multibyte form. We have
1268 to transform it first. */
1269 wchar_t *wczone;
1270 size_t len;
1271 widen (zone, wczone, len);
1272 cpy (len, wczone);
1274 #else
1275 cpy (strlen (zone), zone);
1276 #endif
1277 break;
1279 case L_('z'): /* GNU extension. */
1280 if (tp->tm_isdst < 0)
1281 break;
1284 int diff;
1285 #if HAVE_TM_GMTOFF
1286 diff = tp->tm_gmtoff;
1287 #else
1288 if (ut)
1289 diff = 0;
1290 else
1292 struct tm gtm;
1293 struct tm ltm;
1294 time_t lt;
1296 ltm = *tp;
1297 lt = mktime (&ltm);
1299 if (lt == (time_t) -1)
1301 /* mktime returns -1 for errors, but -1 is also a
1302 valid time_t value. Check whether an error really
1303 occurred. */
1304 struct tm tm;
1306 if (! my_strftime_localtime_r (&lt, &tm)
1307 || ((ltm.tm_sec ^ tm.tm_sec)
1308 | (ltm.tm_min ^ tm.tm_min)
1309 | (ltm.tm_hour ^ tm.tm_hour)
1310 | (ltm.tm_mday ^ tm.tm_mday)
1311 | (ltm.tm_mon ^ tm.tm_mon)
1312 | (ltm.tm_year ^ tm.tm_year)))
1313 break;
1316 if (! my_strftime_gmtime_r (&lt, &gtm))
1317 break;
1319 diff = tm_diff (&ltm, &gtm);
1321 #endif
1323 if (diff < 0)
1325 add (1, *p = L_('-'));
1326 diff = -diff;
1328 else
1329 add (1, *p = L_('+'));
1331 diff /= 60;
1332 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1335 case L_('\0'): /* GNU extension: % at end of format. */
1336 --f;
1337 /* Fall through. */
1338 default:
1339 /* Unknown format; output the format, including the '%',
1340 since this is most likely the right thing to do if a
1341 multibyte string has been misparsed. */
1342 bad_format:
1344 int flen;
1345 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1346 continue;
1347 cpy (flen, &f[1 - flen]);
1349 break;
1353 if (p && maxsize != 0)
1354 *p = L_('\0');
1355 return i;
1359 #ifdef emacs
1360 /* For Emacs we have a separate interface which corresponds to the normal
1361 strftime function and does not have the extra information whether the
1362 TP arguments comes from a `gmtime' call or not. */
1363 size_t
1364 emacs_strftime (s, maxsize, format, tp)
1365 char *s;
1366 size_t maxsize;
1367 const char *format;
1368 const struct tm *tp;
1370 return my_strftime (s, maxsize, format, tp, 0);
1372 #endif