1 /* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
3 NOTE: The canonical source of this file is maintained with the GNU C Library.
4 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
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26 # define HAVE_LIMITS_H 1
28 # define HAVE_MBRLEN 1
29 # define HAVE_STRUCT_ERA_ENTRY 1
30 # define HAVE_TM_GMTOFF 1
31 # define HAVE_TM_ZONE 1
32 # define HAVE_TZNAME 1
34 # define MULTIBYTE_IS_FORMAT_SAFE 1
35 # define STDC_HEADERS 1
36 # include <ansidecl.h>
37 # include "../locale/localeinfo.h"
41 #include <sys/types.h> /* Some systems define `time_t' here. */
43 #ifdef TIME_WITH_SYS_TIME
44 # include <sys/time.h>
47 # ifdef HAVE_SYS_TIME_H
48 # include <sys/time.h>
54 extern char *tzname
[];
57 /* Do multibyte processing if multibytes are supported, unless
58 multibyte sequences are safe in formats. Multibyte sequences are
59 safe if they cannot contain byte sequences that look like format
60 conversion specifications. The GNU C Library uses UTF8 multibyte
61 encoding, which is safe for formats, but strftime.c can be used
62 with other C libraries that use unsafe encodings. */
63 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
69 /* Simulate mbrlen with mblen as best we can. */
70 # define mbstate_t int
71 # define mbrlen(s, n, ps) mblen (s, n)
72 # define mbsinit(ps) (*(ps) == 0)
74 static const mbstate_t mbstate_zero
;
86 # define memcpy(d, s, n) bcopy ((s), (d), (n))
90 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
91 # define __P(args) args
113 #define TYPE_SIGNED(t) ((t) -1 < 0)
115 /* Bound on length of the string representing an integer value of type t.
116 Subtract one for the sign bit if t is signed;
117 302 / 1000 is log10 (2) rounded up;
118 add one for integer division truncation;
119 add one more for a minus sign if t is signed. */
120 #define INT_STRLEN_BOUND(t) \
121 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 100 + 1 + TYPE_SIGNED (t))
123 #define TM_YEAR_BASE 1900
126 /* Nonzero if YEAR is a leap year (every 4 years,
127 except every 100th isn't, and every 400th is). */
128 # define __isleap(year) \
129 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
134 # define gmtime_r __gmtime_r
135 # define localtime_r __localtime_r
136 extern int __tz_compute
__P ((time_t timer
, const struct tm
*tm
));
137 # define tzname __tzname
138 # define tzset __tzset
140 # if ! HAVE_LOCALTIME_R
141 # if ! HAVE_TM_GMTOFF
142 /* Approximate gmtime_r as best we can in its absence. */
143 # define gmtime_r my_gmtime_r
144 static struct tm
*gmtime_r
__P ((const time_t *, struct tm
*));
150 struct tm
*l
= gmtime (t
);
156 # endif /* ! HAVE_TM_GMTOFF */
158 /* Approximate localtime_r as best we can in its absence. */
159 # define localtime_r my_localtime_r
160 static struct tm
*localtime_r
__P ((const time_t *, struct tm
*));
166 struct tm
*l
= localtime (t
);
172 # endif /* ! HAVE_LOCALTIME_R */
173 #endif /* ! defined (_LIBC) */
176 #if !defined (memset) && !defined (HAVE_MEMSET) && !defined (_LIBC)
177 /* Some systems lack the `memset' function and we don't want to
178 introduce additional dependencies. */
179 static const char spaces
[16] = " ";
181 # define memset_space(P, Len) \
187 int _this = _len > 16 ? 16 : _len; \
188 memcpy ((P), spaces, _this); \
195 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
202 int _delta = width - _n; \
203 int _incr = _n + (_delta > 0 ? _delta : 0); \
204 if (i + _incr >= maxsize) \
209 memset_space (p, _delta); \
219 memcpy_lowcase (p, (s), _n); \
220 else if (to_uppcase) \
221 memcpy_uppcase (p, (s), _n); \
223 memcpy ((PTR) p, (PTR) (s), _n))
228 # define TOUPPER(Ch) toupper (Ch)
229 # define TOLOWER(Ch) tolower (Ch)
231 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
232 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
234 /* We don't use `isdigit' here since the locale dependent
235 interpretation is not what we want here. We only need to accept
236 the arabic digits in the ASCII range. One day there is perhaps a
237 more reliable way to accept other sets of digits. */
238 #define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
240 static char *memcpy_lowcase
__P ((char *dest
, const char *src
, size_t len
));
243 memcpy_lowcase (dest
, src
, len
)
249 dest
[len
] = TOLOWER (src
[len
]);
253 static char *memcpy_uppcase
__P ((char *dest
, const char *src
, size_t len
));
256 memcpy_uppcase (dest
, src
, len
)
262 dest
[len
] = TOUPPER (src
[len
]);
267 /* Yield the difference between *A and *B,
268 measured in seconds, ignoring leap seconds. */
269 static int tm_diff
__P ((const struct tm
*, const struct tm
*));
275 /* Compute intervening leap days correctly even if year is negative.
276 Take care to avoid int overflow in leap day calculations,
277 but it's OK to assume that A and B are close to each other. */
278 int a4
= (a
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (a
->tm_year
& 3);
279 int b4
= (b
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (b
->tm_year
& 3);
280 int a100
= a4
/ 25 - (a4
% 25 < 0);
281 int b100
= b4
/ 25 - (b4
% 25 < 0);
282 int a400
= a100
>> 2;
283 int b400
= b100
>> 2;
284 int intervening_leap_days
= (a4
- b4
) - (a100
- b100
) + (a400
- b400
);
285 int years
= a
->tm_year
- b
->tm_year
;
286 int days
= (365 * years
+ intervening_leap_days
287 + (a
->tm_yday
- b
->tm_yday
));
288 return (60 * (60 * (24 * days
+ (a
->tm_hour
- b
->tm_hour
))
289 + (a
->tm_min
- b
->tm_min
))
290 + (a
->tm_sec
- b
->tm_sec
));
292 #endif /* ! HAVE_TM_GMTOFF */
296 /* The number of days from the first day of the first ISO week of this
297 year to the year day YDAY with week day WDAY. ISO weeks start on
298 Monday; the first ISO week has the year's first Thursday. YDAY may
299 be as small as YDAY_MINIMUM. */
300 #define ISO_WEEK_START_WDAY 1 /* Monday */
301 #define ISO_WEEK1_WDAY 4 /* Thursday */
302 #define YDAY_MINIMUM (-366)
303 static int iso_week_days
__P ((int, int));
308 iso_week_days (yday
, wday
)
312 /* Add enough to the first operand of % to make it nonnegative. */
313 int big_enough_multiple_of_7
= (-YDAY_MINIMUM
/ 7 + 2) * 7;
315 - (yday
- wday
+ ISO_WEEK1_WDAY
+ big_enough_multiple_of_7
) % 7
316 + ISO_WEEK1_WDAY
- ISO_WEEK_START_WDAY
);
321 static char const weekday_name
[][10] =
323 "Sunday", "Monday", "Tuesday", "Wednesday",
324 "Thursday", "Friday", "Saturday"
326 static char const month_name
[][10] =
328 "January", "February", "March", "April", "May", "June",
329 "July", "August", "September", "October", "November", "December"
334 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
335 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
336 Work around this bug by copying *tp before it might be munged. */
337 size_t _strftime_copytm
__P ((char *, size_t, const char *,
340 strftime (s
, maxsize
, format
, tp
)
348 return _strftime_copytm (s
, maxsize
, format
, &tmcopy
);
353 # define strftime(S, Maxsize, Format, Tp) \
354 _strftime_copytm (S, Maxsize, Format, Tp)
358 /* Write information from TP into S according to the format
359 string FORMAT, writing no more that MAXSIZE characters
360 (including the terminating '\0') and returning number of
361 characters written. If S is NULL, nothing will be written
362 anywhere, so to determine how many characters would be
363 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
365 strftime (s
, maxsize
, format
, tp
)
371 int hour12
= tp
->tm_hour
;
373 const char *const a_wkday
= _NL_CURRENT (LC_TIME
, ABDAY_1
+ tp
->tm_wday
);
374 const char *const f_wkday
= _NL_CURRENT (LC_TIME
, DAY_1
+ tp
->tm_wday
);
375 const char *const a_month
= _NL_CURRENT (LC_TIME
, ABMON_1
+ tp
->tm_mon
);
376 const char *const f_month
= _NL_CURRENT (LC_TIME
, MON_1
+ tp
->tm_mon
);
377 const char *const ampm
= _NL_CURRENT (LC_TIME
,
378 hour12
> 11 ? PM_STR
: AM_STR
);
379 size_t aw_len
= strlen (a_wkday
);
380 size_t am_len
= strlen (a_month
);
381 size_t ap_len
= strlen (ampm
);
383 const char *const f_wkday
= weekday_name
[tp
->tm_wday
];
384 const char *const f_month
= month_name
[tp
->tm_mon
];
385 const char *const a_wkday
= f_wkday
;
386 const char *const a_month
= f_month
;
387 const char *const ampm
= "AMPM" + 2 * (hour12
> 11);
392 size_t wkday_len
= strlen (f_wkday
);
393 size_t month_len
= strlen (f_month
);
401 #if !defined _LIBC && HAVE_TM_ZONE
402 /* XXX We have some problems here. First, the string pointed to by
403 tm_zone is dynamically allocated while loading the zone data. But
404 when another zone is loaded since the information in TP were
405 computed this would be a stale pointer.
406 The second problem is the POSIX test suite which assumes setting
407 the environment variable TZ to a new value before calling strftime()
408 will influence the result (the %Z format) even if the information in
409 TP is computed with a totally different time zone. --drepper@gnu */
410 zone
= (const char *) tp
->tm_zone
;
413 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
414 time zone names contained in the external variable `tzname' shall
415 be set as if the tzset() function had been called. */
420 if (!(zone
&& *zone
) && tp
->tm_isdst
>= 0)
421 zone
= tzname
[tp
->tm_isdst
];
424 zone
= ""; /* POSIX.2 requires the empty string here. */
426 zonelen
= strlen (zone
);
431 if (hour12
== 0) hour12
= 12;
433 for (f
= format
; *f
!= '\0'; ++f
)
435 int pad
; /* Padding for number ('-', '_', or 0). */
436 int modifier
; /* Field modifier ('E', 'O', or 0). */
437 int digits
; /* Max digits for numeric format. */
438 int number_value
; /* Numeric value to be printed. */
439 int negative_number
; /* 1 if the number is negative. */
442 char buf
[1 + (sizeof (int) < sizeof (time_t)
443 ? INT_STRLEN_BOUND (time_t)
444 : INT_STRLEN_BOUND (int))];
456 case '\a': case '\b': case '\t': case '\n':
457 case '\v': case '\f': case '\r':
458 case ' ': case '!': case '"': case '#': case '&': case'\'':
459 case '(': case ')': case '*': case '+': case ',': case '-':
460 case '.': case '/': case '0': case '1': case '2': case '3':
461 case '4': case '5': case '6': case '7': case '8': case '9':
462 case ':': case ';': case '<': case '=': case '>': case '?':
463 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
464 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
465 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
466 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
467 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
468 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
469 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
470 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
471 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
472 case 'x': case 'y': case 'z': case '{': case '|': case '}':
474 /* The C Standard requires these 98 characters (plus '%') to
475 be in the basic execution character set. None of these
476 characters can start a multibyte sequence, so they need
477 not be analyzed further. */
482 /* Copy this multibyte sequence until we reach its end, find
483 an error, or come back to the initial shift state. */
485 mbstate_t mbstate
= mbstate_zero
;
490 size_t bytes
= mbrlen (f
+ len
, (size_t) -1, &mbstate
);
495 if (bytes
== (size_t) -2 || bytes
== (size_t) -1)
503 while (! mbsinit (&mbstate
));
510 #else /* ! DO_MULTIBYTE */
512 /* Either multibyte encodings are not supported, or they are
513 safe for formats, so any non-'%' byte can be copied through. */
520 #endif /* ! DO_MULTIBYTE */
522 /* Check for flags that can modify a format. */
528 /* This influences the number formats. */
535 /* This changes textual output. */
546 /* As a GNU extension we allow to specify the field width. */
556 while (ISDIGIT (*f
));
559 /* Check for modifiers. */
572 /* Now do the specified format. */
575 #define DO_NUMBER(d, v) \
576 digits = d; number_value = v; goto do_number
577 #define DO_NUMBER_SPACEPAD(d, v) \
578 digits = d; number_value = v; goto do_number_spacepad
589 cpy (aw_len
, a_wkday
);
595 cpy (wkday_len
, f_wkday
);
599 case 'h': /* POSIX.2 extension. */
602 cpy (am_len
, a_month
);
608 cpy (month_len
, f_month
);
615 if (! (modifier
== 'E'
616 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_T_FMT
)) != '\0'))
617 subfmt
= _NL_CURRENT (LC_TIME
, D_T_FMT
);
619 subfmt
= "%a %b %e %H:%M:%S %Y";
625 size_t len
= strftime (NULL
, maxsize
- i
, subfmt
, tp
);
626 if (len
== 0 && *subfmt
)
628 add (len
, strftime (p
, maxsize
- i
, subfmt
, tp
));
631 while (old_start
< p
)
633 *old_start
= TOUPPER (*old_start
);
639 case 'C': /* POSIX.2 extension. */
642 #if HAVE_STRUCT_ERA_ENTRY
645 struct era_entry
*era
= _nl_get_era_entry (tp
);
648 size_t len
= strlen (era
->name_fmt
);
649 cpy (len
, era
->name_fmt
);
655 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
656 DO_NUMBER (1, year
/ 100 - (year
% 100 < 0));
663 if (! (modifier
== 'E'
664 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_D_FMT
)) != '\0'))
665 subfmt
= _NL_CURRENT (LC_TIME
, D_FMT
);
669 case 'D': /* POSIX.2 extension. */
679 DO_NUMBER (2, tp
->tm_mday
);
681 case 'e': /* POSIX.2 extension. */
685 DO_NUMBER_SPACEPAD (2, tp
->tm_mday
);
687 /* All numeric formats set DIGITS and NUMBER_VALUE and then
688 jump to one of these two labels. */
691 /* Force `_' flag unless overwritten by `0' flag. */
696 /* Format the number according to the MODIFIER flag. */
699 if (modifier
== 'O' && 0 <= number_value
)
701 /* Get the locale specific alternate representation of
702 the number NUMBER_VALUE. If none exist NULL is returned. */
703 const char *cp
= _nl_get_alt_digit (number_value
);
707 size_t digitlen
= strlen (cp
);
717 unsigned int u
= number_value
;
719 bufp
= buf
+ sizeof (buf
);
720 negative_number
= number_value
< 0;
726 *--bufp
= u
% 10 + '0';
727 while ((u
/= 10) != 0);
730 do_number_sign_and_padding
:
736 int padding
= digits
- (buf
+ sizeof (buf
) - bufp
);
740 while (0 < padding
--)
745 bufp
+= negative_number
;
746 while (0 < padding
--)
753 cpy (buf
+ sizeof (buf
) - bufp
, bufp
);
761 DO_NUMBER (2, tp
->tm_hour
);
767 DO_NUMBER (2, hour12
);
769 case 'k': /* GNU extension. */
773 DO_NUMBER_SPACEPAD (2, tp
->tm_hour
);
775 case 'l': /* GNU extension. */
779 DO_NUMBER_SPACEPAD (2, hour12
);
785 DO_NUMBER (3, 1 + tp
->tm_yday
);
791 DO_NUMBER (2, tp
->tm_min
);
797 DO_NUMBER (2, tp
->tm_mon
+ 1);
799 case 'n': /* POSIX.2 extension. */
811 case 'R': /* GNU extension. */
815 case 'r': /* POSIX.2 extension. */
817 if (*(subfmt
= _NL_CURRENT (LC_TIME
, T_FMT_AMPM
)) == '\0')
819 subfmt
= "%I:%M:%S %p";
826 DO_NUMBER (2, tp
->tm_sec
);
828 case 's': /* GNU extension. */
836 /* Generate string value for T using time_t arithmetic;
837 this works even if sizeof (long) < sizeof (time_t). */
839 bufp
= buf
+ sizeof (buf
);
840 negative_number
= t
< 0;
851 /* Adjust if division truncates to minus infinity. */
852 if (0 < -1 % 10 && d
< 0)
864 goto do_number_sign_and_padding
;
871 if (! (modifier
== 'E'
872 && *(subfmt
= _NL_CURRENT (LC_TIME
, ERA_T_FMT
)) != '\0'))
873 subfmt
= _NL_CURRENT (LC_TIME
, T_FMT
);
877 case 'T': /* POSIX.2 extension. */
881 case 't': /* POSIX.2 extension. */
885 case 'u': /* POSIX.2 extension. */
886 DO_NUMBER (1, (tp
->tm_wday
- 1 + 7) % 7 + 1);
892 DO_NUMBER (2, (tp
->tm_yday
- tp
->tm_wday
+ 7) / 7);
895 case 'g': /* GNU extension. */
896 case 'G': /* GNU extension. */
900 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
901 int days
= iso_week_days (tp
->tm_yday
, tp
->tm_wday
);
905 /* This ISO week belongs to the previous year. */
907 days
= iso_week_days (tp
->tm_yday
+ (365 + __isleap (year
)),
912 int d
= iso_week_days (tp
->tm_yday
- (365 + __isleap (year
)),
916 /* This ISO week belongs to the next year. */
925 DO_NUMBER (2, (year
% 100 + 100) % 100);
931 DO_NUMBER (2, days
/ 7 + 1);
939 DO_NUMBER (2, (tp
->tm_yday
- (tp
->tm_wday
- 1 + 7) % 7 + 7) / 7);
945 DO_NUMBER (1, tp
->tm_wday
);
948 #if HAVE_STRUCT_ERA_ENTRY
951 struct era_entry
*era
= _nl_get_era_entry (tp
);
954 subfmt
= strchr (era
->name_fmt
, '\0') + 1;
962 DO_NUMBER (1, tp
->tm_year
+ TM_YEAR_BASE
);
965 #if HAVE_STRUCT_ERA_ENTRY
968 struct era_entry
*era
= _nl_get_era_entry (tp
);
971 int delta
= tp
->tm_year
- era
->start_date
[0];
972 DO_NUMBER (1, (era
->offset
973 + (era
->direction
== '-' ? -delta
: delta
)));
977 DO_NUMBER (2, (tp
->tm_year
% 100 + 100) % 100);
983 case 'z': /* GNU extension. */
984 if (tp
->tm_isdst
< 0)
990 diff
= tp
->tm_gmtoff
;
999 if (lt
== (time_t) -1)
1001 /* mktime returns -1 for errors, but -1 is also a
1002 valid time_t value. Check whether an error really
1005 localtime_r (<
, &tm
);
1007 if ((ltm
.tm_sec
^ tm
.tm_sec
)
1008 | (ltm
.tm_min
^ tm
.tm_min
)
1009 | (ltm
.tm_hour
^ tm
.tm_hour
)
1010 | (ltm
.tm_mday
^ tm
.tm_mday
)
1011 | (ltm
.tm_mon
^ tm
.tm_mon
)
1012 | (ltm
.tm_year
^ tm
.tm_year
))
1016 if (! gmtime_r (<
, >m
))
1019 diff
= tm_diff (<m
, >m
);
1031 DO_NUMBER (4, (diff
/ 60) * 100 + diff
% 60);
1034 case '\0': /* GNU extension: % at end of format. */
1038 /* Unknown format; output the format, including the '%',
1039 since this is most likely the right thing to do if a
1040 multibyte string has been misparsed. */
1044 for (flen
= 1; f
[1 - flen
] != '%'; flen
++)
1046 cpy (flen
, &f
[1 - flen
]);