1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
2 This file is part of the GNU Emacs.
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"
37 #if defined emacs && !defined HAVE_BCOPY
38 # define HAVE_MEMCPY 1
42 #include <sys/types.h> /* Some systems define `time_t' here. */
44 #ifdef TIME_WITH_SYS_TIME
45 # include <sys/time.h>
48 # ifdef HAVE_SYS_TIME_H
49 # include <sys/time.h>
56 extern char *tzname
[];
60 /* Do multibyte processing if multibytes are supported, unless
61 multibyte sequences are safe in formats. Multibyte sequences are
62 safe if they cannot contain byte sequences that look like format
63 conversion specifications. The GNU C Library uses UTF8 multibyte
64 encoding, which is safe for formats, but strftime.c can be used
65 with other C libraries that use unsafe encodings. */
66 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
72 # include <sys/_mbstate_t.h>
74 # if !defined (mbsinit) && !defined (HAVE_MBSINIT)
75 # define mbsinit(ps) 1
76 # endif /* !defined (mbsinit) && !defined (HAVE_MBSINIT) */
78 /* Simulate mbrlen with mblen as best we can. */
79 # define mbstate_t int
80 # define mbrlen(s, n, ps) mblen (s, n)
81 # define mbsinit(ps) (*(ps) == 0)
83 static const mbstate_t mbstate_zero
;
95 # define memcpy(d, s, n) bcopy ((s), (d), (n))
101 # define CHAR_T wchar_t
102 # define UCHAR_T unsigned int
103 # define L_(Str) L##Str
104 # define NLW(Sym) _NL_W##Sym
106 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
107 # define STRLEN(s) __wcslen (s)
111 # define UCHAR_T unsigned char
113 # define NLW(Sym) Sym
115 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
116 # define MEMCPY(d, s, n) bcopy ((s), (d), (n))
118 # define MEMCPY(d, s, n) memcpy ((d), (s), (n))
120 # define STRLEN(s) strlen (s)
123 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
125 # ifndef HAVE_MEMPCPY
126 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
132 # if defined emacs && defined PROTOTYPES
133 # define __P(args) args
134 # elif defined __GNUC__ || (defined __STDC__ && __STDC__)
135 # define __P(args) args
137 # define __P(args) ()
139 #endif /* Not __P. */
157 #define TYPE_SIGNED(t) ((t) -1 < 0)
159 /* Bound on length of the string representing an integer value of type t.
160 Subtract one for the sign bit if t is signed;
161 302 / 1000 is log10 (2) rounded up;
162 add one for integer division truncation;
163 add one more for a minus sign if t is signed. */
164 #define INT_STRLEN_BOUND(t) \
165 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
167 #define TM_YEAR_BASE 1900
170 /* Nonzero if YEAR is a leap year (every 4 years,
171 except every 100th isn't, and every 400th is). */
172 # define __isleap(year) \
173 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
178 # define my_strftime_gmtime_r __gmtime_r
179 # define my_strftime_localtime_r __localtime_r
180 # define tzname __tzname
181 # define tzset __tzset
184 /* If we're a strftime substitute in a GNU program, then prefer gmtime
185 to gmtime_r, since many gmtime_r implementations are buggy.
186 Similarly for localtime_r. */
188 # if ! HAVE_TM_GMTOFF
189 static struct tm
*my_strftime_gmtime_r
__P ((const time_t *, struct tm
*));
191 my_strftime_gmtime_r (t
, tp
)
195 struct tm
*l
= gmtime (t
);
201 # endif /* ! HAVE_TM_GMTOFF */
203 static struct tm
*my_strftime_localtime_r
__P ((const time_t *, struct tm
*));
205 my_strftime_localtime_r (t
, tp
)
209 struct tm
*l
= localtime (t
);
215 #endif /* ! defined _LIBC */
218 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
219 /* Some systems lack the `memset' function and we don't want to
220 introduce additional dependencies. */
221 /* The SGI compiler reportedly barfs on the trailing null
222 if we use a string constant as the initializer. 28 June 1997, rms. */
223 static const CHAR_T spaces
[16] = /* " " */
225 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
226 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
228 static const CHAR_T zeroes
[16] = /* "0000000000000000" */
230 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
231 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
234 # define memset_space(P, Len) \
240 int _this = _len > 16 ? 16 : _len; \
241 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
247 # define memset_zero(P, Len) \
253 int _this = _len > 16 ? 16 : _len; \
254 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
261 # define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
262 # define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
264 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
265 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
273 int _delta = width - _n; \
274 int _incr = _n + (_delta > 0 ? _delta : 0); \
275 if (i + _incr >= maxsize) \
281 if (pad == L_('0')) \
282 memset_zero (p, _delta); \
284 memset_space (p, _delta); \
295 memcpy_lowcase (p, (s), _n); \
296 else if (to_uppcase) \
297 memcpy_uppcase (p, (s), _n); \
299 MEMCPY ((PTR) p, (PTR) (s), _n))
302 # define widen(os, ws, l) \
305 const char *__s = os; \
306 memset (&__st, '\0', sizeof (__st)); \
307 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
308 ws = alloca ((l + 1) * sizeof (wchar_t)); \
309 (void) __mbsrtowcs (ws, &__s, l, &__st); \
315 # define TOUPPER(Ch) towupper (Ch)
316 # define TOLOWER(Ch) towlower (Ch)
319 # define TOUPPER(Ch) toupper (Ch)
320 # define TOLOWER(Ch) tolower (Ch)
322 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
323 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
326 /* We don't use `isdigit' here since the locale dependent
327 interpretation is not what we want here. We only need to accept
328 the arabic digits in the ASCII range. One day there is perhaps a
329 more reliable way to accept other sets of digits. */
330 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
332 static CHAR_T
*memcpy_lowcase
__P ((CHAR_T
*dest
, const CHAR_T
*src
,
336 memcpy_lowcase (dest
, src
, len
)
342 dest
[len
] = TOLOWER ((UCHAR_T
) src
[len
]);
346 static CHAR_T
*memcpy_uppcase
__P ((CHAR_T
*dest
, const CHAR_T
*src
,
350 memcpy_uppcase (dest
, src
, len
)
356 dest
[len
] = TOUPPER ((UCHAR_T
) src
[len
]);
362 /* Yield the difference between *A and *B,
363 measured in seconds, ignoring leap seconds. */
364 # define tm_diff ftime_tm_diff
365 static int tm_diff
__P ((const struct tm
*, const struct tm
*));
371 /* Compute intervening leap days correctly even if year is negative.
372 Take care to avoid int overflow in leap day calculations,
373 but it's OK to assume that A and B are close to each other. */
374 int a4
= (a
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (a
->tm_year
& 3);
375 int b4
= (b
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (b
->tm_year
& 3);
376 int a100
= a4
/ 25 - (a4
% 25 < 0);
377 int b100
= b4
/ 25 - (b4
% 25 < 0);
378 int a400
= a100
>> 2;
379 int b400
= b100
>> 2;
380 int intervening_leap_days
= (a4
- b4
) - (a100
- b100
) + (a400
- b400
);
381 int years
= a
->tm_year
- b
->tm_year
;
382 int days
= (365 * years
+ intervening_leap_days
383 + (a
->tm_yday
- b
->tm_yday
));
384 return (60 * (60 * (24 * days
+ (a
->tm_hour
- b
->tm_hour
))
385 + (a
->tm_min
- b
->tm_min
))
386 + (a
->tm_sec
- b
->tm_sec
));
388 #endif /* ! HAVE_TM_GMTOFF */
392 /* The number of days from the first day of the first ISO week of this
393 year to the year day YDAY with week day WDAY. ISO weeks start on
394 Monday; the first ISO week has the year's first Thursday. YDAY may
395 be as small as YDAY_MINIMUM. */
396 #define ISO_WEEK_START_WDAY 1 /* Monday */
397 #define ISO_WEEK1_WDAY 4 /* Thursday */
398 #define YDAY_MINIMUM (-366)
399 static int iso_week_days
__P ((int, int));
404 iso_week_days (yday
, wday
)
408 /* Add enough to the first operand of % to make it nonnegative. */
409 int big_enough_multiple_of_7
= (-YDAY_MINIMUM
/ 7 + 2) * 7;
411 - (yday
- wday
+ ISO_WEEK1_WDAY
+ big_enough_multiple_of_7
) % 7
412 + ISO_WEEK1_WDAY
- ISO_WEEK_START_WDAY
);
416 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
417 static CHAR_T
const weekday_name
[][10] =
419 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
420 L_("Thursday"), L_("Friday"), L_("Saturday")
422 static CHAR_T
const month_name
[][10] =
424 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
425 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
426 L_("November"), L_("December")
432 # define my_strftime emacs_strftimeu
433 # define ut_argument , ut
434 # define ut_argument_spec int ut;
435 # define ut_argument_spec_iso , int ut
438 # define my_strftime wcsftime
440 # define my_strftime strftime
443 # define ut_argument_spec
444 # define ut_argument_spec_iso
445 /* We don't have this information in general. */
449 #if !defined _LIBC && !defined(WINDOWSNT) && HAVE_TZNAME && HAVE_TZSET
450 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
451 Work around this bug by copying *tp before it might be munged. */
452 size_t _strftime_copytm
__P ((char *, size_t, const char *,
453 const struct tm
* ut_argument_spec_iso
));
455 my_strftime (s
, maxsize
, format
, tp ut_argument
)
458 const CHAR_T
*format
;
464 return _strftime_copytm (s
, maxsize
, format
, &tmcopy ut_argument
);
467 # define my_strftime _strftime_copytm
471 /* Write information from TP into S according to the format
472 string FORMAT, writing no more that MAXSIZE characters
473 (including the terminating '\0') and returning number of
474 characters written. If S is NULL, nothing will be written
475 anywhere, so to determine how many characters would be
476 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
478 my_strftime (s
, maxsize
, format
, tp ut_argument
)
481 const CHAR_T
*format
;
485 int hour12
= tp
->tm_hour
;
487 /* We cannot make the following values variables since we must delay
488 the evaluation of these values until really needed since some
489 expressions might not be valid in every situation. The `struct tm'
490 might be generated by a strptime() call that initialized
491 only a few elements. Dereference the pointers only if the format
492 requires this. Then it is ok to fail if the pointers are invalid. */
494 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
496 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
498 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
500 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
502 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
503 ? NLW(PM_STR) : NLW(AM_STR)))
505 # define aw_len STRLEN (a_wkday)
506 # define am_len STRLEN (a_month)
507 # define ap_len STRLEN (ampm)
510 # define f_wkday (weekday_name[tp->tm_wday])
511 # define f_month (month_name[tp->tm_mon])
512 # define a_wkday f_wkday
513 # define a_month f_month
514 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
528 /* The POSIX test suite assumes that setting
529 the environment variable TZ to a new value before calling strftime()
530 will influence the result (the %Z format) even if the information in
531 TP is computed with a totally different time zone.
532 This is bogus: though POSIX allows bad behavior like this,
533 POSIX does not require it. Do the right thing instead. */
534 zone
= (const char *) tp
->tm_zone
;
539 if (! (zone
&& *zone
))
544 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
545 time zone names contained in the external variable `tzname' shall
546 be set as if the tzset() function had been called. */
559 for (f
= format
; *f
!= '\0'; ++f
)
561 int pad
= 0; /* Padding for number ('-', '_', or 0). */
562 int modifier
; /* Field modifier ('E', 'O', or 0). */
563 int digits
; /* Max digits for numeric format. */
564 int number_value
; /* Numeric value to be printed. */
565 int negative_number
; /* 1 if the number is negative. */
566 const CHAR_T
*subfmt
;
568 CHAR_T buf
[1 + (sizeof (int) < sizeof (time_t)
569 ? INT_STRLEN_BOUND (time_t)
570 : INT_STRLEN_BOUND (int))];
577 #if DO_MULTIBYTE && !defined COMPILE_WIDE
583 case L_('\b'): case L_('\t'): case L_('\n'):
584 case L_('\v'): case L_('\f'): case L_('\r'):
585 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
586 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
587 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
588 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
589 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
590 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
591 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
592 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
593 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
594 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
595 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
596 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
597 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
598 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
599 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
600 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
601 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
602 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
604 /* The C Standard requires these 97 characters (plus '%', `\a') to
605 be in the basic execution character set. None of these
606 characters can start a multibyte sequence, so they need
607 not be analyzed further. Some old compilers object to
608 `\a', so don't bother optimizing for it. */
613 /* Copy this multibyte sequence until we reach its end, find
614 an error, or come back to the initial shift state. */
616 mbstate_t mbstate
= mbstate_zero
;
621 size_t bytes
= mbrlen (f
+ len
, (size_t) -1, &mbstate
);
626 if (bytes
== (size_t) -2)
628 len
+= strlen (f
+ len
);
632 if (bytes
== (size_t) -1)
640 while (! mbsinit (&mbstate
));
648 #else /* ! DO_MULTIBYTE */
650 /* Either multibyte encodings are not supported, they are
651 safe for formats, so any non-'%' byte can be copied through,
652 or this is the wide character version. */
659 #endif /* ! DO_MULTIBYTE */
661 /* Check for flags that can modify a format. */
666 /* This influences the number formats. */
673 /* This changes textual output. */
687 /* As a GNU extension we allow to specify the field width. */
694 width
+= *f
- L_('0');
697 while (ISDIGIT (*f
));
700 /* Check for modifiers. */
713 /* Now do the specified format. */
717 #define DO_NUMBER(d, v) \
718 digits = width == -1 ? d : width; \
719 number_value = v; goto do_number
720 #define DO_NUMBER_SPACEPAD(d, v) \
721 digits = width == -1 ? d : width; \
722 number_value = v; goto do_number_spacepad
738 #if defined _NL_CURRENT || !HAVE_STRFTIME
739 cpy (aw_len
, a_wkday
);
742 goto underlying_strftime
;
753 #if defined _NL_CURRENT || !HAVE_STRFTIME
754 cpy (STRLEN (f_wkday
), f_wkday
);
757 goto underlying_strftime
;
761 case L_('h'): /* POSIX.2 extension. */
769 #if defined _NL_CURRENT || !HAVE_STRFTIME
770 cpy (am_len
, a_month
);
773 goto underlying_strftime
;
784 #if defined _NL_CURRENT || !HAVE_STRFTIME
785 cpy (STRLEN (f_month
), f_month
);
788 goto underlying_strftime
;
792 if (modifier
== L_('O'))
795 if (! (modifier
== 'E'
796 && (*(subfmt
= (CHAR_T
*) _NL_CURRENT (LC_TIME
,
799 subfmt
= (CHAR_T
*) _NL_CURRENT (LC_TIME
, NLW(D_T_FMT
));
802 goto underlying_strftime
;
804 subfmt
= L_("%a %b %e %H:%M:%S %Y");
810 CHAR_T
*old_start
= p
;
811 size_t len
= my_strftime (NULL
, (size_t) -1, subfmt
, tp
, 0);
812 add (len
, my_strftime (p
, maxsize
- i
, subfmt
, tp
, 0));
815 while (old_start
< p
)
817 *old_start
= TOUPPER ((UCHAR_T
) *old_start
);
823 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
826 /* The relevant information is available only via the
827 underlying strftime implementation, so use that. */
830 char ubuf
[1024]; /* enough for any single format in practice */
832 /* Make sure we're calling the actual underlying strftime.
833 In some cases, config.h contains something like
834 "#define strftime rpl_strftime". */
840 #ifdef STRFTIME_NO_POSIX2
841 /* Some system libraries do not support the POSIX.2 extensions.
842 In those cases, convert %h to %b, and strip modifiers. */
844 if (format_char
== 'h')
852 len
= strftime (ubuf
, sizeof ubuf
, ufmt
, tp
);
853 if (len
== 0 && ubuf
[0] != '\0')
860 case L_('C'): /* POSIX.2 extension. */
861 if (modifier
== L_('O'))
863 if (modifier
== L_('E'))
865 #if HAVE_STRUCT_ERA_ENTRY
866 struct era_entry
*era
= _nl_get_era_entry (tp
);
870 size_t len
= __wcslen (era
->era_wname
);
871 cpy (len
, era
->era_wname
);
873 size_t len
= strlen (era
->era_name
);
874 cpy (len
, era
->era_name
);
880 goto underlying_strftime
;
886 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
887 DO_NUMBER (1, year
/ 100 - (year
% 100 < 0));
891 if (modifier
== L_('O'))
894 if (! (modifier
== L_('E')
895 && (*(subfmt
= (CHAR_T
*)_NL_CURRENT (LC_TIME
,
898 subfmt
= (CHAR_T
*) _NL_CURRENT (LC_TIME
, NLW(D_FMT
));
902 goto underlying_strftime
;
907 case L_('D'): /* POSIX.2 extension. */
910 subfmt
= L_("%m/%d/%y");
914 if (modifier
== L_('E'))
917 DO_NUMBER (2, tp
->tm_mday
);
919 case L_('e'): /* POSIX.2 extension. */
920 if (modifier
== L_('E'))
923 DO_NUMBER_SPACEPAD (2, tp
->tm_mday
);
925 /* All numeric formats set DIGITS and NUMBER_VALUE and then
926 jump to one of these two labels. */
929 /* Force `_' flag unless overwritten by `0' flag. */
934 /* Format the number according to the MODIFIER flag. */
936 if (modifier
== L_('O') && 0 <= number_value
)
939 /* Get the locale specific alternate representation of
940 the number NUMBER_VALUE. If none exist NULL is returned. */
942 const wchar_t *cp
= _nl_get_walt_digit (number_value
);
944 const char *cp
= _nl_get_alt_digit (number_value
);
949 size_t digitlen
= STRLEN (cp
);
958 goto underlying_strftime
;
963 unsigned int u
= number_value
;
965 bufp
= buf
+ sizeof (buf
) / sizeof (buf
[0]);
966 negative_number
= number_value
< 0;
972 *--bufp
= u
% 10 + L_('0');
973 while ((u
/= 10) != 0);
976 do_number_sign_and_padding
:
982 int padding
= digits
- (buf
+ (sizeof (buf
) / sizeof (buf
[0]))
987 while (0 < padding
--)
992 bufp
+= negative_number
;
993 while (0 < padding
--)
1000 cpy (buf
+ sizeof (buf
) / sizeof (buf
[0]) - bufp
, bufp
);
1006 subfmt
= L_("%Y-%m-%d");
1010 if (modifier
== L_('E'))
1013 DO_NUMBER (2, tp
->tm_hour
);
1016 if (modifier
== L_('E'))
1019 DO_NUMBER (2, hour12
);
1021 case L_('k'): /* GNU extension. */
1022 if (modifier
== L_('E'))
1025 DO_NUMBER_SPACEPAD (2, tp
->tm_hour
);
1027 case L_('l'): /* GNU extension. */
1028 if (modifier
== L_('E'))
1031 DO_NUMBER_SPACEPAD (2, hour12
);
1034 if (modifier
== L_('E'))
1037 DO_NUMBER (3, 1 + tp
->tm_yday
);
1040 if (modifier
== L_('E'))
1043 DO_NUMBER (2, tp
->tm_min
);
1046 if (modifier
== L_('E'))
1049 DO_NUMBER (2, tp
->tm_mon
+ 1);
1051 case L_('n'): /* POSIX.2 extension. */
1052 add (1, *p
= L_('\n'));
1057 #if !defined _NL_CURRENT && HAVE_STRFTIME
1058 format_char
= L_('p');
1068 #if defined _NL_CURRENT || !HAVE_STRFTIME
1072 goto underlying_strftime
;
1075 case L_('R'): /* GNU extension. */
1076 subfmt
= L_("%H:%M");
1079 case L_('r'): /* POSIX.2 extension. */
1081 if (*(subfmt
= (CHAR_T
*) _NL_CURRENT (LC_TIME
,
1082 NLW(T_FMT_AMPM
))) == L_('\0'))
1084 subfmt
= L_("%I:%M:%S %p");
1088 if (modifier
== L_('E'))
1091 DO_NUMBER (2, tp
->tm_sec
);
1093 case L_('s'): /* GNU extension. */
1101 /* Generate string value for T using time_t arithmetic;
1102 this works even if sizeof (long) < sizeof (time_t). */
1104 bufp
= buf
+ sizeof (buf
) / sizeof (buf
[0]);
1105 negative_number
= t
< 0;
1112 if (negative_number
)
1116 /* Adjust if division truncates to minus infinity. */
1117 if (0 < -1 % 10 && d
< 0)
1124 *--bufp
= d
+ L_('0');
1129 goto do_number_sign_and_padding
;
1133 if (modifier
== L_('O'))
1136 if (! (modifier
== L_('E')
1137 && (*(subfmt
= (CHAR_T
*) _NL_CURRENT (LC_TIME
,
1140 subfmt
= (CHAR_T
*) _NL_CURRENT (LC_TIME
, NLW(T_FMT
));
1144 goto underlying_strftime
;
1149 case L_('T'): /* POSIX.2 extension. */
1150 subfmt
= L_("%H:%M:%S");
1153 case L_('t'): /* POSIX.2 extension. */
1154 add (1, *p
= L_('\t'));
1157 case L_('u'): /* POSIX.2 extension. */
1158 DO_NUMBER (1, (tp
->tm_wday
- 1 + 7) % 7 + 1);
1161 if (modifier
== L_('E'))
1164 DO_NUMBER (2, (tp
->tm_yday
- tp
->tm_wday
+ 7) / 7);
1167 case L_('g'): /* GNU extension. */
1168 case L_('G'): /* GNU extension. */
1169 if (modifier
== L_('E'))
1172 int year
= tp
->tm_year
+ TM_YEAR_BASE
;
1173 int days
= iso_week_days (tp
->tm_yday
, tp
->tm_wday
);
1177 /* This ISO week belongs to the previous year. */
1179 days
= iso_week_days (tp
->tm_yday
+ (365 + __isleap (year
)),
1184 int d
= iso_week_days (tp
->tm_yday
- (365 + __isleap (year
)),
1188 /* This ISO week belongs to the next year. */
1197 DO_NUMBER (2, (year
% 100 + 100) % 100);
1200 DO_NUMBER (1, year
);
1203 DO_NUMBER (2, days
/ 7 + 1);
1208 if (modifier
== L_('E'))
1211 DO_NUMBER (2, (tp
->tm_yday
- (tp
->tm_wday
- 1 + 7) % 7 + 7) / 7);
1214 if (modifier
== L_('E'))
1217 DO_NUMBER (1, tp
->tm_wday
);
1220 if (modifier
== 'E')
1222 #if HAVE_STRUCT_ERA_ENTRY
1223 struct era_entry
*era
= _nl_get_era_entry (tp
);
1226 # ifdef COMPILE_WIDE
1227 subfmt
= era
->era_wformat
;
1229 subfmt
= era
->era_format
;
1235 goto underlying_strftime
;
1239 if (modifier
== L_('O'))
1242 DO_NUMBER (1, tp
->tm_year
+ TM_YEAR_BASE
);
1245 if (modifier
== L_('E'))
1247 #if HAVE_STRUCT_ERA_ENTRY
1248 struct era_entry
*era
= _nl_get_era_entry (tp
);
1251 int delta
= tp
->tm_year
- era
->start_date
[0];
1252 DO_NUMBER (1, (era
->offset
1253 + delta
* era
->absolute_direction
));
1257 goto underlying_strftime
;
1261 DO_NUMBER (2, (tp
->tm_year
% 100 + 100) % 100);
1271 /* The tzset() call might have changed the value. */
1272 if (!(zone
&& *zone
) && tp
->tm_isdst
>= 0)
1273 zone
= tzname
[tp
->tm_isdst
];
1276 zone
= ""; /* POSIX.2 requires the empty string here. */
1280 /* The zone string is always given in multibyte form. We have
1281 to transform it first. */
1284 widen (zone
, wczone
, len
);
1288 cpy (strlen (zone
), zone
);
1292 case L_('z'): /* GNU extension. */
1293 if (tp
->tm_isdst
< 0)
1299 diff
= tp
->tm_gmtoff
;
1312 if (lt
== (time_t) -1)
1314 /* mktime returns -1 for errors, but -1 is also a
1315 valid time_t value. Check whether an error really
1319 if (! my_strftime_localtime_r (<
, &tm
)
1320 || ((ltm
.tm_sec
^ tm
.tm_sec
)
1321 | (ltm
.tm_min
^ tm
.tm_min
)
1322 | (ltm
.tm_hour
^ tm
.tm_hour
)
1323 | (ltm
.tm_mday
^ tm
.tm_mday
)
1324 | (ltm
.tm_mon
^ tm
.tm_mon
)
1325 | (ltm
.tm_year
^ tm
.tm_year
)))
1329 if (! my_strftime_gmtime_r (<
, >m
))
1332 diff
= tm_diff (<m
, >m
);
1338 add (1, *p
= L_('-'));
1342 add (1, *p
= L_('+'));
1345 DO_NUMBER (4, (diff
/ 60) * 100 + diff
% 60);
1348 case L_('\0'): /* GNU extension: % at end of format. */
1352 /* Unknown format; output the format, including the '%',
1353 since this is most likely the right thing to do if a
1354 multibyte string has been misparsed. */
1358 for (flen
= 1; f
[1 - flen
] != L_('%'); flen
++)
1360 cpy (flen
, &f
[1 - flen
]);
1366 if (p
&& maxsize
!= 0)
1373 /* For Emacs we have a separate interface which corresponds to the normal
1374 strftime function and does not have the extra information whether the
1375 TP arguments comes from a `gmtime' call or not. */
1377 emacs_strftime (s
, maxsize
, format
, tp
)
1381 const struct tm
*tp
;
1383 return my_strftime (s
, maxsize
, format
, tp
, 0);