1 /* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
3 NOTE: The canonical source of this file is maintained with the GNU C
4 Library. 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
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
14 GNU 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 Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
25 # define HAVE_LIMITS_H 1
27 # define HAVE_MBRLEN 1
28 # define HAVE_STRUCT_ERA_ENTRY 1
29 # define HAVE_TM_GMTOFF 1
30 # define HAVE_TM_ZONE 1
31 # define HAVE_TZNAME 1
33 # define MULTIBYTE_IS_FORMAT_SAFE 1
34 # define STDC_HEADERS 1
35 # include <ansidecl.h>
36 # include "../locale/localeinfo.h"
40 #include <sys/types.h> /* Some systems define `time_t' here. */
42 #ifdef TIME_WITH_SYS_TIME
43 # include <sys/time.h>
46 # ifdef HAVE_SYS_TIME_H
47 # include <sys/time.h>
53 extern char *tzname[];
56 /* Do multibyte processing if multibytes are supported, unless
57 multibyte sequences are safe in formats. Multibyte sequences are
58 safe if they cannot contain byte sequences that look like format
59 conversion specifications. The GNU C Library uses UTF8 multibyte
60 encoding, which is safe for formats, but strftime.c can be used
61 with other C libraries that use unsafe encodings. */
62 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
68 /* Simulate mbrlen with mblen as best we can. */
69 # define mbstate_t int
70 # define mbrlen(s, n, ps) mblen (s, n)
71 # define mbsinit(ps) (*(ps) == 0)
73 static const mbstate_t mbstate_zero;
85 # define memcpy(d, s, n) bcopy ((s), (d), (n))
89 #if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
90 #define __P(args) args
108 #define TYPE_SIGNED(t) ((t) -1 < 0)
110 /* Bound on length of the string representing an integer value of type t.
111 Subtract one for the sign bit if t is signed;
112 302 / 1000 is log10 (2) rounded up;
113 add one for integer division truncation;
114 add one more for a minus sign if t is signed. */
115 #define INT_STRLEN_BOUND(t) \
116 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 100 + 1 + TYPE_SIGNED (t))
118 #define TM_YEAR_BASE 1900
121 /* Nonzero if YEAR is a leap year (every 4 years,
122 except every 100th isn't, and every 400th is). */
123 #define __isleap(year) \
124 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
129 # define gmtime_r __gmtime_r
130 # define localtime_r __localtime_r
131 extern int __tz_compute __P ((time_t timer, const struct tm *tm));
133 # if ! HAVE_LOCALTIME_R
134 # if ! HAVE_TM_GMTOFF
135 /* Approximate gmtime_r as best we can in its absence. */
136 #define gmtime_r my_gmtime_r
137 static struct tm *gmtime_r __P ((const time_t *, struct tm *));
143 struct tm *l = gmtime (t);
149 # endif /* ! HAVE_TM_GMTOFF */
151 /* Approximate localtime_r as best we can in its absence. */
152 #define localtime_r my_localtime_r
153 static struct tm *localtime_r __P ((const time_t *, struct tm *));
159 struct tm *l = localtime (t);
165 # endif /* ! HAVE_LOCALTIME_R */
166 #endif /* ! defined (_LIBC) */
169 #if !defined (memset) && !defined (HAVE_MEMSET) && !defined (_LIBC)
170 /* Some systems lack the `memset' function and we don't want to
171 introduce additional dependencies. */
172 static const char spaces[16] = " ";
174 # define memset_space(P, Len) \
180 int _this = _len > 16 ? 16 : _len; \
181 memcpy ((P), spaces, _this); \
188 # define memset_space(P, Len) memset ((P), ' ', (Len))
195 int _delta = width - _n; \
196 i += _n + (_delta > 0 ? _delta : 0); \
203 memset_space (p, _delta); \
212 memcpy_lowcase (p, (s), _n); \
214 memcpy ((PTR) p, (PTR) (s), _n))
219 # define TOUPPER(Ch) toupper (Ch)
220 # define TOLOWER(Ch) tolower (Ch)
222 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
223 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
226 static char *memcpy_lowcase __P ((char *dest, const char *src, size_t len));
229 memcpy_lowcase (dest, src, len)
235 dest[len] = TOLOWER (src[len]);
240 /* Yield the difference between *A and *B,
241 measured in seconds, ignoring leap seconds. */
242 static int tm_diff __P ((const struct tm *, const struct tm *));
248 /* Compute intervening leap days correctly even if year is negative.
249 Take care to avoid int overflow in leap day calculations,
250 but it's OK to assume that A and B are close to each other. */
251 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
252 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
253 int a100 = a4 / 25 - (a4 % 25 < 0);
254 int b100 = b4 / 25 - (b4 % 25 < 0);
255 int a400 = a100 >> 2;
256 int b400 = b100 >> 2;
257 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
258 int years = a->tm_year - b->tm_year;
259 int days = (365 * years + intervening_leap_days
260 + (a->tm_yday - b->tm_yday));
261 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
262 + (a->tm_min - b->tm_min))
263 + (a->tm_sec - b->tm_sec));
265 #endif /* ! HAVE_TM_GMTOFF */
269 /* The number of days from the first day of the first ISO week of this
270 year to the year day YDAY with week day WDAY. ISO weeks start on
271 Monday; the first ISO week has the year's first Thursday. YDAY may
272 be as small as YDAY_MINIMUM. */
273 #define ISO_WEEK_START_WDAY 1 /* Monday */
274 #define ISO_WEEK1_WDAY 4 /* Thursday */
275 #define YDAY_MINIMUM (-366)
276 static int iso_week_days __P ((int, int));
281 iso_week_days (yday, wday)
285 /* Add enough to the first operand of % to make it nonnegative. */
286 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
288 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
289 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
294 static char const weekday_name[][10] =
296 "Sunday", "Monday", "Tuesday", "Wednesday",
297 "Thursday", "Friday", "Saturday"
299 static char const month_name[][10] =
301 "January", "February", "March", "April", "May", "June",
302 "July", "August", "September", "October", "November", "December"
306 /* Write information from TP into S according to the format
307 string FORMAT, writing no more that MAXSIZE characters
308 (including the terminating '\0') and returning number of
309 characters written. If S is NULL, nothing will be written
310 anywhere, so to determine how many characters would be
311 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
313 strftime (s, maxsize, format, tp)
319 int hour12 = tp->tm_hour;
321 const char *const a_wkday = _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday);
322 const char *const f_wkday = _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday);
323 const char *const a_month = _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon);
324 const char *const f_month = _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon);
325 const char *const ampm = _NL_CURRENT (LC_TIME,
326 hour12 > 11 ? PM_STR : AM_STR);
327 size_t aw_len = strlen (a_wkday);
328 size_t am_len = strlen (a_month);
329 size_t ap_len = strlen (ampm);
331 const char *const f_wkday = weekday_name[tp->tm_wday];
332 const char *const f_month = month_name[tp->tm_mon];
333 const char *const a_wkday = f_wkday;
334 const char *const a_month = f_month;
335 const char *const ampm = "AMPM" + 2 * (hour12 > 11);
340 size_t wkday_len = strlen (f_wkday);
341 size_t month_len = strlen (f_month);
349 #if !defined _LIBC && HAVE_TM_ZONE
350 /* XXX We have some problems here. First, the string pointed to by
351 tm_zone is dynamically allocated while loading the zone data. But
352 when another zone is loaded since the information in TP were
353 computed this would be a stale pointer.
354 The second problem is the POSIX test suite which assumes setting
355 the environment variable TZ to a new value before calling strftime()
356 will influence the result (the %Z format) even if the information in
357 TP is computed with a totally different time zone. --drepper@gnu */
358 zone = (const char *) tp->tm_zone;
361 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
362 time zone names contained in the external variable `tzname' shall
363 be set as if the tzset() function had been called. */
368 if (!(zone && *zone) && tp->tm_isdst >= 0)
369 zone = tzname[tp->tm_isdst];
372 zone = ""; /* POSIX.2 requires the empty string here. */
374 zonelen = strlen (zone);
379 if (hour12 == 0) hour12 = 12;
381 for (f = format; *f != '\0'; ++f)
383 int pad; /* Padding for number ('-', '_', or 0). */
384 int modifier; /* Field modifier ('E', 'O', or 0). */
385 int digits; /* Max digits for numeric format. */
386 int number_value; /* Numeric value to be printed. */
387 int negative_number; /* 1 if the number is negative. */
390 char buf[1 + (sizeof (int) < sizeof (time_t)
391 ? INT_STRLEN_BOUND (time_t)
392 : INT_STRLEN_BOUND (int))];
403 case '\a': case '\b': case '\t': case '\n':
404 case '\v': case '\f': case '\r':
405 case ' ': case '!': case '"': case '#': case '&': case'\'':
406 case '(': case ')': case '*': case '+': case ',': case '-':
407 case '.': case '/': case '0': case '1': case '2': case '3':
408 case '4': case '5': case '6': case '7': case '8': case '9':
409 case ':': case ';': case '<': case '=': case '>': case '?':
410 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
411 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
412 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
413 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
414 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
415 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
416 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
417 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
418 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
419 case 'x': case 'y': case 'z': case '{': case '|': case '}':
421 /* The C Standard requires these 98 characters (plus '%') to
422 be in the basic execution character set. None of these
423 characters can start a multibyte sequence, so they need
424 not be analyzed further. */
429 /* Copy this multibyte sequence until we reach its end, find
430 an error, or come back to the initial shift state. */
432 mbstate_t mbstate = mbstate_zero;
437 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
442 if (bytes == (size_t) -2 || bytes == (size_t) -1)
450 while (! mbsinit (&mbstate));
457 #else /* ! DO_MULTIBYTE */
459 /* Either multibyte encodings are not supported, or they are
460 safe for formats, so any non-'%' byte can be copied through. */
467 #endif /* ! DO_MULTIBYTE */
469 /* Check for flags that can modify a number format. */
488 /* As a GNU extension we allow to specify the field width. */
497 while (isdigit (*++f));
500 /* Check for modifiers. */
513 /* Now do the specified format. */
516 #define DO_NUMBER(d, v) \
517 digits = d; number_value = v; goto do_number
518 #define DO_NUMBER_SPACEPAD(d, v) \
519 digits = d; number_value = v; goto do_number_spacepad
530 cpy (aw_len, a_wkday);
536 cpy (wkday_len, f_wkday);
540 case 'h': /* POSIX.2 extension. */
543 cpy (am_len, a_month);
549 cpy (month_len, f_month);
556 if (! (modifier == 'E'
557 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT)) != '\0'))
558 subfmt = _NL_CURRENT (LC_TIME, D_T_FMT);
560 subfmt = "%a %b %e %H:%M:%S %Y";
565 size_t len = strftime (NULL, maxsize - i, subfmt, tp);
566 if (len == 0 && *subfmt)
568 add (len, strftime (p, maxsize - i, subfmt, tp));
572 case 'C': /* POSIX.2 extension. */
575 #if HAVE_STRUCT_ERA_ENTRY
578 struct era_entry *era = _nl_get_era_entry (tp);
581 size_t len = strlen (era->name_fmt);
582 cpy (len, era->name_fmt);
588 int year = tp->tm_year + TM_YEAR_BASE;
589 DO_NUMBER (1, year / 100 - (year % 100 < 0));
596 if (! (modifier == 'E'
597 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_FMT)) != '\0'))
598 subfmt = _NL_CURRENT (LC_TIME, D_FMT);
602 case 'D': /* POSIX.2 extension. */
612 DO_NUMBER (2, tp->tm_mday);
614 case 'e': /* POSIX.2 extension. */
618 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
620 /* All numeric formats set DIGITS and NUMBER_VALUE and then
621 jump to one of these two labels. */
624 /* Force `_' flag unless overwritten by `0' flag. */
629 /* Format the number according to the MODIFIER flag. */
632 if (modifier == 'O' && 0 <= number_value)
634 /* Get the locale specific alternate representation of
635 the number NUMBER_VALUE. If none exist NULL is returned. */
636 const char *cp = _nl_get_alt_digit (number_value);
640 size_t digitlen = strlen (cp);
650 unsigned int u = number_value;
652 bufp = buf + sizeof (buf);
653 negative_number = number_value < 0;
659 *--bufp = u % 10 + '0';
660 while ((u /= 10) != 0);
663 do_number_sign_and_padding:
669 int padding = digits - (buf + sizeof (buf) - bufp);
673 while (0 < padding--)
678 bufp += negative_number;
679 while (0 < padding--)
686 cpy (buf + sizeof (buf) - bufp, bufp);
694 DO_NUMBER (2, tp->tm_hour);
700 DO_NUMBER (2, hour12);
702 case 'k': /* GNU extension. */
706 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
708 case 'l': /* GNU extension. */
712 DO_NUMBER_SPACEPAD (2, hour12);
718 DO_NUMBER (3, 1 + tp->tm_yday);
724 DO_NUMBER (2, tp->tm_min);
730 DO_NUMBER (2, tp->tm_mon + 1);
732 case 'n': /* POSIX.2 extension. */
744 case 'R': /* GNU extension. */
748 case 'r': /* POSIX.2 extension. */
750 if (*(subfmt = _NL_CURRENT (LC_TIME, T_FMT_AMPM)) == '\0')
752 subfmt = "%I:%M:%S %p";
759 DO_NUMBER (2, tp->tm_sec);
761 case 's': /* GNU extension. */
769 /* Generate string value for T using time_t arithmetic;
770 this works even if sizeof (long) < sizeof (time_t). */
772 bufp = buf + sizeof (buf);
773 negative_number = t < 0;
784 /* Adjust if division truncates to minus infinity. */
785 if (0 < -1 % 10 && d < 0)
797 goto do_number_sign_and_padding;
804 if (! (modifier == 'E'
805 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_T_FMT)) != '\0'))
806 subfmt = _NL_CURRENT (LC_TIME, T_FMT);
810 case 'T': /* POSIX.2 extension. */
814 case 't': /* POSIX.2 extension. */
818 case 'u': /* POSIX.2 extension. */
819 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
825 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
828 case 'g': /* GNU extension. */
829 case 'G': /* GNU extension. */
833 int year = tp->tm_year + TM_YEAR_BASE;
834 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
838 /* This ISO week belongs to the previous year. */
840 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
845 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
849 /* This ISO week belongs to the next year. */
858 DO_NUMBER (2, (year % 100 + 100) % 100);
864 DO_NUMBER (2, days / 7 + 1);
872 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
878 DO_NUMBER (1, tp->tm_wday);
881 #if HAVE_STRUCT_ERA_ENTRY
884 struct era_entry *era = _nl_get_era_entry (tp);
887 subfmt = strchr (era->name_fmt, '\0') + 1;
895 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
898 #if HAVE_STRUCT_ERA_ENTRY
901 struct era_entry *era = _nl_get_era_entry (tp);
904 int delta = tp->tm_year - era->start_date[0];
905 DO_NUMBER (1, (era->offset
906 + (era->direction == '-' ? -delta : delta)));
910 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
916 case 'z': /* GNU extension. */
917 if (tp->tm_isdst < 0)
923 diff = tp->tm_gmtoff;
932 if (lt == (time_t) -1)
934 /* mktime returns -1 for errors, but -1 is also a
935 valid time_t value. Check whether an error really
938 localtime_r (<, &tm);
940 if ((ltm.tm_sec ^ tm.tm_sec)
941 | (ltm.tm_min ^ tm.tm_min)
942 | (ltm.tm_hour ^ tm.tm_hour)
943 | (ltm.tm_mday ^ tm.tm_mday)
944 | (ltm.tm_mon ^ tm.tm_mon)
945 | (ltm.tm_year ^ tm.tm_year))
949 if (! gmtime_r (<, >m))
952 diff = tm_diff (<m, >m);
964 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
967 case '\0': /* GNU extension: % at end of format. */
971 /* Unknown format; output the format, including the '%',
972 since this is most likely the right thing to do if a
973 multibyte string has been misparsed. */
977 for (flen = 1; f[1 - flen] != '%'; flen++)
979 cpy (flen, &f[1 - flen]);