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 <ansidecl.h>
35 # include "../locale/localeinfo.h"
39 #include <sys/types.h> /* Some systems define `time_t' here. */
41 #ifdef TIME_WITH_SYS_TIME
42 # include <sys/time.h>
45 # ifdef HAVE_SYS_TIME_H
46 # include <sys/time.h>
52 extern char *tzname
[];
55 /* Do multibyte processing if multibytes are supported, unless
56 multibyte sequences are safe in formats. Multibyte sequences are
57 safe if they cannot contain byte sequences that look like format
58 conversion specifications. The GNU C Library uses UTF8 multibyte
59 encoding, which is safe for formats, but strftime.c can be used
60 with other C libraries that use unsafe encodings. */
61 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
67 /* Simulate mbrlen with mblen as best we can. */
68 # define mbstate_t int
69 # define mbrlen(s, n, ps) mblen (s, n)
70 # define mbsinit(ps) (*(ps) == 0)
72 static const mbstate_t mbstate_zero
;
84 # define memcpy(d, s, n) bcopy ((s), (d), (n))
88 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
89 # define __P(args) args
111 #define TYPE_SIGNED(t) ((t) -1 < 0)
113 /* Bound on length of the string representing an integer value of type t.
114 Subtract one for the sign bit if t is signed;
115 302 / 1000 is log10 (2) rounded up;
116 add one for integer division truncation;
117 add one more for a minus sign if t is signed. */
118 #define INT_STRLEN_BOUND(t) \
119 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 100 + 1 + TYPE_SIGNED (t))
121 #define TM_YEAR_BASE 1900
124 /* Nonzero if YEAR is a leap year (every 4 years,
125 except every 100th isn't, and every 400th is). */
126 # define __isleap(year) \
127 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
132 # define gmtime_r __gmtime_r
133 # define localtime_r __localtime_r
134 extern int __tz_compute
__P ((time_t timer
, const struct tm
*tm
));
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_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 static const char spaces
[16] = " ";
179 # define memset_space(P, Len) \
185 int _this = _len > 16 ? 16 : _len; \
186 memcpy ((P), spaces, _this); \
193 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
200 int _delta = width - _n; \
201 int _incr = _n + (_delta > 0 ? _delta : 0); \
202 if (i + _incr >= maxsize) \
207 memset_space (p, _delta); \
217 memcpy_lowcase (p, (s), _n); \
218 else if (to_uppcase) \
219 memcpy_uppcase (p, (s), _n); \
221 memcpy ((PTR) p, (PTR) (s), _n))
226 # define TOUPPER(Ch) toupper (Ch)
227 # define TOLOWER(Ch) tolower (Ch)
229 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
230 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
232 /* We don't use `isdigit' here since the locale dependent
233 interpretation is not what we want here. We only need to accept
234 the arabic digits in the ASCII range. One day there is perhaps a
235 more reliable way to accept other sets of digits. */
236 #define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
238 static char *memcpy_lowcase
__P ((char *dest
, const char *src
, size_t len
));
241 memcpy_lowcase (dest
, src
, len
)
247 dest
[len
] = TOLOWER (src
[len
]);
251 static char *memcpy_uppcase
__P ((char *dest
, const char *src
, size_t len
));
254 memcpy_uppcase (dest
, src
, len
)
260 dest
[len
] = TOUPPER (src
[len
]);
265 /* Yield the difference between *A and *B,
266 measured in seconds, ignoring leap seconds. */
267 static int tm_diff
__P ((const struct tm
*, const struct tm
*));
273 /* Compute intervening leap days correctly even if year is negative.
274 Take care to avoid int overflow in leap day calculations,
275 but it's OK to assume that A and B are close to each other. */
276 int a4
= (a
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (a
->tm_year
& 3);
277 int b4
= (b
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (b
->tm_year
& 3);
278 int a100
= a4
/ 25 - (a4
% 25 < 0);
279 int b100
= b4
/ 25 - (b4
% 25 < 0);
280 int a400
= a100
>> 2;
281 int b400
= b100
>> 2;
282 int intervening_leap_days
= (a4
- b4
) - (a100
- b100
) + (a400
- b400
);
283 int years
= a
->tm_year
- b
->tm_year
;
284 int days
= (365 * years
+ intervening_leap_days
285 + (a
->tm_yday
- b
->tm_yday
));
286 return (60 * (60 * (24 * days
+ (a
->tm_hour
- b
->tm_hour
))
287 + (a
->tm_min
- b
->tm_min
))
288 + (a
->tm_sec
- b
->tm_sec
));
290 #endif /* ! HAVE_TM_GMTOFF */
294 /* The number of days from the first day of the first ISO week of this
295 year to the year day YDAY with week day WDAY. ISO weeks start on
296 Monday; the first ISO week has the year's first Thursday. YDAY may
297 be as small as YDAY_MINIMUM. */
298 #define ISO_WEEK_START_WDAY 1 /* Monday */
299 #define ISO_WEEK1_WDAY 4 /* Thursday */
300 #define YDAY_MINIMUM (-366)
301 static int iso_week_days
__P ((int, int));
306 iso_week_days (yday
, wday
)
310 /* Add enough to the first operand of % to make it nonnegative. */
311 int big_enough_multiple_of_7
= (-YDAY_MINIMUM
/ 7 + 2) * 7;
313 - (yday
- wday
+ ISO_WEEK1_WDAY
+ big_enough_multiple_of_7
) % 7
314 + ISO_WEEK1_WDAY
- ISO_WEEK_START_WDAY
);
319 static char const weekday_name
[][10] =
321 "Sunday", "Monday", "Tuesday", "Wednesday",
322 "Thursday", "Friday", "Saturday"
324 static char const month_name
[][10] =
326 "January", "February", "March", "April", "May", "June",
327 "July", "August", "September", "October", "November", "December"
332 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
333 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
334 Work around this bug by copying *tp before it might be munged. */
335 size_t _strftime_copytm
__P ((char *, size_t, const char *,
338 strftime (s
, maxsize
, format
, tp
)
346 return _strftime_copytm (s
, maxsize
, format
, &tmcopy
);
351 # define strftime(S, Maxsize, Format, Tp) \
352 _strftime_copytm (S, Maxsize, Format, Tp)
356 /* Write information from TP into S according to the format
357 string FORMAT, writing no more that MAXSIZE characters
358 (including the terminating '\0') and returning number of
359 characters written. If S is NULL, nothing will be written
360 anywhere, so to determine how many characters would be
361 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
363 strftime (s
, maxsize
, format
, tp
)
369 int hour12
= tp
->tm_hour
;
371 const char *const a_wkday
= _NL_CURRENT (LC_TIME
, ABDAY_1
+ tp
->tm_wday
);
372 const char *const f_wkday
= _NL_CURRENT (LC_TIME
, DAY_1
+ tp
->tm_wday
);
373 const char *const a_month
= _NL_CURRENT (LC_TIME
, ABMON_1
+ tp
->tm_mon
);
374 const char *const f_month
= _NL_CURRENT (LC_TIME
, MON_1
+ tp
->tm_mon
);
375 const char *const ampm
= _NL_CURRENT (LC_TIME
,
376 hour12
> 11 ? PM_STR
: AM_STR
);
377 size_t aw_len
= strlen (a_wkday
);
378 size_t am_len
= strlen (a_month
);
379 size_t ap_len
= strlen (ampm
);
381 const char *const f_wkday
= weekday_name
[tp
->tm_wday
];
382 const char *const f_month
= month_name
[tp
->tm_mon
];
383 const char *const a_wkday
= f_wkday
;
384 const char *const a_month
= f_month
;
385 const char *const ampm
= "AMPM" + 2 * (hour12
> 11);
390 size_t wkday_len
= strlen (f_wkday
);
391 size_t month_len
= strlen (f_month
);
399 #if !defined _LIBC && HAVE_TM_ZONE
400 /* XXX We have some problems here. First, the string pointed to by
401 tm_zone is dynamically allocated while loading the zone data. But
402 when another zone is loaded since the information in TP were
403 computed this would be a stale pointer.
404 The second problem is the POSIX test suite which assumes setting
405 the environment variable TZ to a new value before calling strftime()
406 will influence the result (the %Z format) even if the information in
407 TP is computed with a totally different time zone. --drepper@gnu */
408 zone
= (const char *) tp
->tm_zone
;
411 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
412 time zone names contained in the external variable `tzname' shall
413 be set as if the tzset() function had been called. */
418 if (!(zone
&& *zone
) && tp
->tm_isdst
>= 0)
419 zone
= tzname
[tp
->tm_isdst
];
422 zone
= ""; /* POSIX.2 requires the empty string here. */
424 zonelen
= strlen (zone
);
429 if (hour12
== 0) hour12
= 12;
431 for (f
= format
; *f
!= '\0'; ++f
)
433 int pad
; /* Padding for number ('-', '_', or 0). */
434 int modifier
; /* Field modifier ('E', 'O', or 0). */
435 int digits
; /* Max digits for numeric format. */
436 int number_value
; /* Numeric value to be printed. */
437 int negative_number
; /* 1 if the number is negative. */
440 char buf
[1 + (sizeof (int) < sizeof (time_t)
441 ? INT_STRLEN_BOUND (time_t)
442 : INT_STRLEN_BOUND (int))];
454 case '\a': case '\b': case '\t': case '\n':
455 case '\v': case '\f': case '\r':
456 case ' ': case '!': case '"': case '#': case '&': case'\'':
457 case '(': case ')': case '*': case '+': case ',': case '-':
458 case '.': case '/': case '0': case '1': case '2': case '3':
459 case '4': case '5': case '6': case '7': case '8': case '9':
460 case ':': case ';': case '<': case '=': case '>': case '?':
461 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
462 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
463 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
464 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
465 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
466 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
467 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
468 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
469 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
470 case 'x': case 'y': case 'z': case '{': case '|': case '}':
472 /* The C Standard requires these 98 characters (plus '%') to
473 be in the basic execution character set. None of these
474 characters can start a multibyte sequence, so they need
475 not be analyzed further. */
480 /* Copy this multibyte sequence until we reach its end, find
481 an error, or come back to the initial shift state. */
483 mbstate_t mbstate
= mbstate_zero
;
488 size_t bytes
= mbrlen (f
+ len
, (size_t) -1, &mbstate
);
493 if (bytes
== (size_t) -2 || bytes
== (size_t) -1)
501 while (! mbsinit (&mbstate
));
508 #else /* ! DO_MULTIBYTE */
510 /* Either multibyte encodings are not supported, or they are
511 safe for formats, so any non-'%' byte can be copied through. */
518 #endif /* ! DO_MULTIBYTE */
520 /* Check for flags that can modify a format. */
526 /* This influences the number formats. */
533 /* This changes textual output. */
544 /* As a GNU extension we allow to specify the field width. */
554 while (ISDIGIT (*f
));
557 /* Check for modifiers. */
570 /* Now do the specified format. */
573 #define DO_NUMBER(d, v) \
574 digits = d; number_value = v; goto do_number
575 #define DO_NUMBER_SPACEPAD(d, v) \
576 digits = d; number_value = v; goto do_number_spacepad
587 cpy (aw_len
, a_wkday
);
593 cpy (wkday_len
, f_wkday
);
597 case 'h': /* POSIX.2 extension. */
600 cpy (am_len
, a_month
);
606 cpy (month_len
, f_month
);
613 if (! (modifier
== 'E'
614 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_T_FMT
)) != '\0'))
615 subfmt
= _NL_CURRENT (LC_TIME
, D_T_FMT
);
617 subfmt
= "%a %b %e %H:%M:%S %Y";
623 size_t len
= strftime (NULL
, maxsize
- i
, subfmt
, tp
);
624 if (len
== 0 && *subfmt
)
626 add (len
, strftime (p
, maxsize
- i
, subfmt
, tp
));
629 while (old_start
< p
)
631 *old_start
= TOUPPER (*old_start
);
637 case 'C': /* POSIX.2 extension. */
640 #if HAVE_STRUCT_ERA_ENTRY
643 struct era_entry
*era
= _nl_get_era_entry (tp
);
646 size_t len
= strlen (era
->name_fmt
);
647 cpy (len
, era
->name_fmt
);
653 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
654 DO_NUMBER (1, year
/ 100 - (year
% 100 < 0));
661 if (! (modifier
== 'E'
662 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_FMT
)) != '\0'))
663 subfmt
= _NL_CURRENT (LC_TIME
, D_FMT
);
667 case 'D': /* POSIX.2 extension. */
677 DO_NUMBER (2, tp
->tm_mday
);
679 case 'e': /* POSIX.2 extension. */
683 DO_NUMBER_SPACEPAD (2, tp
->tm_mday
);
685 /* All numeric formats set DIGITS and NUMBER_VALUE and then
686 jump to one of these two labels. */
689 /* Force `_' flag unless overwritten by `0' flag. */
694 /* Format the number according to the MODIFIER flag. */
697 if (modifier
== 'O' && 0 <= number_value
)
699 /* Get the locale specific alternate representation of
700 the number NUMBER_VALUE. If none exist NULL is returned. */
701 const char *cp
= _nl_get_alt_digit (number_value
);
705 size_t digitlen
= strlen (cp
);
715 unsigned int u
= number_value
;
717 bufp
= buf
+ sizeof (buf
);
718 negative_number
= number_value
< 0;
724 *--bufp
= u
% 10 + '0';
725 while ((u
/= 10) != 0);
728 do_number_sign_and_padding
:
734 int padding
= digits
- (buf
+ sizeof (buf
) - bufp
);
738 while (0 < padding
--)
743 bufp
+= negative_number
;
744 while (0 < padding
--)
751 cpy (buf
+ sizeof (buf
) - bufp
, bufp
);
759 DO_NUMBER (2, tp
->tm_hour
);
765 DO_NUMBER (2, hour12
);
767 case 'k': /* GNU extension. */
771 DO_NUMBER_SPACEPAD (2, tp
->tm_hour
);
773 case 'l': /* GNU extension. */
777 DO_NUMBER_SPACEPAD (2, hour12
);
783 DO_NUMBER (3, 1 + tp
->tm_yday
);
789 DO_NUMBER (2, tp
->tm_min
);
795 DO_NUMBER (2, tp
->tm_mon
+ 1);
797 case 'n': /* POSIX.2 extension. */
809 case 'R': /* GNU extension. */
813 case 'r': /* POSIX.2 extension. */
815 if (*(subfmt
= _NL_CURRENT (LC_TIME
, T_FMT_AMPM
)) == '\0')
817 subfmt
= "%I:%M:%S %p";
824 DO_NUMBER (2, tp
->tm_sec
);
826 case 's': /* GNU extension. */
834 /* Generate string value for T using time_t arithmetic;
835 this works even if sizeof (long) < sizeof (time_t). */
837 bufp
= buf
+ sizeof (buf
);
838 negative_number
= t
< 0;
849 /* Adjust if division truncates to minus infinity. */
850 if (0 < -1 % 10 && d
< 0)
862 goto do_number_sign_and_padding
;
869 if (! (modifier
== 'E'
870 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_T_FMT
)) != '\0'))
871 subfmt
= _NL_CURRENT (LC_TIME
, T_FMT
);
875 case 'T': /* POSIX.2 extension. */
879 case 't': /* POSIX.2 extension. */
883 case 'u': /* POSIX.2 extension. */
884 DO_NUMBER (1, (tp
->tm_wday
- 1 + 7) % 7 + 1);
890 DO_NUMBER (2, (tp
->tm_yday
- tp
->tm_wday
+ 7) / 7);
893 case 'g': /* GNU extension. */
894 case 'G': /* GNU extension. */
898 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
899 int days
= iso_week_days (tp
->tm_yday
, tp
->tm_wday
);
903 /* This ISO week belongs to the previous year. */
905 days
= iso_week_days (tp
->tm_yday
+ (365 + __isleap (year
)),
910 int d
= iso_week_days (tp
->tm_yday
- (365 + __isleap (year
)),
914 /* This ISO week belongs to the next year. */
923 DO_NUMBER (2, (year
% 100 + 100) % 100);
929 DO_NUMBER (2, days
/ 7 + 1);
937 DO_NUMBER (2, (tp
->tm_yday
- (tp
->tm_wday
- 1 + 7) % 7 + 7) / 7);
943 DO_NUMBER (1, tp
->tm_wday
);
946 #if HAVE_STRUCT_ERA_ENTRY
949 struct era_entry
*era
= _nl_get_era_entry (tp
);
952 subfmt
= strchr (era
->name_fmt
, '\0') + 1;
960 DO_NUMBER (1, tp
->tm_year
+ TM_YEAR_BASE
);
963 #if HAVE_STRUCT_ERA_ENTRY
966 struct era_entry
*era
= _nl_get_era_entry (tp
);
969 int delta
= tp
->tm_year
- era
->start_date
[0];
970 DO_NUMBER (1, (era
->offset
971 + (era
->direction
== '-' ? -delta
: delta
)));
975 DO_NUMBER (2, (tp
->tm_year
% 100 + 100) % 100);
981 case 'z': /* GNU extension. */
982 if (tp
->tm_isdst
< 0)
988 diff
= tp
->tm_gmtoff
;
997 if (lt
== (time_t) -1)
999 /* mktime returns -1 for errors, but -1 is also a
1000 valid time_t value. Check whether an error really
1003 localtime_r (<
, &tm
);
1005 if ((ltm
.tm_sec
^ tm
.tm_sec
)
1006 | (ltm
.tm_min
^ tm
.tm_min
)
1007 | (ltm
.tm_hour
^ tm
.tm_hour
)
1008 | (ltm
.tm_mday
^ tm
.tm_mday
)
1009 | (ltm
.tm_mon
^ tm
.tm_mon
)
1010 | (ltm
.tm_year
^ tm
.tm_year
))
1014 if (! gmtime_r (<
, >m
))
1017 diff
= tm_diff (<m
, >m
);
1029 DO_NUMBER (4, (diff
/ 60) * 100 + diff
% 60);
1032 case '\0': /* GNU extension: % at end of format. */
1036 /* Unknown format; output the format, including the '%',
1037 since this is most likely the right thing to do if a
1038 multibyte string has been misparsed. */
1042 for (flen
= 1; f
[1 - flen
] != '%'; flen
++)
1044 cpy (flen
, &f
[1 - flen
]);