*** empty log message ***
[coreutils.git] / lib / strftime.c
blob18977d17822e0dbb76717a17d4b6722050e10e19
1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
3 NOTE: The canonical source of this file is maintained with the GNU C Library.
4 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA. */
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #ifdef _LIBC
26 # define HAVE_LIMITS_H 1
27 # define HAVE_MBLEN 1
28 # define HAVE_MBRLEN 1
29 # define HAVE_STRUCT_ERA_ENTRY 1
30 # define HAVE_TM_GMTOFF 1
31 # define HAVE_TM_ZONE 1
32 # define HAVE_TZNAME 1
33 # define HAVE_TZSET 1
34 # define MULTIBYTE_IS_FORMAT_SAFE 1
35 # define STDC_HEADERS 1
36 # include "../locale/localeinfo.h"
37 #endif
39 #if defined emacs && !defined HAVE_BCOPY
40 # define HAVE_MEMCPY 1
41 #endif
43 #include <ctype.h>
44 #include <sys/types.h> /* Some systems define `time_t' here. */
46 #ifdef TIME_WITH_SYS_TIME
47 # include <sys/time.h>
48 # include <time.h>
49 #else
50 # ifdef HAVE_SYS_TIME_H
51 # include <sys/time.h>
52 # else
53 # include <time.h>
54 # endif
55 #endif
56 #if HAVE_TZNAME
57 extern char *tzname[];
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 #if HAVE_LIMITS_H
81 # include <limits.h>
82 #endif
84 #if STDC_HEADERS
85 # include <stddef.h>
86 # include <stdlib.h>
87 # include <string.h>
88 #else
89 # ifndef HAVE_MEMCPY
90 # define memcpy(d, s, n) bcopy ((s), (d), (n))
91 # endif
92 #endif
94 #ifdef _LIBC
95 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
96 #else
97 # ifndef HAVE_MEMPCPY
98 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
99 # endif
100 #endif
102 #ifndef __P
103 # if defined __GNUC__ || (defined __STDC__ && __STDC__)
104 # define __P(args) args
105 # else
106 # define __P(args) ()
107 # endif /* GCC. */
108 #endif /* Not __P. */
110 #ifndef PTR
111 # ifdef __STDC__
112 # define PTR void *
113 # else
114 # define PTR char *
115 # endif
116 #endif
118 #ifndef CHAR_BIT
119 # define CHAR_BIT 8
120 #endif
122 #ifndef NULL
123 # define NULL 0
124 #endif
126 #define TYPE_SIGNED(t) ((t) -1 < 0)
128 /* Bound on length of the string representing an integer value of type t.
129 Subtract one for the sign bit if t is signed;
130 302 / 1000 is log10 (2) rounded up;
131 add one for integer division truncation;
132 add one more for a minus sign if t is signed. */
133 #define INT_STRLEN_BOUND(t) \
134 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
136 #define TM_YEAR_BASE 1900
138 #ifndef __isleap
139 /* Nonzero if YEAR is a leap year (every 4 years,
140 except every 100th isn't, and every 400th is). */
141 # define __isleap(year) \
142 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
143 #endif
146 #ifdef _LIBC
147 # define my_strftime_gmtime_r __gmtime_r
148 # define my_strftime_localtime_r __localtime_r
149 # define tzname __tzname
150 # define tzset __tzset
151 #else
153 /* If we're a strftime substitute in a GNU program, then prefer gmtime
154 to gmtime_r, since many gmtime_r implementations are buggy.
155 Similarly for localtime_r. */
157 # if ! HAVE_TM_GMTOFF
158 static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
159 static struct tm *
160 my_strftime_gmtime_r (const time_t *t, struct tm *tp)
162 struct tm *l = gmtime (t);
163 if (! l)
164 return 0;
165 *tp = *l;
166 return tp;
168 # endif /* ! HAVE_TM_GMTOFF */
170 static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
171 static struct tm *
172 my_strftime_localtime_r (const time_t *t, struct tm *tp)
174 struct tm *l = localtime (t);
175 if (! l)
176 return 0;
177 *tp = *l;
178 return tp;
180 #endif /* ! defined _LIBC */
183 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
184 /* Some systems lack the `memset' function and we don't want to
185 introduce additional dependencies. */
186 /* The SGI compiler reportedly barfs on the trailing null
187 if we use a string constant as the initializer. 28 June 1997, rms. */
188 static const char spaces[16] = /* " " */
189 { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
190 static const char zeroes[16] = /* "0000000000000000" */
191 { '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0' };
193 # define memset_space(P, Len) \
194 do { \
195 int _len = (Len); \
197 do \
199 int _this = _len > 16 ? 16 : _len; \
200 (P) = MEMPCPY ((P), spaces, _this); \
201 _len -= _this; \
203 while (_len > 0); \
204 } while (0)
206 # define memset_zero(P, Len) \
207 do { \
208 int _len = (Len); \
210 do \
212 int _this = _len > 16 ? 16 : _len; \
213 (P) = MEMPCPY ((P), zeroes, _this); \
214 _len -= _this; \
216 while (_len > 0); \
217 } while (0)
218 #else
219 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
220 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
221 #endif
223 #define add(n, f) \
224 do \
226 int _n = (n); \
227 int _delta = width - _n; \
228 int _incr = _n + (_delta > 0 ? _delta : 0); \
229 if (i + _incr >= maxsize) \
230 return 0; \
231 if (p) \
233 if (_delta > 0) \
235 if (pad == '0') \
236 memset_zero (p, _delta); \
237 else \
238 memset_space (p, _delta); \
240 f; \
241 p += _n; \
243 i += _incr; \
244 } while (0)
246 #define cpy(n, s) \
247 add ((n), \
248 if (to_lowcase) \
249 memcpy_lowcase (p, (s), _n); \
250 else if (to_uppcase) \
251 memcpy_uppcase (p, (s), _n); \
252 else \
253 memcpy ((PTR) p, (PTR) (s), _n))
257 #ifdef _LIBC
258 # define TOUPPER(Ch) toupper (Ch)
259 # define TOLOWER(Ch) tolower (Ch)
260 #else
261 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
262 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
263 #endif
264 /* We don't use `isdigit' here since the locale dependent
265 interpretation is not what we want here. We only need to accept
266 the arabic digits in the ASCII range. One day there is perhaps a
267 more reliable way to accept other sets of digits. */
268 #define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
270 static char *memcpy_lowcase __P ((char *dest, const char *src, size_t len));
272 static char *
273 memcpy_lowcase (char *dest, const char *src, size_t len)
275 while (len-- > 0)
276 dest[len] = TOLOWER ((unsigned char) src[len]);
277 return dest;
280 static char *memcpy_uppcase __P ((char *dest, const char *src, size_t len));
282 static char *
283 memcpy_uppcase (char *dest, const char *src, size_t len)
285 while (len-- > 0)
286 dest[len] = TOUPPER ((unsigned char) src[len]);
287 return dest;
291 #if ! HAVE_TM_GMTOFF
292 /* Yield the difference between *A and *B,
293 measured in seconds, ignoring leap seconds. */
294 # define tm_diff ftime_tm_diff
295 static int tm_diff __P ((const struct tm *, const struct tm *));
296 static int
297 tm_diff (const struct tm *a, const struct tm *b)
299 /* Compute intervening leap days correctly even if year is negative.
300 Take care to avoid int overflow in leap day calculations,
301 but it's OK to assume that A and B are close to each other. */
302 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
303 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
304 int a100 = a4 / 25 - (a4 % 25 < 0);
305 int b100 = b4 / 25 - (b4 % 25 < 0);
306 int a400 = a100 >> 2;
307 int b400 = b100 >> 2;
308 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
309 int years = a->tm_year - b->tm_year;
310 int days = (365 * years + intervening_leap_days
311 + (a->tm_yday - b->tm_yday));
312 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
313 + (a->tm_min - b->tm_min))
314 + (a->tm_sec - b->tm_sec));
316 #endif /* ! HAVE_TM_GMTOFF */
320 /* The number of days from the first day of the first ISO week of this
321 year to the year day YDAY with week day WDAY. ISO weeks start on
322 Monday; the first ISO week has the year's first Thursday. YDAY may
323 be as small as YDAY_MINIMUM. */
324 #define ISO_WEEK_START_WDAY 1 /* Monday */
325 #define ISO_WEEK1_WDAY 4 /* Thursday */
326 #define YDAY_MINIMUM (-366)
327 static int iso_week_days __P ((int, int));
328 #ifdef __GNUC__
329 __inline__
330 #endif
331 static int
332 iso_week_days (int yday, int wday)
334 /* Add enough to the first operand of % to make it nonnegative. */
335 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
336 return (yday
337 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
338 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
342 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
343 static char const weekday_name[][10] =
345 "Sunday", "Monday", "Tuesday", "Wednesday",
346 "Thursday", "Friday", "Saturday"
348 static char const month_name[][10] =
350 "January", "February", "March", "April", "May", "June",
351 "July", "August", "September", "October", "November", "December"
353 #endif
356 #ifdef emacs
357 # define my_strftime emacs_strftimeu
358 # define ut_argument , ut
359 # define ut_argument_spec int ut;
360 # define ut_argument_spec_iso , int ut
361 #else
362 # define my_strftime strftime
363 # define ut_argument
364 # define ut_argument_spec
365 # define ut_argument_spec_iso
366 /* We don't have this information in general. */
367 # define ut 0
368 #endif
370 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
371 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
372 Work around this bug by copying *tp before it might be munged. */
373 size_t _strftime_copytm __P ((char *, size_t, const char *,
374 const struct tm * ut_argument_spec_iso));
375 size_t
376 my_strftime (s, maxsize, format, tp ut_argument)
377 char *s;
378 size_t maxsize;
379 const char *format;
380 const struct tm *tp;
381 ut_argument_spec
383 struct tm tmcopy;
384 tmcopy = *tp;
385 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
387 # undef my_strftime
388 # define my_strftime(S, Maxsize, Format, Tp) \
389 _strftime_copytm (S, Maxsize, Format, Tp)
390 #endif
393 /* Write information from TP into S according to the format
394 string FORMAT, writing no more that MAXSIZE characters
395 (including the terminating '\0') and returning number of
396 characters written. If S is NULL, nothing will be written
397 anywhere, so to determine how many characters would be
398 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
399 size_t
400 my_strftime (char *s, size_t maxsize, const char *format, const struct tm *tp
401 ut_argument_spec)
403 int hour12 = tp->tm_hour;
404 #ifdef _NL_CURRENT
405 /* We cannot make the following values variables since we must delay
406 the evaluation of these values until really needed since some
407 expressions might not be valid in every situation. The `struct tm'
408 might be generated by a strptime() call that initialized
409 only a few elements. Dereference the pointers only if the format
410 requires this. Then it is ok to fail if the pointers are invalid. */
411 # define a_wkday _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday)
412 # define f_wkday _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday)
413 # define a_month _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon)
414 # define f_month _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon)
415 # define ampm _NL_CURRENT (LC_TIME, tp->tm_hour > 11 ? PM_STR : AM_STR)
417 # define aw_len strlen (a_wkday)
418 # define am_len strlen (a_month)
419 # define ap_len strlen (ampm)
420 #else
421 # if !HAVE_STRFTIME
422 # define f_wkday (weekday_name[tp->tm_wday])
423 # define f_month (month_name[tp->tm_mon])
424 # define a_wkday f_wkday
425 # define a_month f_month
426 # define ampm ("AMPM" + 2 * (tp->tm_hour > 11))
428 size_t aw_len = 3;
429 size_t am_len = 3;
430 size_t ap_len = 2;
431 # endif
432 #endif
433 const char *zone;
434 size_t i = 0;
435 char *p = s;
436 const char *f;
438 zone = NULL;
439 #if HAVE_TM_ZONE
440 /* The POSIX test suite assumes that setting
441 the environment variable TZ to a new value before calling strftime()
442 will influence the result (the %Z format) even if the information in
443 TP is computed with a totally different time zone.
444 This is bogus: though POSIX allows bad behavior like this,
445 POSIX does not require it. Do the right thing instead. */
446 zone = (const char *) tp->tm_zone;
447 #endif
448 #if HAVE_TZNAME
449 if (ut)
451 if (! (zone && *zone))
452 zone = "GMT";
454 else
456 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
457 time zone names contained in the external variable `tzname' shall
458 be set as if the tzset() function had been called. */
459 # if HAVE_TZSET
460 tzset ();
461 # endif
463 #endif
465 if (hour12 > 12)
466 hour12 -= 12;
467 else
468 if (hour12 == 0)
469 hour12 = 12;
471 for (f = format; *f != '\0'; ++f)
473 int pad = 0; /* Padding for number ('-', '_', or 0). */
474 int modifier; /* Field modifier ('E', 'O', or 0). */
475 int digits; /* Max digits for numeric format. */
476 int number_value; /* Numeric value to be printed. */
477 int negative_number; /* 1 if the number is negative. */
478 const char *subfmt;
479 char *bufp;
480 char buf[1 + (sizeof (int) < sizeof (time_t)
481 ? INT_STRLEN_BOUND (time_t)
482 : INT_STRLEN_BOUND (int))];
483 int width = -1;
484 int to_lowcase = 0;
485 int to_uppcase = 0;
486 int change_case = 0;
487 int format_char;
489 #if DO_MULTIBYTE
491 switch (*f)
493 case '%':
494 break;
496 case '\b': case '\t': case '\n':
497 case '\v': case '\f': case '\r':
498 case ' ': case '!': case '"': case '#': case '&': case'\'':
499 case '(': case ')': case '*': case '+': case ',': case '-':
500 case '.': case '/': case '0': case '1': case '2': case '3':
501 case '4': case '5': case '6': case '7': case '8': case '9':
502 case ':': case ';': case '<': case '=': case '>': case '?':
503 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
504 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
505 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
506 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
507 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
508 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
509 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
510 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
511 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
512 case 'x': case 'y': case 'z': case '{': case '|': case '}':
513 case '~':
514 /* The C Standard requires these 97 characters (plus '%', '\a') to
515 be in the basic execution character set. None of these
516 characters can start a multibyte sequence, so they need
517 not be analyzed further. Some old compilers object to
518 '\a', so don't bother optimizing for it. */
519 add (1, *p = *f);
520 continue;
522 default:
523 /* Copy this multibyte sequence until we reach its end, find
524 an error, or come back to the initial shift state. */
526 mbstate_t mbstate = mbstate_zero;
527 size_t len = 0;
531 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
533 if (bytes == 0)
534 break;
536 if (bytes == (size_t) -2)
538 len += strlen (f + len);
539 break;
542 if (bytes == (size_t) -1)
544 len++;
545 break;
548 len += bytes;
550 while (! mbsinit (&mbstate));
552 cpy (len, f);
553 f += len - 1;
554 continue;
558 #else /* ! DO_MULTIBYTE */
560 /* Either multibyte encodings are not supported, or they are
561 safe for formats, so any non-'%' byte can be copied through. */
562 if (*f != '%')
564 add (1, *p = *f);
565 continue;
568 #endif /* ! DO_MULTIBYTE */
570 /* Check for flags that can modify a format. */
571 while (1)
573 switch (*++f)
575 /* This influences the number formats. */
576 case '_':
577 case '-':
578 case '0':
579 pad = *f;
580 continue;
582 /* This changes textual output. */
583 case '^':
584 to_uppcase = 1;
585 continue;
586 case '#':
587 change_case = 1;
588 continue;
590 default:
591 break;
593 break;
596 /* As a GNU extension we allow to specify the field width. */
597 if (ISDIGIT (*f))
599 width = 0;
602 width *= 10;
603 width += *f - '0';
604 ++f;
606 while (ISDIGIT (*f));
609 /* Check for modifiers. */
610 switch (*f)
612 case 'E':
613 case 'O':
614 modifier = *f++;
615 break;
617 default:
618 modifier = 0;
619 break;
622 /* Now do the specified format. */
623 format_char = *f;
624 switch (format_char)
626 #define DO_NUMBER(d, v) \
627 digits = width == -1 ? d : width; \
628 number_value = v; goto do_number
629 #define DO_NUMBER_SPACEPAD(d, v) \
630 digits = width == -1 ? d : width; \
631 number_value = v; goto do_number_spacepad
633 case '%':
634 if (modifier != 0)
635 goto bad_format;
636 add (1, *p = *f);
637 break;
639 case 'a':
640 if (modifier != 0)
641 goto bad_format;
642 if (change_case)
644 to_uppcase = 1;
645 to_lowcase = 0;
647 #if defined _NL_CURRENT || !HAVE_STRFTIME
648 cpy (aw_len, a_wkday);
649 break;
650 #else
651 goto underlying_strftime;
652 #endif
654 case 'A':
655 if (modifier != 0)
656 goto bad_format;
657 if (change_case)
659 to_uppcase = 1;
660 to_lowcase = 0;
662 #if defined _NL_CURRENT || !HAVE_STRFTIME
663 cpy (strlen (f_wkday), f_wkday);
664 break;
665 #else
666 goto underlying_strftime;
667 #endif
669 case 'b':
670 case 'h': /* POSIX.2 extension. */
671 if (modifier != 0)
672 goto bad_format;
673 #if defined _NL_CURRENT || !HAVE_STRFTIME
674 cpy (am_len, a_month);
675 break;
676 #else
677 goto underlying_strftime;
678 #endif
680 case 'B':
681 if (modifier != 0)
682 goto bad_format;
683 if (change_case)
685 to_uppcase = 1;
686 to_lowcase = 0;
688 #if defined _NL_CURRENT || !HAVE_STRFTIME
689 cpy (strlen (f_month), f_month);
690 break;
691 #else
692 goto underlying_strftime;
693 #endif
695 case 'c':
696 if (modifier == 'O')
697 goto bad_format;
698 #ifdef _NL_CURRENT
699 if (! (modifier == 'E'
700 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT)) != '\0'))
701 subfmt = _NL_CURRENT (LC_TIME, D_T_FMT);
702 #else
703 # if HAVE_STRFTIME
704 goto underlying_strftime;
705 # else
706 subfmt = "%a %b %e %H:%M:%S %Y";
707 # endif
708 #endif
710 subformat:
712 char *old_start = p;
713 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp);
714 add (len, my_strftime (p, maxsize - i, subfmt, tp));
716 if (to_uppcase)
717 while (old_start < p)
719 *old_start = TOUPPER ((unsigned char) *old_start);
720 ++old_start;
723 break;
725 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
726 underlying_strftime:
728 /* The relevant information is available only via the
729 underlying strftime implementation, so use that. */
730 char ufmt[4];
731 char *u = ufmt;
732 char ubuf[1024]; /* enough for any single format in practice */
733 size_t len;
734 *u++ = '%';
735 if (modifier != 0)
736 *u++ = modifier;
737 *u++ = format_char;
738 *u = '\0';
739 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
740 if (len == 0 && ubuf[0] != '\0')
741 return 0;
742 cpy (len, ubuf);
744 break;
745 #endif
747 case 'C': /* POSIX.2 extension. */
748 if (modifier == 'O')
749 goto bad_format;
750 if (modifier == 'E')
752 #if HAVE_STRUCT_ERA_ENTRY
753 struct era_entry *era = _nl_get_era_entry (tp);
754 if (era)
756 size_t len = strlen (era->name_fmt);
757 cpy (len, era->name_fmt);
758 break;
760 #else
761 # if HAVE_STRFTIME
762 goto underlying_strftime;
763 # endif
764 #endif
768 int year = tp->tm_year + TM_YEAR_BASE;
769 DO_NUMBER (1, year / 100 - (year % 100 < 0));
772 case 'x':
773 if (modifier == 'O')
774 goto bad_format;
775 #ifdef _NL_CURRENT
776 if (! (modifier == 'E'
777 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_FMT)) != '\0'))
778 subfmt = _NL_CURRENT (LC_TIME, D_FMT);
779 goto subformat;
780 #else
781 # if HAVE_STRFTIME
782 goto underlying_strftime;
783 # else
784 /* Fall through. */
785 # endif
786 #endif
787 case 'D': /* POSIX.2 extension. */
788 if (modifier != 0)
789 goto bad_format;
790 subfmt = "%m/%d/%y";
791 goto subformat;
793 case 'd':
794 if (modifier == 'E')
795 goto bad_format;
797 DO_NUMBER (2, tp->tm_mday);
799 case 'e': /* POSIX.2 extension. */
800 if (modifier == 'E')
801 goto bad_format;
803 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
805 /* All numeric formats set DIGITS and NUMBER_VALUE and then
806 jump to one of these two labels. */
808 do_number_spacepad:
809 /* Force `_' flag unless overwritten by `0' flag. */
810 if (pad != '0')
811 pad = '_';
813 do_number:
814 /* Format the number according to the MODIFIER flag. */
816 if (modifier == 'O' && 0 <= number_value)
818 #ifdef _NL_CURRENT
819 /* Get the locale specific alternate representation of
820 the number NUMBER_VALUE. If none exist NULL is returned. */
821 const char *cp = _nl_get_alt_digit (number_value);
823 if (cp != NULL)
825 size_t digitlen = strlen (cp);
826 if (digitlen != 0)
828 cpy (digitlen, cp);
829 break;
832 #else
833 # if HAVE_STRFTIME
834 goto underlying_strftime;
835 # endif
836 #endif
839 unsigned int u = number_value;
841 bufp = buf + sizeof (buf);
842 negative_number = number_value < 0;
844 if (negative_number)
845 u = -u;
848 *--bufp = u % 10 + '0';
849 while ((u /= 10) != 0);
852 do_number_sign_and_padding:
853 if (negative_number)
854 *--bufp = '-';
856 if (pad != '-')
858 int padding = digits - (buf + sizeof (buf) - bufp);
860 if (pad == '_')
862 while (0 < padding--)
863 *--bufp = ' ';
865 else
867 bufp += negative_number;
868 while (0 < padding--)
869 *--bufp = '0';
870 if (negative_number)
871 *--bufp = '-';
875 cpy (buf + sizeof (buf) - bufp, bufp);
876 break;
878 case 'F':
879 if (modifier != 0)
880 goto bad_format;
881 subfmt = "%Y-%m-%d";
882 goto subformat;
884 case 'H':
885 if (modifier == 'E')
886 goto bad_format;
888 DO_NUMBER (2, tp->tm_hour);
890 case 'I':
891 if (modifier == 'E')
892 goto bad_format;
894 DO_NUMBER (2, hour12);
896 case 'k': /* GNU extension. */
897 if (modifier == 'E')
898 goto bad_format;
900 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
902 case 'l': /* GNU extension. */
903 if (modifier == 'E')
904 goto bad_format;
906 DO_NUMBER_SPACEPAD (2, hour12);
908 case 'j':
909 if (modifier == 'E')
910 goto bad_format;
912 DO_NUMBER (3, 1 + tp->tm_yday);
914 case 'M':
915 if (modifier == 'E')
916 goto bad_format;
918 DO_NUMBER (2, tp->tm_min);
920 case 'm':
921 if (modifier == 'E')
922 goto bad_format;
924 DO_NUMBER (2, tp->tm_mon + 1);
926 case 'n': /* POSIX.2 extension. */
927 add (1, *p = '\n');
928 break;
930 case 'P':
931 to_lowcase = 1;
932 #if !defined _NL_CURRENT && HAVE_STRFTIME
933 format_char = 'p';
934 #endif
935 /* FALLTHROUGH */
937 case 'p':
938 if (change_case)
940 to_uppcase = 0;
941 to_lowcase = 1;
943 #if defined _NL_CURRENT || !HAVE_STRFTIME
944 cpy (ap_len, ampm);
945 break;
946 #else
947 goto underlying_strftime;
948 #endif
950 case 'R': /* GNU extension. */
951 subfmt = "%H:%M";
952 goto subformat;
954 case 'r': /* POSIX.2 extension. */
955 #ifdef _NL_CURRENT
956 if (*(subfmt = _NL_CURRENT (LC_TIME, T_FMT_AMPM)) == '\0')
957 #endif
958 subfmt = "%I:%M:%S %p";
959 goto subformat;
961 case 'S':
962 if (modifier == 'E')
963 goto bad_format;
965 DO_NUMBER (2, tp->tm_sec);
967 case 's': /* GNU extension. */
969 struct tm ltm;
970 time_t t;
972 ltm = *tp;
973 t = mktime (&ltm);
975 /* Generate string value for T using time_t arithmetic;
976 this works even if sizeof (long) < sizeof (time_t). */
978 bufp = buf + sizeof (buf);
979 negative_number = t < 0;
983 int d = t % 10;
984 t /= 10;
986 if (negative_number)
988 d = -d;
990 /* Adjust if division truncates to minus infinity. */
991 if (0 < -1 % 10 && d < 0)
993 t++;
994 d += 10;
998 *--bufp = d + '0';
1000 while (t != 0);
1002 digits = 1;
1003 goto do_number_sign_and_padding;
1006 case 'X':
1007 if (modifier == 'O')
1008 goto bad_format;
1009 #ifdef _NL_CURRENT
1010 if (! (modifier == 'E'
1011 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_T_FMT)) != '\0'))
1012 subfmt = _NL_CURRENT (LC_TIME, T_FMT);
1013 goto subformat;
1014 #else
1015 # if HAVE_STRFTIME
1016 goto underlying_strftime;
1017 # else
1018 /* Fall through. */
1019 # endif
1020 #endif
1021 case 'T': /* POSIX.2 extension. */
1022 subfmt = "%H:%M:%S";
1023 goto subformat;
1025 case 't': /* POSIX.2 extension. */
1026 add (1, *p = '\t');
1027 break;
1029 case 'u': /* POSIX.2 extension. */
1030 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1032 case 'U':
1033 if (modifier == 'E')
1034 goto bad_format;
1036 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1038 case 'V':
1039 case 'g': /* GNU extension. */
1040 case 'G': /* GNU extension. */
1041 if (modifier == 'E')
1042 goto bad_format;
1044 int year = tp->tm_year + TM_YEAR_BASE;
1045 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1047 if (days < 0)
1049 /* This ISO week belongs to the previous year. */
1050 year--;
1051 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1052 tp->tm_wday);
1054 else
1056 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1057 tp->tm_wday);
1058 if (0 <= d)
1060 /* This ISO week belongs to the next year. */
1061 year++;
1062 days = d;
1066 switch (*f)
1068 case 'g':
1069 DO_NUMBER (2, (year % 100 + 100) % 100);
1071 case 'G':
1072 DO_NUMBER (1, year);
1074 default:
1075 DO_NUMBER (2, days / 7 + 1);
1079 case 'W':
1080 if (modifier == 'E')
1081 goto bad_format;
1083 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1085 case 'w':
1086 if (modifier == 'E')
1087 goto bad_format;
1089 DO_NUMBER (1, tp->tm_wday);
1091 case 'Y':
1092 if (modifier == 'E')
1094 #if HAVE_STRUCT_ERA_ENTRY
1095 struct era_entry *era = _nl_get_era_entry (tp);
1096 if (era)
1098 subfmt = strchr (era->name_fmt, '\0') + 1;
1099 goto subformat;
1101 #else
1102 # if HAVE_STRFTIME
1103 goto underlying_strftime;
1104 # endif
1105 #endif
1107 if (modifier == 'O')
1108 goto bad_format;
1109 else
1110 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1112 case 'y':
1113 if (modifier == 'E')
1115 #if HAVE_STRUCT_ERA_ENTRY
1116 struct era_entry *era = _nl_get_era_entry (tp);
1117 if (era)
1119 int delta = tp->tm_year - era->start_date[0];
1120 DO_NUMBER (1, (era->offset
1121 + (era->direction == '-' ? -delta : delta)));
1123 #else
1124 # if HAVE_STRFTIME
1125 goto underlying_strftime;
1126 # endif
1127 #endif
1129 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1131 case 'Z':
1132 if (change_case)
1134 to_uppcase = 0;
1135 to_lowcase = 1;
1138 #if HAVE_TZNAME
1139 /* The tzset() call might have changed the value. */
1140 if (!(zone && *zone) && tp->tm_isdst >= 0)
1141 zone = tzname[tp->tm_isdst];
1142 #endif
1143 if (! zone)
1144 zone = ""; /* POSIX.2 requires the empty string here. */
1146 cpy (strlen (zone), zone);
1147 break;
1149 case 'z': /* GNU extension. */
1150 if (tp->tm_isdst < 0)
1151 break;
1154 int diff;
1155 #if HAVE_TM_GMTOFF
1156 diff = tp->tm_gmtoff;
1157 #else
1158 if (ut)
1159 diff = 0;
1160 else
1162 struct tm gtm;
1163 struct tm ltm;
1164 time_t lt;
1166 ltm = *tp;
1167 lt = mktime (&ltm);
1169 if (lt == (time_t) -1)
1171 /* mktime returns -1 for errors, but -1 is also a
1172 valid time_t value. Check whether an error really
1173 occurred. */
1174 struct tm tm;
1176 if (! my_strftime_localtime_r (&lt, &tm)
1177 || ((ltm.tm_sec ^ tm.tm_sec)
1178 | (ltm.tm_min ^ tm.tm_min)
1179 | (ltm.tm_hour ^ tm.tm_hour)
1180 | (ltm.tm_mday ^ tm.tm_mday)
1181 | (ltm.tm_mon ^ tm.tm_mon)
1182 | (ltm.tm_year ^ tm.tm_year)))
1183 break;
1186 if (! my_strftime_gmtime_r (&lt, &gtm))
1187 break;
1189 diff = tm_diff (&ltm, &gtm);
1191 #endif
1193 if (diff < 0)
1195 add (1, *p = '-');
1196 diff = -diff;
1198 else
1199 add (1, *p = '+');
1201 diff /= 60;
1202 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1205 case '\0': /* GNU extension: % at end of format. */
1206 --f;
1207 /* Fall through. */
1208 default:
1209 /* Unknown format; output the format, including the '%',
1210 since this is most likely the right thing to do if a
1211 multibyte string has been misparsed. */
1212 bad_format:
1214 int flen;
1215 for (flen = 1; f[1 - flen] != '%'; flen++)
1216 continue;
1217 cpy (flen, &f[1 - flen]);
1219 break;
1223 if (p && maxsize != 0)
1224 *p = '\0';
1225 return i;
1229 #ifdef emacs
1230 /* For Emacs we have a separate interface which corresponds to the normal
1231 strftime function and does not have the extra information whether the
1232 TP arguments comes from a `gmtime' call or not. */
1233 size_t
1234 emacs_strftime (s, maxsize, format, tp)
1235 char *s;
1236 size_t maxsize;
1237 const char *format;
1238 const struct tm *tp;
1240 return my_strftime (s, maxsize, format, tp, 0);
1242 #endif