1 /* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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 HAVE_TZNAME 1
32 # define MULTIBYTE_IS_FORMAT_SAFE 1
33 # define STDC_HEADERS 1
34 # include "../locale/localeinfo.h"
38 #include <sys/types.h> /* Some systems define `time_t' here. */
40 #ifdef TIME_WITH_SYS_TIME
41 # include <sys/time.h>
44 # ifdef HAVE_SYS_TIME_H
45 # include <sys/time.h>
51 extern char *tzname
[];
54 /* Do multibyte processing if multibytes are supported, unless
55 multibyte sequences are safe in formats. Multibyte sequences are
56 safe if they cannot contain byte sequences that look like format
57 conversion specifications. The GNU C Library uses UTF8 multibyte
58 encoding, which is safe for formats, but strftime.c can be used
59 with other C libraries that use unsafe encodings. */
60 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
66 /* Simulate mbrlen with mblen as best we can. */
67 # define mbstate_t int
68 # define mbrlen(s, n, ps) mblen (s, n)
69 # define mbsinit(ps) (*(ps) == 0)
71 static const mbstate_t mbstate_zero
;
84 # define memcpy(d, s, n) bcopy ((s), (d), (n))
89 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
90 # define __P(args) args
112 #define TYPE_SIGNED(t) ((t) -1 < 0)
114 /* Bound on length of the string representing an integer value of type t.
115 Subtract one for the sign bit if t is signed;
116 302 / 1000 is log10 (2) rounded up;
117 add one for integer division truncation;
118 add one more for a minus sign if t is signed. */
119 #define INT_STRLEN_BOUND(t) \
120 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 100 + 1 + TYPE_SIGNED (t))
122 #define TM_YEAR_BASE 1900
125 /* Nonzero if YEAR is a leap year (every 4 years,
126 except every 100th isn't, and every 400th is). */
127 # define __isleap(year) \
128 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
133 # define gmtime_r __gmtime_r
134 # define localtime_r __localtime_r
135 # define tzname __tzname
136 # define tzset __tzset
138 # if ! HAVE_LOCALTIME_R
139 # if ! HAVE_TM_GMTOFF
140 /* Approximate gmtime_r as best we can in its absence. */
141 # define gmtime_r my_gmtime_r
142 static struct tm
*gmtime_r
__P ((const time_t *, struct tm
*));
148 struct tm
*l
= gmtime (t
);
154 # endif /* ! HAVE_TM_GMTOFF */
156 /* Approximate localtime_r as best we can in its absence. */
157 # define localtime_r my_ftime_localtime_r
158 static struct tm
*localtime_r
__P ((const time_t *, struct tm
*));
164 struct tm
*l
= localtime (t
);
170 # endif /* ! HAVE_LOCALTIME_R */
171 #endif /* ! defined (_LIBC) */
174 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
175 /* Some systems lack the `memset' function and we don't want to
176 introduce additional dependencies. */
177 /* The SGI compiler reportedly barfs on the trailing null
178 if we use a string constant as the initializer. 28 June 1997, rms. */
179 static const char spaces
[16] = /* " " */
180 { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
181 static const char zeroes
[16] = /* "0000000000000000" */
182 { '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0' };
184 # define memset_space(P, Len) \
190 int _this = _len > 16 ? 16 : _len; \
191 memcpy ((P), spaces, _this); \
198 # define memset_zero(P, Len) \
204 int _this = _len > 16 ? 16 : _len; \
205 memcpy ((P), zeroes, _this); \
212 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
213 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
220 int _delta = width - _n; \
221 int _incr = _n + (_delta > 0 ? _delta : 0); \
222 if (i + _incr >= maxsize) \
229 memset_zero (p, _delta); \
231 memset_space (p, _delta); \
242 memcpy_lowcase (p, (s), _n); \
243 else if (to_uppcase) \
244 memcpy_uppcase (p, (s), _n); \
246 memcpy ((PTR) p, (PTR) (s), _n))
251 # define TOUPPER(Ch) toupper (Ch)
252 # define TOLOWER(Ch) tolower (Ch)
254 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
255 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
257 /* We don't use `isdigit' here since the locale dependent
258 interpretation is not what we want here. We only need to accept
259 the arabic digits in the ASCII range. One day there is perhaps a
260 more reliable way to accept other sets of digits. */
261 #define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
263 static char *memcpy_lowcase
__P ((char *dest
, const char *src
, size_t len
));
266 memcpy_lowcase (dest
, src
, len
)
272 dest
[len
] = TOLOWER (src
[len
]);
276 static char *memcpy_uppcase
__P ((char *dest
, const char *src
, size_t len
));
279 memcpy_uppcase (dest
, src
, len
)
285 dest
[len
] = TOUPPER (src
[len
]);
291 /* Yield the difference between *A and *B,
292 measured in seconds, ignoring leap seconds. */
293 # define tm_diff ftime_tm_diff
294 static int tm_diff
__P ((const struct tm
*, const struct tm
*));
300 /* Compute intervening leap days correctly even if year is negative.
301 Take care to avoid int overflow in leap day calculations,
302 but it's OK to assume that A and B are close to each other. */
303 int a4
= (a
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (a
->tm_year
& 3);
304 int b4
= (b
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (b
->tm_year
& 3);
305 int a100
= a4
/ 25 - (a4
% 25 < 0);
306 int b100
= b4
/ 25 - (b4
% 25 < 0);
307 int a400
= a100
>> 2;
308 int b400
= b100
>> 2;
309 int intervening_leap_days
= (a4
- b4
) - (a100
- b100
) + (a400
- b400
);
310 int years
= a
->tm_year
- b
->tm_year
;
311 int days
= (365 * years
+ intervening_leap_days
312 + (a
->tm_yday
- b
->tm_yday
));
313 return (60 * (60 * (24 * days
+ (a
->tm_hour
- b
->tm_hour
))
314 + (a
->tm_min
- b
->tm_min
))
315 + (a
->tm_sec
- b
->tm_sec
));
317 #endif /* ! HAVE_TM_GMTOFF */
321 /* The number of days from the first day of the first ISO week of this
322 year to the year day YDAY with week day WDAY. ISO weeks start on
323 Monday; the first ISO week has the year's first Thursday. YDAY may
324 be as small as YDAY_MINIMUM. */
325 #define ISO_WEEK_START_WDAY 1 /* Monday */
326 #define ISO_WEEK1_WDAY 4 /* Thursday */
327 #define YDAY_MINIMUM (-366)
328 static int iso_week_days
__P ((int, int));
333 iso_week_days (yday
, wday
)
337 /* Add enough to the first operand of % to make it nonnegative. */
338 int big_enough_multiple_of_7
= (-YDAY_MINIMUM
/ 7 + 2) * 7;
340 - (yday
- wday
+ ISO_WEEK1_WDAY
+ big_enough_multiple_of_7
) % 7
341 + ISO_WEEK1_WDAY
- ISO_WEEK_START_WDAY
);
346 static char const weekday_name
[][10] =
348 "Sunday", "Monday", "Tuesday", "Wednesday",
349 "Thursday", "Friday", "Saturday"
351 static char const month_name
[][10] =
353 "January", "February", "March", "April", "May", "June",
354 "July", "August", "September", "October", "November", "December"
359 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
360 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
361 Work around this bug by copying *tp before it might be munged. */
362 size_t _strftime_copytm
__P ((char *, size_t, const char *,
365 strftime (s
, maxsize
, format
, tp
)
373 return _strftime_copytm (s
, maxsize
, format
, &tmcopy
);
378 # define strftime(S, Maxsize, Format, Tp) \
379 _strftime_copytm (S, Maxsize, Format, Tp)
383 /* Write information from TP into S according to the format
384 string FORMAT, writing no more that MAXSIZE characters
385 (including the terminating '\0') and returning number of
386 characters written. If S is NULL, nothing will be written
387 anywhere, so to determine how many characters would be
388 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
390 strftime (s
, maxsize
, format
, tp
)
396 int hour12
= tp
->tm_hour
;
398 const char *const a_wkday
= _NL_CURRENT (LC_TIME
, ABDAY_1
+ tp
->tm_wday
);
399 const char *const f_wkday
= _NL_CURRENT (LC_TIME
, DAY_1
+ tp
->tm_wday
);
400 const char *const a_month
= _NL_CURRENT (LC_TIME
, ABMON_1
+ tp
->tm_mon
);
401 const char *const f_month
= _NL_CURRENT (LC_TIME
, MON_1
+ tp
->tm_mon
);
402 const char *const ampm
= _NL_CURRENT (LC_TIME
,
403 hour12
> 11 ? PM_STR
: AM_STR
);
404 size_t aw_len
= strlen (a_wkday
);
405 size_t am_len
= strlen (a_month
);
406 size_t ap_len
= strlen (ampm
);
408 const char *const f_wkday
= weekday_name
[tp
->tm_wday
];
409 const char *const f_month
= month_name
[tp
->tm_mon
];
410 const char *const a_wkday
= f_wkday
;
411 const char *const a_month
= f_month
;
412 const char *const ampm
= "AMPM" + 2 * (hour12
> 11);
417 size_t wkday_len
= strlen (f_wkday
);
418 size_t month_len
= strlen (f_month
);
427 /* The POSIX test suite assumes that setting
428 the environment variable TZ to a new value before calling strftime()
429 will influence the result (the %Z format) even if the information in
430 TP is computed with a totally different time zone.
431 This is bogus: though POSIX allows bad behavior like this,
432 POSIX does not require it. Do the right thing instead. */
433 zone
= (const char *) tp
->tm_zone
;
436 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
437 time zone names contained in the external variable `tzname' shall
438 be set as if the tzset() function had been called. */
443 if (!(zone
&& *zone
) && tp
->tm_isdst
>= 0)
444 zone
= tzname
[tp
->tm_isdst
];
447 zone
= ""; /* POSIX.2 requires the empty string here. */
449 zonelen
= strlen (zone
);
454 if (hour12
== 0) hour12
= 12;
456 for (f
= format
; *f
!= '\0'; ++f
)
458 int pad
; /* Padding for number ('-', '_', or 0). */
459 int modifier
; /* Field modifier ('E', 'O', or 0). */
460 int digits
; /* Max digits for numeric format. */
461 int number_value
; /* Numeric value to be printed. */
462 int negative_number
; /* 1 if the number is negative. */
465 char buf
[1 + (sizeof (int) < sizeof (time_t)
466 ? INT_STRLEN_BOUND (time_t)
467 : INT_STRLEN_BOUND (int))];
480 case '\a': case '\b': case '\t': case '\n':
481 case '\v': case '\f': case '\r':
482 case ' ': case '!': case '"': case '#': case '&': case'\'':
483 case '(': case ')': case '*': case '+': case ',': case '-':
484 case '.': case '/': case '0': case '1': case '2': case '3':
485 case '4': case '5': case '6': case '7': case '8': case '9':
486 case ':': case ';': case '<': case '=': case '>': case '?':
487 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
488 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
489 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
490 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
491 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
492 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
493 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
494 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
495 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
496 case 'x': case 'y': case 'z': case '{': case '|': case '}':
498 /* The C Standard requires these 98 characters (plus '%') to
499 be in the basic execution character set. None of these
500 characters can start a multibyte sequence, so they need
501 not be analyzed further. */
506 /* Copy this multibyte sequence until we reach its end, find
507 an error, or come back to the initial shift state. */
509 mbstate_t mbstate
= mbstate_zero
;
514 size_t bytes
= mbrlen (f
+ len
, (size_t) -1, &mbstate
);
519 if (bytes
== (size_t) -2 || bytes
== (size_t) -1)
527 while (! mbsinit (&mbstate
));
534 #else /* ! DO_MULTIBYTE */
536 /* Either multibyte encodings are not supported, or they are
537 safe for formats, so any non-'%' byte can be copied through. */
544 #endif /* ! DO_MULTIBYTE */
546 /* Check for flags that can modify a format. */
552 /* This influences the number formats. */
559 /* This changes textual output. */
573 /* As a GNU extension we allow to specify the field width. */
583 while (ISDIGIT (*f
));
586 /* Check for modifiers. */
599 /* Now do the specified format. */
602 #define DO_NUMBER(d, v) \
603 digits = width == -1 ? d : width; \
604 number_value = v; goto do_number
605 #define DO_NUMBER_SPACEPAD(d, v) \
606 digits = width == -1 ? d : width; \
607 number_value = v; goto do_number_spacepad
623 cpy (aw_len
, a_wkday
);
634 cpy (wkday_len
, f_wkday
);
638 case 'h': /* POSIX.2 extension. */
641 cpy (am_len
, a_month
);
652 cpy (month_len
, f_month
);
659 if (! (modifier
== 'E'
660 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_T_FMT
)) != '\0'))
661 subfmt
= _NL_CURRENT (LC_TIME
, D_T_FMT
);
663 subfmt
= "%a %b %e %H:%M:%S %Y";
669 size_t len
= strftime (NULL
, maxsize
- i
, subfmt
, tp
);
670 if (len
== 0 && *subfmt
)
672 add (len
, strftime (p
, maxsize
- i
, subfmt
, tp
));
675 while (old_start
< p
)
677 *old_start
= TOUPPER (*old_start
);
683 case 'C': /* POSIX.2 extension. */
686 #if HAVE_STRUCT_ERA_ENTRY
689 struct era_entry
*era
= _nl_get_era_entry (tp
);
692 size_t len
= strlen (era
->name_fmt
);
693 cpy (len
, era
->name_fmt
);
699 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
700 DO_NUMBER (1, year
/ 100 - (year
% 100 < 0));
707 if (! (modifier
== 'E'
708 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_FMT
)) != '\0'))
709 subfmt
= _NL_CURRENT (LC_TIME
, D_FMT
);
713 case 'D': /* POSIX.2 extension. */
723 DO_NUMBER (2, tp
->tm_mday
);
725 case 'e': /* POSIX.2 extension. */
729 DO_NUMBER_SPACEPAD (2, tp
->tm_mday
);
731 /* All numeric formats set DIGITS and NUMBER_VALUE and then
732 jump to one of these two labels. */
735 /* Force `_' flag unless overwritten by `0' flag. */
740 /* Format the number according to the MODIFIER flag. */
743 if (modifier
== 'O' && 0 <= number_value
)
745 /* Get the locale specific alternate representation of
746 the number NUMBER_VALUE. If none exist NULL is returned. */
747 const char *cp
= _nl_get_alt_digit (number_value
);
751 size_t digitlen
= strlen (cp
);
761 unsigned int u
= number_value
;
763 bufp
= buf
+ sizeof (buf
);
764 negative_number
= number_value
< 0;
770 *--bufp
= u
% 10 + '0';
771 while ((u
/= 10) != 0);
774 do_number_sign_and_padding
:
780 int padding
= digits
- (buf
+ sizeof (buf
) - bufp
);
784 while (0 < padding
--)
789 bufp
+= negative_number
;
790 while (0 < padding
--)
797 cpy (buf
+ sizeof (buf
) - bufp
, bufp
);
805 DO_NUMBER (2, tp
->tm_hour
);
811 DO_NUMBER (2, hour12
);
813 case 'k': /* GNU extension. */
817 DO_NUMBER_SPACEPAD (2, tp
->tm_hour
);
819 case 'l': /* GNU extension. */
823 DO_NUMBER_SPACEPAD (2, hour12
);
829 DO_NUMBER (3, 1 + tp
->tm_yday
);
835 DO_NUMBER (2, tp
->tm_min
);
841 DO_NUMBER (2, tp
->tm_mon
+ 1);
843 case 'n': /* POSIX.2 extension. */
860 case 'R': /* GNU extension. */
864 case 'r': /* POSIX.2 extension. */
866 if (*(subfmt
= _NL_CURRENT (LC_TIME
, T_FMT_AMPM
)) == '\0')
868 subfmt
= "%I:%M:%S %p";
875 DO_NUMBER (2, tp
->tm_sec
);
877 case 's': /* GNU extension. */
885 /* Generate string value for T using time_t arithmetic;
886 this works even if sizeof (long) < sizeof (time_t). */
888 bufp
= buf
+ sizeof (buf
);
889 negative_number
= t
< 0;
900 /* Adjust if division truncates to minus infinity. */
901 if (0 < -1 % 10 && d
< 0)
913 goto do_number_sign_and_padding
;
920 if (! (modifier
== 'E'
921 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_T_FMT
)) != '\0'))
922 subfmt
= _NL_CURRENT (LC_TIME
, T_FMT
);
926 case 'T': /* POSIX.2 extension. */
930 case 't': /* POSIX.2 extension. */
934 case 'u': /* POSIX.2 extension. */
935 DO_NUMBER (1, (tp
->tm_wday
- 1 + 7) % 7 + 1);
941 DO_NUMBER (2, (tp
->tm_yday
- tp
->tm_wday
+ 7) / 7);
944 case 'g': /* GNU extension. */
945 case 'G': /* GNU extension. */
949 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
950 int days
= iso_week_days (tp
->tm_yday
, tp
->tm_wday
);
954 /* This ISO week belongs to the previous year. */
956 days
= iso_week_days (tp
->tm_yday
+ (365 + __isleap (year
)),
961 int d
= iso_week_days (tp
->tm_yday
- (365 + __isleap (year
)),
965 /* This ISO week belongs to the next year. */
974 DO_NUMBER (2, (year
% 100 + 100) % 100);
980 DO_NUMBER (2, days
/ 7 + 1);
988 DO_NUMBER (2, (tp
->tm_yday
- (tp
->tm_wday
- 1 + 7) % 7 + 7) / 7);
994 DO_NUMBER (1, tp
->tm_wday
);
997 #if HAVE_STRUCT_ERA_ENTRY
1000 struct era_entry
*era
= _nl_get_era_entry (tp
);
1003 subfmt
= strchr (era
->name_fmt
, '\0') + 1;
1008 if (modifier
== 'O')
1011 DO_NUMBER (1, tp
->tm_year
+ TM_YEAR_BASE
);
1014 #if HAVE_STRUCT_ERA_ENTRY
1015 if (modifier
== 'E')
1017 struct era_entry
*era
= _nl_get_era_entry (tp
);
1020 int delta
= tp
->tm_year
- era
->start_date
[0];
1021 DO_NUMBER (1, (era
->offset
1022 + (era
->direction
== '-' ? -delta
: delta
)));
1026 DO_NUMBER (2, (tp
->tm_year
% 100 + 100) % 100);
1034 cpy (zonelen
, zone
);
1037 case 'z': /* GNU extension. */
1038 if (tp
->tm_isdst
< 0)
1044 diff
= tp
->tm_gmtoff
;
1053 if (lt
== (time_t) -1)
1055 /* mktime returns -1 for errors, but -1 is also a
1056 valid time_t value. Check whether an error really
1059 localtime_r (<
, &tm
);
1061 if ((ltm
.tm_sec
^ tm
.tm_sec
)
1062 | (ltm
.tm_min
^ tm
.tm_min
)
1063 | (ltm
.tm_hour
^ tm
.tm_hour
)
1064 | (ltm
.tm_mday
^ tm
.tm_mday
)
1065 | (ltm
.tm_mon
^ tm
.tm_mon
)
1066 | (ltm
.tm_year
^ tm
.tm_year
))
1070 if (! gmtime_r (<
, >m
))
1073 diff
= tm_diff (<m
, >m
);
1085 DO_NUMBER (4, (diff
/ 60) * 100 + diff
% 60);
1088 case '\0': /* GNU extension: % at end of format. */
1092 /* Unknown format; output the format, including the '%',
1093 since this is most likely the right thing to do if a
1094 multibyte string has been misparsed. */
1098 for (flen
= 1; f
[1 - flen
] != '%'; flen
++)
1100 cpy (flen
, &f
[1 - flen
]);