1 /* Copyright (C) 1991, 92, 93, 94, 95, 96 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. */
24 # define HAVE_LIMITS_H 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 MULTIBYTE_IS_FORMAT_SAFE 1
31 # define STDC_HEADERS 1
32 # include <ansidecl.h>
33 # include "../locale/localeinfo.h"
37 #include <sys/types.h> /* Some systems define `time_t' here. */
39 #ifdef TIME_WITH_SYS_TIME
40 # include <sys/time.h>
43 # ifdef HAVE_SYS_TIME_H
44 # include <sys/time.h>
50 extern char *tzname[];
53 /* Do multibyte processing if multibytes are supported, unless
54 multibyte sequences are safe in formats. Multibyte sequences are
55 safe if they cannot contain byte sequences that look like format
56 conversion specifications. The GNU C Library uses UTF8 multibyte
57 encoding, which is safe for formats, but strftime.c can be used
58 with other C libraries that use unsafe encodings. */
59 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
65 /* Simulate mbrlen with mblen as best we can. */
66 # define mbstate_t int
67 # define mbrlen(s, n, ps) mblen (s, n)
68 # define mbsinit(ps) (*(ps) == 0)
70 static const mbstate_t mbstate_zero;
82 # define memcpy(d, s, n) bcopy (s, d, n)
86 #if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
87 #define __P(args) args
105 #define TYPE_SIGNED(t) ((t) -1 < 0)
107 /* Bound on length of the string representing an integer value of type t.
108 Subtract one for the sign bit if t is signed;
109 302 / 1000 is log10 (2) rounded up;
110 add one for integer division truncation;
111 add one more for a minus sign if t is signed. */
112 #define INT_STRLEN_BOUND(t) \
113 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 100 + 1 + TYPE_SIGNED (t))
115 #define TM_YEAR_BASE 1900
118 /* Nonzero if YEAR is a leap year (every 4 years,
119 except every 100th isn't, and every 400th is). */
120 #define __isleap(year) \
121 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
126 # define gmtime_r __gmtime_r
127 # define localtime_r __localtime_r
129 # if ! HAVE_LOCALTIME_R
130 # if ! HAVE_TM_GMTOFF
131 /* Approximate gmtime_r as best we can in its absence. */
132 #define gmtime_r my_gmtime_r
133 static struct tm *gmtime_r __P ((const time_t *, struct tm *));
139 struct tm *l = gmtime (t);
145 # endif /* ! HAVE_TM_GMTOFF */
147 /* Approximate localtime_r as best we can in its absence. */
148 #define localtime_r my_localtime_r
149 static struct tm *localtime_r __P ((const time_t *, struct tm *));
155 struct tm *l = localtime (t);
161 # endif /* ! HAVE_LOCALTIME_R */
162 #endif /* ! defined (_LIBC) */
165 static const char spaces[16] = " ";
170 int _delta = width - _n; \
171 i += _n + (_delta > 0 ? _delta : 0); \
179 int _this = _delta > 16 ? 16 : _delta; \
180 memcpy (p, spaces, _this); \
192 memcpy_lowcase (p, (s), _n); \
194 memcpy ((PTR) p, (PTR) (s), _n))
199 # define TOUPPER(Ch) toupper (Ch)
200 # define TOLOWER(Ch) tolower (Ch)
202 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
203 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
206 static char *memcpy_lowcase __P ((char *dest, const char *src, size_t len));
209 memcpy_lowcase (dest, src, len)
215 dest[len] = TOLOWER (src[len]);
220 /* Yield the difference between *A and *B,
221 measured in seconds, ignoring leap seconds. */
222 static int tm_diff __P ((const struct tm *, const struct tm *));
228 /* Compute intervening leap days correctly even if year is negative.
229 Take care to avoid int overflow in leap day calculations,
230 but it's OK to assume that A and B are close to each other. */
231 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
232 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
233 int a100 = a4 / 25 - (a4 % 25 < 0);
234 int b100 = b4 / 25 - (b4 % 25 < 0);
235 int a400 = a100 >> 2;
236 int b400 = b100 >> 2;
237 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
238 int years = a->tm_year - b->tm_year;
239 int days = (365 * years + intervening_leap_days
240 + (a->tm_yday - b->tm_yday));
241 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
242 + (a->tm_min - b->tm_min))
243 + (a->tm_sec - b->tm_sec));
245 #endif /* ! HAVE_TM_GMTOFF */
249 /* The number of days from the first day of the first ISO week of this
250 year to the year day YDAY with week day WDAY. ISO weeks start on
251 Monday; the first ISO week has the year's first Thursday. YDAY may
252 be as small as YDAY_MINIMUM. */
253 #define ISO_WEEK_START_WDAY 1 /* Monday */
254 #define ISO_WEEK1_WDAY 4 /* Thursday */
255 #define YDAY_MINIMUM (-366)
256 static int iso_week_days __P ((int, int));
261 iso_week_days (yday, wday)
265 /* Add enough to the first operand of % to make it nonnegative. */
266 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
268 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
269 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
274 static char const weekday_name[][10] =
276 "Sunday", "Monday", "Tuesday", "Wednesday",
277 "Thursday", "Friday", "Saturday"
279 static char const month_name[][10] =
281 "January", "February", "March", "April", "May", "June",
282 "July", "August", "September", "October", "November", "December"
286 /* Write information from TP into S according to the format
287 string FORMAT, writing no more that MAXSIZE characters
288 (including the terminating '\0') and returning number of
289 characters written. If S is NULL, nothing will be written
290 anywhere, so to determine how many characters would be
291 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
293 strftime (s, maxsize, format, tp)
299 int hour12 = tp->tm_hour;
301 const char *const a_wkday = _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday);
302 const char *const f_wkday = _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday);
303 const char *const a_month = _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon);
304 const char *const f_month = _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon);
305 const char *const ampm = _NL_CURRENT (LC_TIME,
306 hour12 > 11 ? PM_STR : AM_STR);
307 size_t aw_len = strlen (a_wkday);
308 size_t am_len = strlen (a_month);
309 size_t ap_len = strlen (ampm);
311 const char *const f_wkday = weekday_name[tp->tm_wday];
312 const char *const f_month = month_name[tp->tm_mon];
313 const char *const a_wkday = f_wkday;
314 const char *const a_month = f_month;
315 const char *const ampm = "AMPM" + 2 * (hour12 > 11);
320 size_t wkday_len = strlen (f_wkday);
321 size_t month_len = strlen (f_month);
330 zone = (const char *) tp->tm_zone;
333 if (!(zone && *zone) && tp->tm_isdst >= 0)
334 zone = tzname[tp->tm_isdst];
337 zone = ""; /* POSIX.2 requires the empty string here. */
339 zonelen = strlen (zone);
344 if (hour12 == 0) hour12 = 12;
346 for (f = format; *f != '\0'; ++f)
348 int pad; /* Padding for number ('-', '_', or 0). */
349 int modifier; /* Field modifier ('E', 'O', or 0). */
350 int digits; /* Max digits for numeric format. */
351 int number_value; /* Numeric value to be printed. */
352 int negative_number; /* 1 if the number is negative. */
355 char buf[1 + (sizeof (int) < sizeof (time_t)
356 ? INT_STRLEN_BOUND (time_t)
357 : INT_STRLEN_BOUND (int))];
368 case '\a': case '\b': case '\t': case '\n':
369 case '\v': case '\f': case '\r':
370 case ' ': case '!': case '"': case '#': case '&': case'\'':
371 case '(': case ')': case '*': case '+': case ',': case '-':
372 case '.': case '/': case '0': case '1': case '2': case '3':
373 case '4': case '5': case '6': case '7': case '8': case '9':
374 case ':': case ';': case '<': case '=': case '>': case '?':
375 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
376 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
377 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
378 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
379 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
380 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
381 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
382 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
383 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
384 case 'x': case 'y': case 'z': case '{': case '|': case '}':
386 /* The C Standard requires these 98 characters (plus '%') to
387 be in the basic execution character set. None of these
388 characters can start a multibyte sequence, so they need
389 not be analyzed further. */
394 /* Copy this multibyte sequence until we reach its end, find
395 an error, or come back to the initial shift state. */
397 mbstate_t mbstate = mbstate_zero;
402 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
407 if (bytes == (size_t) -2 || bytes == (size_t) -1)
415 while (! mbsinit (&mbstate));
422 #else /* ! DO_MULTIBYTE */
424 /* Either multibyte encodings are not supported, or they are
425 safe for formats, so any non-'%' byte can be copied through. */
432 #endif /* ! DO_MULTIBYTE */
434 /* Check for flags that can modify a number format. */
453 /* As a GNU extension we allow to specify the field width. */
462 while (isdigit (*++f));
465 /* Check for modifiers. */
478 /* Now do the specified format. */
481 #define DO_NUMBER(d, v) \
482 digits = d; number_value = v; goto do_number
483 #define DO_NUMBER_SPACEPAD(d, v) \
484 digits = d; number_value = v; goto do_number_spacepad
495 cpy (aw_len, a_wkday);
501 cpy (wkday_len, f_wkday);
505 case 'h': /* POSIX.2 extension. */
508 cpy (am_len, a_month);
514 cpy (month_len, f_month);
521 if (! (modifier == 'E'
522 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT)) != '\0'))
523 subfmt = _NL_CURRENT (LC_TIME, D_T_FMT);
525 subfmt = "%a %b %e %H:%M:%S %Y";
530 size_t len = strftime (NULL, maxsize - i, subfmt, tp);
531 if (len == 0 && *subfmt)
533 add (len, strftime (p, maxsize - i, subfmt, tp));
537 case 'C': /* POSIX.2 extension. */
540 #if HAVE_STRUCT_ERA_ENTRY
543 struct era_entry *era = _nl_get_era_entry (tp);
546 size_t len = strlen (era->name_fmt);
547 cpy (len, era->name_fmt);
553 int year = tp->tm_year + TM_YEAR_BASE;
554 DO_NUMBER (1, year / 100 - (year % 100 < 0));
561 if (! (modifier == 'E'
562 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_FMT)) != '\0'))
563 subfmt = _NL_CURRENT (LC_TIME, D_FMT);
567 case 'D': /* POSIX.2 extension. */
577 DO_NUMBER (2, tp->tm_mday);
579 case 'e': /* POSIX.2 extension. */
583 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
585 /* All numeric formats set DIGITS and NUMBER_VALUE and then
586 jump to one of these two labels. */
589 /* Force `_' flag unless overwritten by `0' flag. */
594 /* Format the number according to the MODIFIER flag. */
597 if (modifier == 'O' && 0 <= number_value)
599 /* Get the locale specific alternate representation of
600 the number NUMBER_VALUE. If none exist NULL is returned. */
601 const char *cp = _nl_get_alt_digit (number_value);
605 size_t digitlen = strlen (cp);
615 unsigned int u = number_value;
617 bufp = buf + sizeof (buf);
618 negative_number = number_value < 0;
624 *--bufp = u % 10 + '0';
625 while ((u /= 10) != 0);
628 do_number_sign_and_padding:
634 int padding = digits - (buf + sizeof (buf) - bufp);
638 while (0 < padding--)
643 bufp += negative_number;
644 while (0 < padding--)
651 cpy (buf + sizeof (buf) - bufp, bufp);
659 DO_NUMBER (2, tp->tm_hour);
665 DO_NUMBER (2, hour12);
667 case 'k': /* GNU extension. */
671 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
673 case 'l': /* GNU extension. */
677 DO_NUMBER_SPACEPAD (2, hour12);
683 DO_NUMBER (3, 1 + tp->tm_yday);
689 DO_NUMBER (2, tp->tm_min);
695 DO_NUMBER (2, tp->tm_mon + 1);
697 case 'n': /* POSIX.2 extension. */
709 case 'R': /* GNU extension. */
713 case 'r': /* POSIX.2 extension. */
715 if (*(subfmt = _NL_CURRENT (LC_TIME, T_FMT_AMPM)) == '\0')
717 subfmt = "%I:%M:%S %p";
724 DO_NUMBER (2, tp->tm_sec);
726 case 's': /* GNU extension. */
734 /* Generate string value for T using time_t arithmetic;
735 this works even if sizeof (long) < sizeof (time_t). */
737 bufp = buf + sizeof (buf);
738 negative_number = t < 0;
749 /* Adjust if division truncates to minus infinity. */
750 if (0 < -1 % 10 && d < 0)
762 goto do_number_sign_and_padding;
769 if (! (modifier == 'E'
770 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_T_FMT)) != '\0'))
771 subfmt = _NL_CURRENT (LC_TIME, T_FMT);
775 case 'T': /* POSIX.2 extension. */
779 case 't': /* POSIX.2 extension. */
783 case 'u': /* POSIX.2 extension. */
784 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
790 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
793 case 'g': /* GNU extension. */
794 case 'G': /* GNU extension. */
798 int year = tp->tm_year + TM_YEAR_BASE;
799 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
803 /* This ISO week belongs to the previous year. */
805 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
810 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
814 /* This ISO week belongs to the next year. */
823 DO_NUMBER (2, (year % 100 + 100) % 100);
829 DO_NUMBER (2, days / 7 + 1);
837 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
843 DO_NUMBER (1, tp->tm_wday);
846 #if HAVE_STRUCT_ERA_ENTRY
849 struct era_entry *era = _nl_get_era_entry (tp);
852 subfmt = strchr (era->name_fmt, '\0') + 1;
860 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
863 #if HAVE_STRUCT_ERA_ENTRY
866 struct era_entry *era = _nl_get_era_entry (tp);
869 int delta = tp->tm_year - era->start_date[0];
870 DO_NUMBER (1, (era->offset
871 + (era->direction == '-' ? -delta : delta)));
875 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
881 case 'z': /* GNU extension. */
882 if (tp->tm_isdst < 0)
888 diff = tp->tm_gmtoff;
897 if (lt == (time_t) -1)
899 /* mktime returns -1 for errors, but -1 is also a
900 valid time_t value. Check whether an error really
903 localtime_r (<, &tm);
905 if ((ltm.tm_sec ^ tm.tm_sec)
906 | (ltm.tm_min ^ tm.tm_min)
907 | (ltm.tm_hour ^ tm.tm_hour)
908 | (ltm.tm_mday ^ tm.tm_mday)
909 | (ltm.tm_mon ^ tm.tm_mon)
910 | (ltm.tm_year ^ tm.tm_year))
914 if (! gmtime_r (<, >m))
917 diff = tm_diff (<m, >m);
929 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
932 case '\0': /* GNU extension: % at end of format. */
936 /* Unknown format; output the format, including the '%',
937 since this is most likely the right thing to do if a
938 multibyte string has been misparsed. */
942 for (flen = 1; f[1 - flen] != '%'; flen++)
944 cpy (flen, &f[1 - flen]);