Update.
[glibc.git] / time / strftime.c
blob69babade3624a654ca04d14138606638ad6008d0
1 /* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU 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 /* Some hosts need this in order to declare localtime_r properly. */
24 #ifndef __EXTENSIONS__
25 # define __EXTENSIONS__ 1
26 #endif
28 #ifdef _LIBC
29 # define HAVE_LIMITS_H 1
30 # define HAVE_MBLEN 1
31 # define HAVE_MBRLEN 1
32 # define HAVE_STRUCT_ERA_ENTRY 1
33 # define HAVE_TM_GMTOFF 1
34 # define HAVE_TM_ZONE 1
35 # define HAVE_TZNAME 1
36 # define HAVE_TZSET 1
37 # define MULTIBYTE_IS_FORMAT_SAFE 1
38 # define STDC_HEADERS 1
39 # include "../locale/localeinfo.h"
40 #endif
42 #if defined emacs && !defined HAVE_BCOPY
43 # define HAVE_MEMCPY 1
44 #endif
46 #include <ctype.h>
47 #include <sys/types.h> /* Some systems define `time_t' here. */
49 /* Some systems require <unistd.h> to be included before <time.h>
50 for localtime_r to be declared properly. */
51 #if HAVE_UNISTD_H
52 # include <unistd.h>
53 #endif
55 #ifdef TIME_WITH_SYS_TIME
56 # include <sys/time.h>
57 # include <time.h>
58 #else
59 # ifdef HAVE_SYS_TIME_H
60 # include <sys/time.h>
61 # else
62 # include <time.h>
63 # endif
64 #endif
65 #if HAVE_TZNAME
66 extern char *tzname[];
67 #endif
69 /* Do multibyte processing if multibytes are supported, unless
70 multibyte sequences are safe in formats. Multibyte sequences are
71 safe if they cannot contain byte sequences that look like format
72 conversion specifications. The GNU C Library uses UTF8 multibyte
73 encoding, which is safe for formats, but strftime.c can be used
74 with other C libraries that use unsafe encodings. */
75 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
77 #if DO_MULTIBYTE
78 # if HAVE_MBRLEN
79 # include <wchar.h>
80 # else
81 /* Simulate mbrlen with mblen as best we can. */
82 # define mbstate_t int
83 # define mbrlen(s, n, ps) mblen (s, n)
84 # define mbsinit(ps) (*(ps) == 0)
85 # endif
86 static const mbstate_t mbstate_zero;
87 #endif
89 #if HAVE_LIMITS_H
90 # include <limits.h>
91 #endif
93 #if STDC_HEADERS
94 # include <stddef.h>
95 # include <stdlib.h>
96 # include <string.h>
97 #else
98 # ifndef HAVE_MEMCPY
99 # define memcpy(d, s, n) bcopy ((s), (d), (n))
100 # endif
101 #endif
103 #ifdef _LIBC
104 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
105 #else
106 # ifndef HAVE_MEMPCPY
107 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
108 # endif
109 #endif
111 #ifndef __P
112 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
113 # define __P(args) args
114 # else
115 # define __P(args) ()
116 # endif /* GCC. */
117 #endif /* Not __P. */
119 #ifndef PTR
120 # ifdef __STDC__
121 # define PTR void *
122 # else
123 # define PTR char *
124 # endif
125 #endif
127 #ifndef CHAR_BIT
128 # define CHAR_BIT 8
129 #endif
131 #ifndef NULL
132 # define NULL 0
133 #endif
135 #define TYPE_SIGNED(t) ((t) -1 < 0)
137 /* Bound on length of the string representing an integer value of type t.
138 Subtract one for the sign bit if t is signed;
139 302 / 1000 is log10 (2) rounded up;
140 add one for integer division truncation;
141 add one more for a minus sign if t is signed. */
142 #define INT_STRLEN_BOUND(t) \
143 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
145 #define TM_YEAR_BASE 1900
147 #ifndef __isleap
148 /* Nonzero if YEAR is a leap year (every 4 years,
149 except every 100th isn't, and every 400th is). */
150 # define __isleap(year) \
151 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
152 #endif
155 #ifdef _LIBC
156 # define gmtime_r __gmtime_r
157 # define localtime_r __localtime_r
158 # define tzname __tzname
159 # define tzset __tzset
160 #else
161 # if ! HAVE_LOCALTIME_R
162 # if ! HAVE_TM_GMTOFF
163 /* Approximate gmtime_r as best we can in its absence. */
164 # undef gmtime_r
165 # define gmtime_r my_gmtime_r
166 static struct tm *gmtime_r __P ((const time_t *, struct tm *));
167 static struct tm *
168 gmtime_r (t, tp)
169 const time_t *t;
170 struct tm *tp;
172 struct tm *l = gmtime (t);
173 if (! l)
174 return 0;
175 *tp = *l;
176 return tp;
178 # endif /* ! HAVE_TM_GMTOFF */
180 /* Approximate localtime_r as best we can in its absence. */
181 # undef localtime_r
182 # define localtime_r my_ftime_localtime_r
183 static struct tm *localtime_r __P ((const time_t *, struct tm *));
184 static struct tm *
185 localtime_r (t, tp)
186 const time_t *t;
187 struct tm *tp;
189 struct tm *l = localtime (t);
190 if (! l)
191 return 0;
192 *tp = *l;
193 return tp;
195 # endif /* ! HAVE_LOCALTIME_R */
196 #endif /* ! defined _LIBC */
199 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
200 /* Some systems lack the `memset' function and we don't want to
201 introduce additional dependencies. */
202 /* The SGI compiler reportedly barfs on the trailing null
203 if we use a string constant as the initializer. 28 June 1997, rms. */
204 static const char spaces[16] = /* " " */
205 { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
206 static const char zeroes[16] = /* "0000000000000000" */
207 { '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0' };
209 # define memset_space(P, Len) \
210 do { \
211 int _len = (Len); \
213 do \
215 int _this = _len > 16 ? 16 : _len; \
216 (P) = MEMPCPY ((P), spaces, _this); \
217 _len -= _this; \
219 while (_len > 0); \
220 } while (0)
222 # define memset_zero(P, Len) \
223 do { \
224 int _len = (Len); \
226 do \
228 int _this = _len > 16 ? 16 : _len; \
229 (P) = MEMPCPY ((P), zeroes, _this); \
230 _len -= _this; \
232 while (_len > 0); \
233 } while (0)
234 #else
235 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
236 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
237 #endif
239 #define add(n, f) \
240 do \
242 int _n = (n); \
243 int _delta = width - _n; \
244 int _incr = _n + (_delta > 0 ? _delta : 0); \
245 if (i + _incr >= maxsize) \
246 return 0; \
247 if (p) \
249 if (_delta > 0) \
251 if (pad == '0') \
252 memset_zero (p, _delta); \
253 else \
254 memset_space (p, _delta); \
256 f; \
257 p += _n; \
259 i += _incr; \
260 } while (0)
262 #define cpy(n, s) \
263 add ((n), \
264 if (to_lowcase) \
265 memcpy_lowcase (p, (s), _n); \
266 else if (to_uppcase) \
267 memcpy_uppcase (p, (s), _n); \
268 else \
269 memcpy ((PTR) p, (PTR) (s), _n))
273 #ifdef _LIBC
274 # define TOUPPER(Ch) toupper (Ch)
275 # define TOLOWER(Ch) tolower (Ch)
276 #else
277 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
278 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
279 #endif
280 /* We don't use `isdigit' here since the locale dependent
281 interpretation is not what we want here. We only need to accept
282 the arabic digits in the ASCII range. One day there is perhaps a
283 more reliable way to accept other sets of digits. */
284 #define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
286 static char *memcpy_lowcase __P ((char *dest, const char *src, size_t len));
288 static char *
289 memcpy_lowcase (dest, src, len)
290 char *dest;
291 const char *src;
292 size_t len;
294 while (len-- > 0)
295 dest[len] = TOLOWER ((unsigned char) src[len]);
296 return dest;
299 static char *memcpy_uppcase __P ((char *dest, const char *src, size_t len));
301 static char *
302 memcpy_uppcase (dest, src, len)
303 char *dest;
304 const char *src;
305 size_t len;
307 while (len-- > 0)
308 dest[len] = TOUPPER ((unsigned char) src[len]);
309 return dest;
313 #if ! HAVE_TM_GMTOFF
314 /* Yield the difference between *A and *B,
315 measured in seconds, ignoring leap seconds. */
316 # define tm_diff ftime_tm_diff
317 static int tm_diff __P ((const struct tm *, const struct tm *));
318 static int
319 tm_diff (a, b)
320 const struct tm *a;
321 const struct tm *b;
323 /* Compute intervening leap days correctly even if year is negative.
324 Take care to avoid int overflow in leap day calculations,
325 but it's OK to assume that A and B are close to each other. */
326 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
327 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
328 int a100 = a4 / 25 - (a4 % 25 < 0);
329 int b100 = b4 / 25 - (b4 % 25 < 0);
330 int a400 = a100 >> 2;
331 int b400 = b100 >> 2;
332 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
333 int years = a->tm_year - b->tm_year;
334 int days = (365 * years + intervening_leap_days
335 + (a->tm_yday - b->tm_yday));
336 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
337 + (a->tm_min - b->tm_min))
338 + (a->tm_sec - b->tm_sec));
340 #endif /* ! HAVE_TM_GMTOFF */
344 /* The number of days from the first day of the first ISO week of this
345 year to the year day YDAY with week day WDAY. ISO weeks start on
346 Monday; the first ISO week has the year's first Thursday. YDAY may
347 be as small as YDAY_MINIMUM. */
348 #define ISO_WEEK_START_WDAY 1 /* Monday */
349 #define ISO_WEEK1_WDAY 4 /* Thursday */
350 #define YDAY_MINIMUM (-366)
351 static int iso_week_days __P ((int, int));
352 #ifdef __GNUC__
353 __inline__
354 #endif
355 static int
356 iso_week_days (yday, wday)
357 int yday;
358 int wday;
360 /* Add enough to the first operand of % to make it nonnegative. */
361 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
362 return (yday
363 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
364 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
368 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
369 static char const weekday_name[][10] =
371 "Sunday", "Monday", "Tuesday", "Wednesday",
372 "Thursday", "Friday", "Saturday"
374 static char const month_name[][10] =
376 "January", "February", "March", "April", "May", "June",
377 "July", "August", "September", "October", "November", "December"
379 #endif
382 #ifdef emacs
383 # define my_strftime emacs_strftimeu
384 # define ut_argument , ut
385 # define ut_argument_spec int ut;
386 # define ut_argument_spec_iso , int ut
387 #else
388 # define my_strftime strftime
389 # define ut_argument
390 # define ut_argument_spec
391 # define ut_argument_spec_iso
392 /* We don't have this information in general. */
393 # define ut 0
394 #endif
396 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
397 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
398 Work around this bug by copying *tp before it might be munged. */
399 size_t _strftime_copytm __P ((char *, size_t, const char *,
400 const struct tm * ut_argument_spec_iso));
401 size_t
402 my_strftime (s, maxsize, format, tp ut_argument)
403 char *s;
404 size_t maxsize;
405 const char *format;
406 const struct tm *tp;
407 ut_argument_spec
409 struct tm tmcopy;
410 tmcopy = *tp;
411 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
413 # undef my_strftime
414 # define my_strftime(S, Maxsize, Format, Tp) \
415 _strftime_copytm (S, Maxsize, Format, Tp)
416 #endif
419 /* Write information from TP into S according to the format
420 string FORMAT, writing no more that MAXSIZE characters
421 (including the terminating '\0') and returning number of
422 characters written. If S is NULL, nothing will be written
423 anywhere, so to determine how many characters would be
424 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
425 size_t
426 my_strftime (s, maxsize, format, tp ut_argument)
427 char *s;
428 size_t maxsize;
429 const char *format;
430 const struct tm *tp;
431 ut_argument_spec
433 int hour12 = tp->tm_hour;
434 #ifdef _NL_CURRENT
435 /* We cannot make the following values variables since we must delay
436 the evaluation of these values until really needed since some
437 expressions might not be valid in every situation. The `struct tm'
438 might be generated by a strptime() call that initialized
439 only a few elements. Dereference the pointers only if the format
440 requires this. Then it is ok to fail if the pointers are invalid. */
441 # define a_wkday _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday)
442 # define f_wkday _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday)
443 # define a_month _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon)
444 # define f_month _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon)
445 # define ampm _NL_CURRENT (LC_TIME, tp->tm_hour > 11 ? PM_STR : AM_STR)
447 # define aw_len strlen (a_wkday)
448 # define am_len strlen (a_month)
449 # define ap_len strlen (ampm)
450 #else
451 # if !HAVE_STRFTIME
452 # define f_wkday (weekday_name[tp->tm_wday])
453 # define f_month (month_name[tp->tm_mon])
454 # define a_wkday f_wkday
455 # define a_month f_month
456 # define ampm ("AMPM" + 2 * (tp->tm_hour > 11))
458 size_t aw_len = 3;
459 size_t am_len = 3;
460 size_t ap_len = 2;
461 # endif
462 #endif
463 const char *zone;
464 size_t i = 0;
465 char *p = s;
466 const char *f;
468 zone = NULL;
469 #if HAVE_TM_ZONE
470 /* The POSIX test suite assumes that setting
471 the environment variable TZ to a new value before calling strftime()
472 will influence the result (the %Z format) even if the information in
473 TP is computed with a totally different time zone.
474 This is bogus: though POSIX allows bad behavior like this,
475 POSIX does not require it. Do the right thing instead. */
476 zone = (const char *) tp->tm_zone;
477 #endif
478 #if HAVE_TZNAME
479 if (ut)
481 if (! (zone && *zone))
482 zone = "GMT";
484 else
486 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
487 time zone names contained in the external variable `tzname' shall
488 be set as if the tzset() function had been called. */
489 # if HAVE_TZSET
490 tzset ();
491 # endif
493 #endif
495 if (hour12 > 12)
496 hour12 -= 12;
497 else
498 if (hour12 == 0)
499 hour12 = 12;
501 for (f = format; *f != '\0'; ++f)
503 int pad = 0; /* Padding for number ('-', '_', or 0). */
504 int modifier; /* Field modifier ('E', 'O', or 0). */
505 int digits; /* Max digits for numeric format. */
506 int number_value; /* Numeric value to be printed. */
507 int negative_number; /* 1 if the number is negative. */
508 const char *subfmt;
509 char *bufp;
510 char buf[1 + (sizeof (int) < sizeof (time_t)
511 ? INT_STRLEN_BOUND (time_t)
512 : INT_STRLEN_BOUND (int))];
513 int width = -1;
514 int to_lowcase = 0;
515 int to_uppcase = 0;
516 int change_case = 0;
517 int format_char;
519 #if DO_MULTIBYTE
521 switch (*f)
523 case '%':
524 break;
526 case '\a': case '\b': case '\t': case '\n':
527 case '\v': case '\f': case '\r':
528 case ' ': case '!': case '"': case '#': case '&': case'\'':
529 case '(': case ')': case '*': case '+': case ',': case '-':
530 case '.': case '/': case '0': case '1': case '2': case '3':
531 case '4': case '5': case '6': case '7': case '8': case '9':
532 case ':': case ';': case '<': case '=': case '>': case '?':
533 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
534 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
535 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
536 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
537 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
538 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
539 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
540 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
541 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
542 case 'x': case 'y': case 'z': case '{': case '|': case '}':
543 case '~':
544 /* The C Standard requires these 98 characters (plus '%') to
545 be in the basic execution character set. None of these
546 characters can start a multibyte sequence, so they need
547 not be analyzed further. */
548 add (1, *p = *f);
549 continue;
551 default:
552 /* Copy this multibyte sequence until we reach its end, find
553 an error, or come back to the initial shift state. */
555 mbstate_t mbstate = mbstate_zero;
556 size_t len = 0;
560 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
562 if (bytes == 0)
563 break;
565 if (bytes == (size_t) -2)
567 len += strlen (f + len);
568 break;
571 if (bytes == (size_t) -1)
573 len++;
574 break;
577 len += bytes;
579 while (! mbsinit (&mbstate));
581 cpy (len, f);
582 f += len - 1;
583 continue;
587 #else /* ! DO_MULTIBYTE */
589 /* Either multibyte encodings are not supported, or they are
590 safe for formats, so any non-'%' byte can be copied through. */
591 if (*f != '%')
593 add (1, *p = *f);
594 continue;
597 #endif /* ! DO_MULTIBYTE */
599 /* Check for flags that can modify a format. */
600 while (1)
602 switch (*++f)
604 /* This influences the number formats. */
605 case '_':
606 case '-':
607 case '0':
608 pad = *f;
609 continue;
611 /* This changes textual output. */
612 case '^':
613 to_uppcase = 1;
614 continue;
615 case '#':
616 change_case = 1;
617 continue;
619 default:
620 break;
622 break;
625 /* As a GNU extension we allow to specify the field width. */
626 if (ISDIGIT (*f))
628 width = 0;
631 width *= 10;
632 width += *f - '0';
633 ++f;
635 while (ISDIGIT (*f));
638 /* Check for modifiers. */
639 switch (*f)
641 case 'E':
642 case 'O':
643 modifier = *f++;
644 break;
646 default:
647 modifier = 0;
648 break;
651 /* Now do the specified format. */
652 format_char = *f;
653 switch (format_char)
655 #define DO_NUMBER(d, v) \
656 digits = width == -1 ? d : width; \
657 number_value = v; goto do_number
658 #define DO_NUMBER_SPACEPAD(d, v) \
659 digits = width == -1 ? d : width; \
660 number_value = v; goto do_number_spacepad
662 case '%':
663 if (modifier != 0)
664 goto bad_format;
665 add (1, *p = *f);
666 break;
668 case 'a':
669 if (modifier != 0)
670 goto bad_format;
671 if (change_case)
673 to_uppcase = 1;
674 to_lowcase = 0;
676 #if defined _NL_CURRENT || !HAVE_STRFTIME
677 cpy (aw_len, a_wkday);
678 break;
679 #else
680 goto underlying_strftime;
681 #endif
683 case 'A':
684 if (modifier != 0)
685 goto bad_format;
686 if (change_case)
688 to_uppcase = 1;
689 to_lowcase = 0;
691 #if defined _NL_CURRENT || !HAVE_STRFTIME
692 cpy (strlen (f_wkday), f_wkday);
693 break;
694 #else
695 goto underlying_strftime;
696 #endif
698 case 'b':
699 case 'h': /* POSIX.2 extension. */
700 if (modifier != 0)
701 goto bad_format;
702 #if defined _NL_CURRENT || !HAVE_STRFTIME
703 cpy (am_len, a_month);
704 break;
705 #else
706 goto underlying_strftime;
707 #endif
709 case 'B':
710 if (modifier != 0)
711 goto bad_format;
712 if (change_case)
714 to_uppcase = 1;
715 to_lowcase = 0;
717 #if defined _NL_CURRENT || !HAVE_STRFTIME
718 cpy (strlen (f_month), f_month);
719 break;
720 #else
721 goto underlying_strftime;
722 #endif
724 case 'c':
725 if (modifier == 'O')
726 goto bad_format;
727 #ifdef _NL_CURRENT
728 if (! (modifier == 'E'
729 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT)) != '\0'))
730 subfmt = _NL_CURRENT (LC_TIME, D_T_FMT);
731 #else
732 # if HAVE_STRFTIME
733 goto underlying_strftime;
734 # else
735 subfmt = "%a %b %e %H:%M:%S %Y";
736 # endif
737 #endif
739 subformat:
741 char *old_start = p;
742 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp);
743 add (len, my_strftime (p, maxsize - i, subfmt, tp));
745 if (to_uppcase)
746 while (old_start < p)
748 *old_start = TOUPPER ((unsigned char) *old_start);
749 ++old_start;
752 break;
754 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
755 underlying_strftime:
757 /* The relevant information is available only via the
758 underlying strftime implementation, so use that. */
759 char ufmt[4];
760 char *u = ufmt;
761 char ubuf[1024]; /* enough for any single format in practice */
762 size_t len;
763 *u++ = '%';
764 if (modifier != 0)
765 *u++ = modifier;
766 *u++ = format_char;
767 *u = '\0';
768 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
769 if (len == 0 && ubuf[0] != '\0')
770 return 0;
771 cpy (len, ubuf);
773 break;
774 #endif
776 case 'C': /* POSIX.2 extension. */
777 if (modifier == 'O')
778 goto bad_format;
779 if (modifier == 'E')
781 #if HAVE_STRUCT_ERA_ENTRY
782 struct era_entry *era = _nl_get_era_entry (tp);
783 if (era)
785 size_t len = strlen (era->name_fmt);
786 cpy (len, era->name_fmt);
787 break;
789 #else
790 # if HAVE_STRFTIME
791 goto underlying_strftime;
792 # endif
793 #endif
797 int year = tp->tm_year + TM_YEAR_BASE;
798 DO_NUMBER (1, year / 100 - (year % 100 < 0));
801 case 'x':
802 if (modifier == 'O')
803 goto bad_format;
804 #ifdef _NL_CURRENT
805 if (! (modifier == 'E'
806 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_FMT)) != '\0'))
807 subfmt = _NL_CURRENT (LC_TIME, D_FMT);
808 goto subformat;
809 #else
810 # if HAVE_STRFTIME
811 goto underlying_strftime;
812 # else
813 /* Fall through. */
814 # endif
815 #endif
816 case 'D': /* POSIX.2 extension. */
817 if (modifier != 0)
818 goto bad_format;
819 subfmt = "%m/%d/%y";
820 goto subformat;
822 case 'd':
823 if (modifier == 'E')
824 goto bad_format;
826 DO_NUMBER (2, tp->tm_mday);
828 case 'e': /* POSIX.2 extension. */
829 if (modifier == 'E')
830 goto bad_format;
832 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
834 /* All numeric formats set DIGITS and NUMBER_VALUE and then
835 jump to one of these two labels. */
837 do_number_spacepad:
838 /* Force `_' flag unless overwritten by `0' flag. */
839 if (pad != '0')
840 pad = '_';
842 do_number:
843 /* Format the number according to the MODIFIER flag. */
845 if (modifier == 'O' && 0 <= number_value)
847 #ifdef _NL_CURRENT
848 /* Get the locale specific alternate representation of
849 the number NUMBER_VALUE. If none exist NULL is returned. */
850 const char *cp = _nl_get_alt_digit (number_value);
852 if (cp != NULL)
854 size_t digitlen = strlen (cp);
855 if (digitlen != 0)
857 cpy (digitlen, cp);
858 break;
861 #else
862 # if HAVE_STRFTIME
863 goto underlying_strftime;
864 # endif
865 #endif
868 unsigned int u = number_value;
870 bufp = buf + sizeof (buf);
871 negative_number = number_value < 0;
873 if (negative_number)
874 u = -u;
877 *--bufp = u % 10 + '0';
878 while ((u /= 10) != 0);
881 do_number_sign_and_padding:
882 if (negative_number)
883 *--bufp = '-';
885 if (pad != '-')
887 int padding = digits - (buf + sizeof (buf) - bufp);
889 if (pad == '_')
891 while (0 < padding--)
892 *--bufp = ' ';
894 else
896 bufp += negative_number;
897 while (0 < padding--)
898 *--bufp = '0';
899 if (negative_number)
900 *--bufp = '-';
904 cpy (buf + sizeof (buf) - bufp, bufp);
905 break;
907 case 'F':
908 if (modifier != 0)
909 goto bad_format;
910 subfmt = "%Y-%m-%d";
911 goto subformat;
913 case 'H':
914 if (modifier == 'E')
915 goto bad_format;
917 DO_NUMBER (2, tp->tm_hour);
919 case 'I':
920 if (modifier == 'E')
921 goto bad_format;
923 DO_NUMBER (2, hour12);
925 case 'k': /* GNU extension. */
926 if (modifier == 'E')
927 goto bad_format;
929 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
931 case 'l': /* GNU extension. */
932 if (modifier == 'E')
933 goto bad_format;
935 DO_NUMBER_SPACEPAD (2, hour12);
937 case 'j':
938 if (modifier == 'E')
939 goto bad_format;
941 DO_NUMBER (3, 1 + tp->tm_yday);
943 case 'M':
944 if (modifier == 'E')
945 goto bad_format;
947 DO_NUMBER (2, tp->tm_min);
949 case 'm':
950 if (modifier == 'E')
951 goto bad_format;
953 DO_NUMBER (2, tp->tm_mon + 1);
955 case 'n': /* POSIX.2 extension. */
956 add (1, *p = '\n');
957 break;
959 case 'P':
960 to_lowcase = 1;
961 #if !defined _NL_CURRENT && HAVE_STRFTIME
962 format_char = 'p';
963 #endif
964 /* FALLTHROUGH */
966 case 'p':
967 if (change_case)
969 to_uppcase = 0;
970 to_lowcase = 1;
972 #if defined _NL_CURRENT || !HAVE_STRFTIME
973 cpy (ap_len, ampm);
974 break;
975 #else
976 goto underlying_strftime;
977 #endif
979 case 'R': /* GNU extension. */
980 subfmt = "%H:%M";
981 goto subformat;
983 case 'r': /* POSIX.2 extension. */
984 #ifdef _NL_CURRENT
985 if (*(subfmt = _NL_CURRENT (LC_TIME, T_FMT_AMPM)) == '\0')
986 #endif
987 subfmt = "%I:%M:%S %p";
988 goto subformat;
990 case 'S':
991 if (modifier == 'E')
992 goto bad_format;
994 DO_NUMBER (2, tp->tm_sec);
996 case 's': /* GNU extension. */
998 struct tm ltm;
999 time_t t;
1001 ltm = *tp;
1002 t = mktime (&ltm);
1004 /* Generate string value for T using time_t arithmetic;
1005 this works even if sizeof (long) < sizeof (time_t). */
1007 bufp = buf + sizeof (buf);
1008 negative_number = t < 0;
1012 int d = t % 10;
1013 t /= 10;
1015 if (negative_number)
1017 d = -d;
1019 /* Adjust if division truncates to minus infinity. */
1020 if (0 < -1 % 10 && d < 0)
1022 t++;
1023 d += 10;
1027 *--bufp = d + '0';
1029 while (t != 0);
1031 digits = 1;
1032 goto do_number_sign_and_padding;
1035 case 'X':
1036 if (modifier == 'O')
1037 goto bad_format;
1038 #ifdef _NL_CURRENT
1039 if (! (modifier == 'E'
1040 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_T_FMT)) != '\0'))
1041 subfmt = _NL_CURRENT (LC_TIME, T_FMT);
1042 goto subformat;
1043 #else
1044 # if HAVE_STRFTIME
1045 goto underlying_strftime;
1046 # else
1047 /* Fall through. */
1048 # endif
1049 #endif
1050 case 'T': /* POSIX.2 extension. */
1051 subfmt = "%H:%M:%S";
1052 goto subformat;
1054 case 't': /* POSIX.2 extension. */
1055 add (1, *p = '\t');
1056 break;
1058 case 'f':
1059 case 'u': /* POSIX.2 extension. */
1060 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1062 case 'U':
1063 if (modifier == 'E')
1064 goto bad_format;
1066 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1068 case 'V':
1069 case 'g': /* GNU extension. */
1070 case 'G': /* GNU extension. */
1071 if (modifier == 'E')
1072 goto bad_format;
1074 int year = tp->tm_year + TM_YEAR_BASE;
1075 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1077 if (days < 0)
1079 /* This ISO week belongs to the previous year. */
1080 year--;
1081 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1082 tp->tm_wday);
1084 else
1086 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1087 tp->tm_wday);
1088 if (0 <= d)
1090 /* This ISO week belongs to the next year. */
1091 year++;
1092 days = d;
1096 switch (*f)
1098 case 'g':
1099 DO_NUMBER (2, (year % 100 + 100) % 100);
1101 case 'G':
1102 DO_NUMBER (1, year);
1104 default:
1105 DO_NUMBER (2, days / 7 + 1);
1109 case 'W':
1110 if (modifier == 'E')
1111 goto bad_format;
1113 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1115 case 'w':
1116 if (modifier == 'E')
1117 goto bad_format;
1119 DO_NUMBER (1, tp->tm_wday);
1121 case 'Y':
1122 if (modifier == 'E')
1124 #if HAVE_STRUCT_ERA_ENTRY
1125 struct era_entry *era = _nl_get_era_entry (tp);
1126 if (era)
1128 subfmt = strchr (era->name_fmt, '\0') + 1;
1129 goto subformat;
1131 #else
1132 # if HAVE_STRFTIME
1133 goto underlying_strftime;
1134 # endif
1135 #endif
1137 if (modifier == 'O')
1138 goto bad_format;
1139 else
1140 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1142 case 'y':
1143 if (modifier == 'E')
1145 #if HAVE_STRUCT_ERA_ENTRY
1146 struct era_entry *era = _nl_get_era_entry (tp);
1147 if (era)
1149 int delta = tp->tm_year - era->start_date[0];
1150 DO_NUMBER (1, (era->offset
1151 + (era->direction == '-' ? -delta : delta)));
1153 #else
1154 # if HAVE_STRFTIME
1155 goto underlying_strftime;
1156 # endif
1157 #endif
1159 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1161 case 'Z':
1162 if (change_case)
1164 to_uppcase = 0;
1165 to_lowcase = 1;
1168 #if HAVE_TZNAME
1169 /* The tzset() call might have changed the value. */
1170 if (!(zone && *zone) && tp->tm_isdst >= 0)
1171 zone = tzname[tp->tm_isdst];
1172 #endif
1173 if (! zone)
1174 zone = ""; /* POSIX.2 requires the empty string here. */
1176 cpy (strlen (zone), zone);
1177 break;
1179 case 'z': /* GNU extension. */
1180 if (tp->tm_isdst < 0)
1181 break;
1184 int diff;
1185 #if HAVE_TM_GMTOFF
1186 diff = tp->tm_gmtoff;
1187 #else
1188 if (ut)
1189 diff = 0;
1190 else
1192 struct tm gtm;
1193 struct tm ltm;
1194 time_t lt;
1196 ltm = *tp;
1197 lt = mktime (&ltm);
1199 if (lt == (time_t) -1)
1201 /* mktime returns -1 for errors, but -1 is also a
1202 valid time_t value. Check whether an error really
1203 occurred. */
1204 struct tm tm;
1206 if (! localtime_r (&lt, &tm)
1207 || ((ltm.tm_sec ^ tm.tm_sec)
1208 | (ltm.tm_min ^ tm.tm_min)
1209 | (ltm.tm_hour ^ tm.tm_hour)
1210 | (ltm.tm_mday ^ tm.tm_mday)
1211 | (ltm.tm_mon ^ tm.tm_mon)
1212 | (ltm.tm_year ^ tm.tm_year)))
1213 break;
1216 if (! gmtime_r (&lt, &gtm))
1217 break;
1219 diff = tm_diff (&ltm, &gtm);
1221 #endif
1223 if (diff < 0)
1225 add (1, *p = '-');
1226 diff = -diff;
1228 else
1229 add (1, *p = '+');
1231 diff /= 60;
1232 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1235 case '\0': /* GNU extension: % at end of format. */
1236 --f;
1237 /* Fall through. */
1238 default:
1239 /* Unknown format; output the format, including the '%',
1240 since this is most likely the right thing to do if a
1241 multibyte string has been misparsed. */
1242 bad_format:
1244 int flen;
1245 for (flen = 1; f[1 - flen] != '%'; flen++)
1246 continue;
1247 cpy (flen, &f[1 - flen]);
1249 break;
1253 if (p && i < maxsize)
1254 *p = '\0';
1255 return i;
1259 #ifdef emacs
1260 /* For Emacs we have a separate interface which corresponds to the normal
1261 strftime function and does not have the extra information whether the
1262 TP arguments comes from a `gmtime' call or not. */
1263 size_t
1264 emacs_strftime (s, maxsize, format, tp)
1265 char *s;
1266 size_t maxsize;
1267 const char *format;
1268 const struct tm *tp;
1270 return my_strftime (s, maxsize, format, tp, 0);
1272 #endif