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 extern int __tz_compute
__P ((time_t timer
, const struct tm
*tm
));
136 # define tzname __tzname
137 # define tzset __tzset
139 # if ! HAVE_LOCALTIME_R
140 # if ! HAVE_TM_GMTOFF
141 /* Approximate gmtime_r as best we can in its absence. */
142 # define gmtime_r my_gmtime_r
143 static struct tm
*gmtime_r
__P ((const time_t *, struct tm
*));
149 struct tm
*l
= gmtime (t
);
155 # endif /* ! HAVE_TM_GMTOFF */
157 /* Approximate localtime_r as best we can in its absence. */
158 # define localtime_r my_ftime_localtime_r
159 static struct tm
*localtime_r
__P ((const time_t *, struct tm
*));
165 struct tm
*l
= localtime (t
);
171 # endif /* ! HAVE_LOCALTIME_R */
172 #endif /* ! defined (_LIBC) */
175 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
176 /* Some systems lack the `memset' function and we don't want to
177 introduce additional dependencies. */
178 /* The SGI compiler reportedly barfs on the trailing null
179 if we use a string constant as the initializer. 28 June 1997, rms. */
180 static const char spaces
[16] = /* " " */
181 { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
182 static const char zeroes
[16] = /* "0000000000000000" */
183 { '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0' };
185 # define memset_space(P, Len) \
191 int _this = _len > 16 ? 16 : _len; \
192 memcpy ((P), spaces, _this); \
199 # define memset_zero(P, Len) \
205 int _this = _len > 16 ? 16 : _len; \
206 memcpy ((P), zeroes, _this); \
213 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
214 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
221 int _delta = width - _n; \
222 int _incr = _n + (_delta > 0 ? _delta : 0); \
223 if (i + _incr >= maxsize) \
230 memset_zero (p, _delta); \
232 memset_space (p, _delta); \
243 memcpy_lowcase (p, (s), _n); \
244 else if (to_uppcase) \
245 memcpy_uppcase (p, (s), _n); \
247 memcpy ((PTR) p, (PTR) (s), _n))
252 # define TOUPPER(Ch) toupper (Ch)
253 # define TOLOWER(Ch) tolower (Ch)
255 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
256 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
258 /* We don't use `isdigit' here since the locale dependent
259 interpretation is not what we want here. We only need to accept
260 the arabic digits in the ASCII range. One day there is perhaps a
261 more reliable way to accept other sets of digits. */
262 #define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
264 static char *memcpy_lowcase
__P ((char *dest
, const char *src
, size_t len
));
267 memcpy_lowcase (dest
, src
, len
)
273 dest
[len
] = TOLOWER (src
[len
]);
277 static char *memcpy_uppcase
__P ((char *dest
, const char *src
, size_t len
));
280 memcpy_uppcase (dest
, src
, len
)
286 dest
[len
] = TOUPPER (src
[len
]);
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
*));
301 /* Compute intervening leap days correctly even if year is negative.
302 Take care to avoid int overflow in leap day calculations,
303 but it's OK to assume that A and B are close to each other. */
304 int a4
= (a
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (a
->tm_year
& 3);
305 int b4
= (b
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (b
->tm_year
& 3);
306 int a100
= a4
/ 25 - (a4
% 25 < 0);
307 int b100
= b4
/ 25 - (b4
% 25 < 0);
308 int a400
= a100
>> 2;
309 int b400
= b100
>> 2;
310 int intervening_leap_days
= (a4
- b4
) - (a100
- b100
) + (a400
- b400
);
311 int years
= a
->tm_year
- b
->tm_year
;
312 int days
= (365 * years
+ intervening_leap_days
313 + (a
->tm_yday
- b
->tm_yday
));
314 return (60 * (60 * (24 * days
+ (a
->tm_hour
- b
->tm_hour
))
315 + (a
->tm_min
- b
->tm_min
))
316 + (a
->tm_sec
- b
->tm_sec
));
318 #endif /* ! HAVE_TM_GMTOFF */
322 /* The number of days from the first day of the first ISO week of this
323 year to the year day YDAY with week day WDAY. ISO weeks start on
324 Monday; the first ISO week has the year's first Thursday. YDAY may
325 be as small as YDAY_MINIMUM. */
326 #define ISO_WEEK_START_WDAY 1 /* Monday */
327 #define ISO_WEEK1_WDAY 4 /* Thursday */
328 #define YDAY_MINIMUM (-366)
329 static int iso_week_days
__P ((int, int));
334 iso_week_days (yday
, wday
)
338 /* Add enough to the first operand of % to make it nonnegative. */
339 int big_enough_multiple_of_7
= (-YDAY_MINIMUM
/ 7 + 2) * 7;
341 - (yday
- wday
+ ISO_WEEK1_WDAY
+ big_enough_multiple_of_7
) % 7
342 + ISO_WEEK1_WDAY
- ISO_WEEK_START_WDAY
);
347 static char const weekday_name
[][10] =
349 "Sunday", "Monday", "Tuesday", "Wednesday",
350 "Thursday", "Friday", "Saturday"
352 static char const month_name
[][10] =
354 "January", "February", "March", "April", "May", "June",
355 "July", "August", "September", "October", "November", "December"
360 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
361 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
362 Work around this bug by copying *tp before it might be munged. */
363 size_t _strftime_copytm
__P ((char *, size_t, const char *,
366 strftime (s
, maxsize
, format
, tp
)
374 return _strftime_copytm (s
, maxsize
, format
, &tmcopy
);
379 # define strftime(S, Maxsize, Format, Tp) \
380 _strftime_copytm (S, Maxsize, Format, Tp)
384 /* Write information from TP into S according to the format
385 string FORMAT, writing no more that MAXSIZE characters
386 (including the terminating '\0') and returning number of
387 characters written. If S is NULL, nothing will be written
388 anywhere, so to determine how many characters would be
389 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
391 strftime (s
, maxsize
, format
, tp
)
397 int hour12
= tp
->tm_hour
;
399 const char *const a_wkday
= _NL_CURRENT (LC_TIME
, ABDAY_1
+ tp
->tm_wday
);
400 const char *const f_wkday
= _NL_CURRENT (LC_TIME
, DAY_1
+ tp
->tm_wday
);
401 const char *const a_month
= _NL_CURRENT (LC_TIME
, ABMON_1
+ tp
->tm_mon
);
402 const char *const f_month
= _NL_CURRENT (LC_TIME
, MON_1
+ tp
->tm_mon
);
403 const char *const ampm
= _NL_CURRENT (LC_TIME
,
404 hour12
> 11 ? PM_STR
: AM_STR
);
405 size_t aw_len
= strlen (a_wkday
);
406 size_t am_len
= strlen (a_month
);
407 size_t ap_len
= strlen (ampm
);
409 const char *const f_wkday
= weekday_name
[tp
->tm_wday
];
410 const char *const f_month
= month_name
[tp
->tm_mon
];
411 const char *const a_wkday
= f_wkday
;
412 const char *const a_month
= f_month
;
413 const char *const ampm
= "AMPM" + 2 * (hour12
> 11);
418 size_t wkday_len
= strlen (f_wkday
);
419 size_t month_len
= strlen (f_month
);
428 /* The POSIX test suite assumes that setting
429 the environment variable TZ to a new value before calling strftime()
430 will influence the result (the %Z format) even if the information in
431 TP is computed with a totally different time zone.
432 This is bogus: though POSIX allows bad behavior like this,
433 POSIX does not require it. Do the right thing instead. */
434 zone
= (const char *) tp
->tm_zone
;
437 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
438 time zone names contained in the external variable `tzname' shall
439 be set as if the tzset() function had been called. */
444 if (!(zone
&& *zone
) && tp
->tm_isdst
>= 0)
445 zone
= tzname
[tp
->tm_isdst
];
448 zone
= ""; /* POSIX.2 requires the empty string here. */
450 zonelen
= strlen (zone
);
455 if (hour12
== 0) hour12
= 12;
457 for (f
= format
; *f
!= '\0'; ++f
)
459 int pad
; /* Padding for number ('-', '_', or 0). */
460 int modifier
; /* Field modifier ('E', 'O', or 0). */
461 int digits
; /* Max digits for numeric format. */
462 int number_value
; /* Numeric value to be printed. */
463 int negative_number
; /* 1 if the number is negative. */
466 char buf
[1 + (sizeof (int) < sizeof (time_t)
467 ? INT_STRLEN_BOUND (time_t)
468 : INT_STRLEN_BOUND (int))];
481 case '\a': case '\b': case '\t': case '\n':
482 case '\v': case '\f': case '\r':
483 case ' ': case '!': case '"': case '#': case '&': case'\'':
484 case '(': case ')': case '*': case '+': case ',': case '-':
485 case '.': case '/': case '0': case '1': case '2': case '3':
486 case '4': case '5': case '6': case '7': case '8': case '9':
487 case ':': case ';': case '<': case '=': case '>': case '?':
488 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
489 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
490 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
491 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
492 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
493 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
494 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
495 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
496 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
497 case 'x': case 'y': case 'z': case '{': case '|': case '}':
499 /* The C Standard requires these 98 characters (plus '%') to
500 be in the basic execution character set. None of these
501 characters can start a multibyte sequence, so they need
502 not be analyzed further. */
507 /* Copy this multibyte sequence until we reach its end, find
508 an error, or come back to the initial shift state. */
510 mbstate_t mbstate
= mbstate_zero
;
515 size_t bytes
= mbrlen (f
+ len
, (size_t) -1, &mbstate
);
520 if (bytes
== (size_t) -2 || bytes
== (size_t) -1)
528 while (! mbsinit (&mbstate
));
535 #else /* ! DO_MULTIBYTE */
537 /* Either multibyte encodings are not supported, or they are
538 safe for formats, so any non-'%' byte can be copied through. */
545 #endif /* ! DO_MULTIBYTE */
547 /* Check for flags that can modify a format. */
553 /* This influences the number formats. */
560 /* This changes textual output. */
574 /* As a GNU extension we allow to specify the field width. */
584 while (ISDIGIT (*f
));
587 /* Check for modifiers. */
600 /* Now do the specified format. */
603 #define DO_NUMBER(d, v) \
604 digits = width == -1 ? d : width; \
605 number_value = v; goto do_number
606 #define DO_NUMBER_SPACEPAD(d, v) \
607 digits = width == -1 ? d : width; \
608 number_value = v; goto do_number_spacepad
624 cpy (aw_len
, a_wkday
);
635 cpy (wkday_len
, f_wkday
);
639 case 'h': /* POSIX.2 extension. */
642 cpy (am_len
, a_month
);
653 cpy (month_len
, f_month
);
660 if (! (modifier
== 'E'
661 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_T_FMT
)) != '\0'))
662 subfmt
= _NL_CURRENT (LC_TIME
, D_T_FMT
);
664 subfmt
= "%a %b %e %H:%M:%S %Y";
670 size_t len
= strftime (NULL
, maxsize
- i
, subfmt
, tp
);
671 if (len
== 0 && *subfmt
)
673 add (len
, strftime (p
, maxsize
- i
, subfmt
, tp
));
676 while (old_start
< p
)
678 *old_start
= TOUPPER (*old_start
);
684 case 'C': /* POSIX.2 extension. */
687 #if HAVE_STRUCT_ERA_ENTRY
690 struct era_entry
*era
= _nl_get_era_entry (tp
);
693 size_t len
= strlen (era
->name_fmt
);
694 cpy (len
, era
->name_fmt
);
700 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
701 DO_NUMBER (1, year
/ 100 - (year
% 100 < 0));
708 if (! (modifier
== 'E'
709 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_FMT
)) != '\0'))
710 subfmt
= _NL_CURRENT (LC_TIME
, D_FMT
);
714 case 'D': /* POSIX.2 extension. */
724 DO_NUMBER (2, tp
->tm_mday
);
726 case 'e': /* POSIX.2 extension. */
730 DO_NUMBER_SPACEPAD (2, tp
->tm_mday
);
732 /* All numeric formats set DIGITS and NUMBER_VALUE and then
733 jump to one of these two labels. */
736 /* Force `_' flag unless overwritten by `0' flag. */
741 /* Format the number according to the MODIFIER flag. */
744 if (modifier
== 'O' && 0 <= number_value
)
746 /* Get the locale specific alternate representation of
747 the number NUMBER_VALUE. If none exist NULL is returned. */
748 const char *cp
= _nl_get_alt_digit (number_value
);
752 size_t digitlen
= strlen (cp
);
762 unsigned int u
= number_value
;
764 bufp
= buf
+ sizeof (buf
);
765 negative_number
= number_value
< 0;
771 *--bufp
= u
% 10 + '0';
772 while ((u
/= 10) != 0);
775 do_number_sign_and_padding
:
781 int padding
= digits
- (buf
+ sizeof (buf
) - bufp
);
785 while (0 < padding
--)
790 bufp
+= negative_number
;
791 while (0 < padding
--)
798 cpy (buf
+ sizeof (buf
) - bufp
, bufp
);
806 DO_NUMBER (2, tp
->tm_hour
);
812 DO_NUMBER (2, hour12
);
814 case 'k': /* GNU extension. */
818 DO_NUMBER_SPACEPAD (2, tp
->tm_hour
);
820 case 'l': /* GNU extension. */
824 DO_NUMBER_SPACEPAD (2, hour12
);
830 DO_NUMBER (3, 1 + tp
->tm_yday
);
836 DO_NUMBER (2, tp
->tm_min
);
842 DO_NUMBER (2, tp
->tm_mon
+ 1);
844 case 'n': /* POSIX.2 extension. */
861 case 'R': /* GNU extension. */
865 case 'r': /* POSIX.2 extension. */
867 if (*(subfmt
= _NL_CURRENT (LC_TIME
, T_FMT_AMPM
)) == '\0')
869 subfmt
= "%I:%M:%S %p";
876 DO_NUMBER (2, tp
->tm_sec
);
878 case 's': /* GNU extension. */
886 /* Generate string value for T using time_t arithmetic;
887 this works even if sizeof (long) < sizeof (time_t). */
889 bufp
= buf
+ sizeof (buf
);
890 negative_number
= t
< 0;
901 /* Adjust if division truncates to minus infinity. */
902 if (0 < -1 % 10 && d
< 0)
914 goto do_number_sign_and_padding
;
921 if (! (modifier
== 'E'
922 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_T_FMT
)) != '\0'))
923 subfmt
= _NL_CURRENT (LC_TIME
, T_FMT
);
927 case 'T': /* POSIX.2 extension. */
931 case 't': /* POSIX.2 extension. */
935 case 'u': /* POSIX.2 extension. */
936 DO_NUMBER (1, (tp
->tm_wday
- 1 + 7) % 7 + 1);
942 DO_NUMBER (2, (tp
->tm_yday
- tp
->tm_wday
+ 7) / 7);
945 case 'g': /* GNU extension. */
946 case 'G': /* GNU extension. */
950 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
951 int days
= iso_week_days (tp
->tm_yday
, tp
->tm_wday
);
955 /* This ISO week belongs to the previous year. */
957 days
= iso_week_days (tp
->tm_yday
+ (365 + __isleap (year
)),
962 int d
= iso_week_days (tp
->tm_yday
- (365 + __isleap (year
)),
966 /* This ISO week belongs to the next year. */
975 DO_NUMBER (2, (year
% 100 + 100) % 100);
981 DO_NUMBER (2, days
/ 7 + 1);
989 DO_NUMBER (2, (tp
->tm_yday
- (tp
->tm_wday
- 1 + 7) % 7 + 7) / 7);
995 DO_NUMBER (1, tp
->tm_wday
);
998 #if HAVE_STRUCT_ERA_ENTRY
1001 struct era_entry
*era
= _nl_get_era_entry (tp
);
1004 subfmt
= strchr (era
->name_fmt
, '\0') + 1;
1009 if (modifier
== 'O')
1012 DO_NUMBER (1, tp
->tm_year
+ TM_YEAR_BASE
);
1015 #if HAVE_STRUCT_ERA_ENTRY
1016 if (modifier
== 'E')
1018 struct era_entry
*era
= _nl_get_era_entry (tp
);
1021 int delta
= tp
->tm_year
- era
->start_date
[0];
1022 DO_NUMBER (1, (era
->offset
1023 + (era
->direction
== '-' ? -delta
: delta
)));
1027 DO_NUMBER (2, (tp
->tm_year
% 100 + 100) % 100);
1035 cpy (zonelen
, zone
);
1038 case 'z': /* GNU extension. */
1039 if (tp
->tm_isdst
< 0)
1045 diff
= tp
->tm_gmtoff
;
1054 if (lt
== (time_t) -1)
1056 /* mktime returns -1 for errors, but -1 is also a
1057 valid time_t value. Check whether an error really
1060 localtime_r (<
, &tm
);
1062 if ((ltm
.tm_sec
^ tm
.tm_sec
)
1063 | (ltm
.tm_min
^ tm
.tm_min
)
1064 | (ltm
.tm_hour
^ tm
.tm_hour
)
1065 | (ltm
.tm_mday
^ tm
.tm_mday
)
1066 | (ltm
.tm_mon
^ tm
.tm_mon
)
1067 | (ltm
.tm_year
^ tm
.tm_year
))
1071 if (! gmtime_r (<
, >m
))
1074 diff
= tm_diff (<m
, >m
);
1086 DO_NUMBER (4, (diff
/ 60) * 100 + diff
% 60);
1089 case '\0': /* GNU extension: % at end of format. */
1093 /* Unknown format; output the format, including the '%',
1094 since this is most likely the right thing to do if a
1095 multibyte string has been misparsed. */
1099 for (flen
= 1; f
[1 - flen
] != '%'; flen
++)
1101 cpy (flen
, &f
[1 - flen
]);