]> git.ipfire.org Git - thirdparty/glibc.git/blob - time/strftime.c
Update.
[thirdparty/glibc.git] / time / strftime.c
1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
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.
8
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.
13
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. */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #ifdef _LIBC
24 # define HAVE_LIMITS_H 1
25 # define HAVE_MBLEN 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
31 # define HAVE_TZSET 1
32 # define MULTIBYTE_IS_FORMAT_SAFE 1
33 # define STDC_HEADERS 1
34 # include "../locale/localeinfo.h"
35 #endif
36
37 #if defined emacs && !defined HAVE_BCOPY
38 # define HAVE_MEMCPY 1
39 #endif
40
41 #include <ctype.h>
42 #include <sys/types.h> /* Some systems define `time_t' here. */
43
44 #ifdef TIME_WITH_SYS_TIME
45 # include <sys/time.h>
46 # include <time.h>
47 #else
48 # ifdef HAVE_SYS_TIME_H
49 # include <sys/time.h>
50 # else
51 # include <time.h>
52 # endif
53 #endif
54 #if HAVE_TZNAME
55 extern char *tzname[];
56 #endif
57
58 /* Do multibyte processing if multibytes are supported, unless
59 multibyte sequences are safe in formats. Multibyte sequences are
60 safe if they cannot contain byte sequences that look like format
61 conversion specifications. The GNU C Library uses UTF8 multibyte
62 encoding, which is safe for formats, but strftime.c can be used
63 with other C libraries that use unsafe encodings. */
64 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
65
66 #if DO_MULTIBYTE
67 # if HAVE_MBRLEN
68 # include <wchar.h>
69 # else
70 /* Simulate mbrlen with mblen as best we can. */
71 # define mbstate_t int
72 # define mbrlen(s, n, ps) mblen (s, n)
73 # define mbsinit(ps) (*(ps) == 0)
74 # endif
75 static const mbstate_t mbstate_zero;
76 #endif
77
78 #if HAVE_LIMITS_H
79 # include <limits.h>
80 #endif
81
82 #if STDC_HEADERS
83 # include <stddef.h>
84 # include <stdlib.h>
85 # include <string.h>
86 #endif
87
88 #ifdef COMPILE_WIDE
89 # include <endian.h>
90 # define CHAR_T wchar_t
91 # define UCHAR_T unsigned int
92 # define L_(Str) L##Str
93 # define NLW(Sym) _NL_W##Sym
94
95 # define MEMCPY(d, s, n) wmemcpy (d, s, n)
96 # define STRLEN(s) wcslen (s)
97
98 #else
99 # define CHAR_T char
100 # define UCHAR_T unsigned char
101 # define L_(Str) Str
102 # define NLW(Sym) Sym
103
104 # if !defined STDC_HEADERS && !defined HAVE_MEMCPY
105 # define MEMCPY(d, s, n) bcopy ((s), (d), (n))
106 # else
107 # define MEMCPY(d, s, n) memcpy ((d), (s), (n))
108 # endif
109 # define STRLEN(s) strlen (s)
110
111 # ifdef _LIBC
112 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
113 # else
114 # ifndef HAVE_MEMPCPY
115 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
116 # endif
117 # endif
118 #endif
119
120 #ifndef __P
121 # if defined __GNUC__ || (defined __STDC__ && __STDC__)
122 # define __P(args) args
123 # else
124 # define __P(args) ()
125 # endif /* GCC. */
126 #endif /* Not __P. */
127
128 #ifndef PTR
129 # ifdef __STDC__
130 # define PTR void *
131 # else
132 # define PTR char *
133 # endif
134 #endif
135
136 #ifndef CHAR_BIT
137 # define CHAR_BIT 8
138 #endif
139
140 #ifndef NULL
141 # define NULL 0
142 #endif
143
144 #define TYPE_SIGNED(t) ((t) -1 < 0)
145
146 /* Bound on length of the string representing an integer value of type t.
147 Subtract one for the sign bit if t is signed;
148 302 / 1000 is log10 (2) rounded up;
149 add one for integer division truncation;
150 add one more for a minus sign if t is signed. */
151 #define INT_STRLEN_BOUND(t) \
152 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
153
154 #define TM_YEAR_BASE 1900
155
156 #ifndef __isleap
157 /* Nonzero if YEAR is a leap year (every 4 years,
158 except every 100th isn't, and every 400th is). */
159 # define __isleap(year) \
160 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
161 #endif
162
163
164 #ifdef _LIBC
165 # define my_strftime_gmtime_r __gmtime_r
166 # define my_strftime_localtime_r __localtime_r
167 # define tzname __tzname
168 # define tzset __tzset
169 #else
170
171 /* If we're a strftime substitute in a GNU program, then prefer gmtime
172 to gmtime_r, since many gmtime_r implementations are buggy.
173 Similarly for localtime_r. */
174
175 # if ! HAVE_TM_GMTOFF
176 static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
177 static struct tm *
178 my_strftime_gmtime_r (t, tp)
179 const time_t *t;
180 struct tm *tp;
181 {
182 struct tm *l = gmtime (t);
183 if (! l)
184 return 0;
185 *tp = *l;
186 return tp;
187 }
188 # endif /* ! HAVE_TM_GMTOFF */
189
190 static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
191 static struct tm *
192 my_strftime_localtime_r (t, tp)
193 const time_t *t;
194 struct tm *tp;
195 {
196 struct tm *l = localtime (t);
197 if (! l)
198 return 0;
199 *tp = *l;
200 return tp;
201 }
202 #endif /* ! defined _LIBC */
203
204
205 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
206 /* Some systems lack the `memset' function and we don't want to
207 introduce additional dependencies. */
208 /* The SGI compiler reportedly barfs on the trailing null
209 if we use a string constant as the initializer. 28 June 1997, rms. */
210 static const CHAR_T spaces[16] = /* " " */
211 {
212 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
213 L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
214 };
215 static const CHAR_T zeroes[16] = /* "0000000000000000" */
216 {
217 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
218 L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
219 };
220
221 # define memset_space(P, Len) \
222 do { \
223 int _len = (Len); \
224 \
225 do \
226 { \
227 int _this = _len > 16 ? 16 : _len; \
228 (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
229 _len -= _this; \
230 } \
231 while (_len > 0); \
232 } while (0)
233
234 # define memset_zero(P, Len) \
235 do { \
236 int _len = (Len); \
237 \
238 do \
239 { \
240 int _this = _len > 16 ? 16 : _len; \
241 (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
242 _len -= _this; \
243 } \
244 while (_len > 0); \
245 } while (0)
246 #else
247 # ifdef COMPILE_WIDE
248 # define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
249 # define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
250 # else
251 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
252 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
253 # endif
254 #endif
255
256 #define add(n, f) \
257 do \
258 { \
259 int _n = (n); \
260 int _delta = width - _n; \
261 int _incr = _n + (_delta > 0 ? _delta : 0); \
262 if (i + _incr >= maxsize) \
263 return 0; \
264 if (p) \
265 { \
266 if (_delta > 0) \
267 { \
268 if (pad == L_('0')) \
269 memset_zero (p, _delta); \
270 else \
271 memset_space (p, _delta); \
272 } \
273 f; \
274 p += _n; \
275 } \
276 i += _incr; \
277 } while (0)
278
279 #define cpy(n, s) \
280 add ((n), \
281 if (to_lowcase) \
282 memcpy_lowcase (p, (s), _n); \
283 else if (to_uppcase) \
284 memcpy_uppcase (p, (s), _n); \
285 else \
286 MEMCPY ((PTR) p, (PTR) (s), _n))
287
288 #ifdef COMPILE_WIDE
289 # define widen(os, ws, l) \
290 { \
291 mbstate_t __st; \
292 const char *__s = os; \
293 memset (&__st, '\0', sizeof (__st)); \
294 l = __mbsrtowcs (NULL, &__s, 0, &__st); \
295 ws = alloca ((l + 1) * sizeof (wchar_t)); \
296 (void) __mbsrtowcs (ws, &__s, l, &__st); \
297 }
298 #endif
299
300
301 #ifdef COMPILE_WIDE
302 # define TOUPPER(Ch) towupper (Ch)
303 # define TOLOWER(Ch) towlower (Ch)
304 #else
305 # ifdef _LIBC
306 # define TOUPPER(Ch) toupper (Ch)
307 # define TOLOWER(Ch) tolower (Ch)
308 # else
309 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
310 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
311 # endif
312 #endif
313 /* We don't use `isdigit' here since the locale dependent
314 interpretation is not what we want here. We only need to accept
315 the arabic digits in the ASCII range. One day there is perhaps a
316 more reliable way to accept other sets of digits. */
317 #define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
318
319 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
320 size_t len));
321
322 static CHAR_T *
323 memcpy_lowcase (dest, src, len)
324 CHAR_T *dest;
325 const CHAR_T *src;
326 size_t len;
327 {
328 while (len-- > 0)
329 dest[len] = TOLOWER ((UCHAR_T) src[len]);
330 return dest;
331 }
332
333 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
334 size_t len));
335
336 static CHAR_T *
337 memcpy_uppcase (dest, src, len)
338 CHAR_T *dest;
339 const CHAR_T *src;
340 size_t len;
341 {
342 while (len-- > 0)
343 dest[len] = TOUPPER ((UCHAR_T) src[len]);
344 return dest;
345 }
346
347
348 #if ! HAVE_TM_GMTOFF
349 /* Yield the difference between *A and *B,
350 measured in seconds, ignoring leap seconds. */
351 # define tm_diff ftime_tm_diff
352 static int tm_diff __P ((const struct tm *, const struct tm *));
353 static int
354 tm_diff (a, b)
355 const struct tm *a;
356 const struct tm *b;
357 {
358 /* Compute intervening leap days correctly even if year is negative.
359 Take care to avoid int overflow in leap day calculations,
360 but it's OK to assume that A and B are close to each other. */
361 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
362 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
363 int a100 = a4 / 25 - (a4 % 25 < 0);
364 int b100 = b4 / 25 - (b4 % 25 < 0);
365 int a400 = a100 >> 2;
366 int b400 = b100 >> 2;
367 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
368 int years = a->tm_year - b->tm_year;
369 int days = (365 * years + intervening_leap_days
370 + (a->tm_yday - b->tm_yday));
371 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
372 + (a->tm_min - b->tm_min))
373 + (a->tm_sec - b->tm_sec));
374 }
375 #endif /* ! HAVE_TM_GMTOFF */
376
377
378
379 /* The number of days from the first day of the first ISO week of this
380 year to the year day YDAY with week day WDAY. ISO weeks start on
381 Monday; the first ISO week has the year's first Thursday. YDAY may
382 be as small as YDAY_MINIMUM. */
383 #define ISO_WEEK_START_WDAY 1 /* Monday */
384 #define ISO_WEEK1_WDAY 4 /* Thursday */
385 #define YDAY_MINIMUM (-366)
386 static int iso_week_days __P ((int, int));
387 #ifdef __GNUC__
388 __inline__
389 #endif
390 static int
391 iso_week_days (yday, wday)
392 int yday;
393 int wday;
394 {
395 /* Add enough to the first operand of % to make it nonnegative. */
396 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
397 return (yday
398 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
399 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
400 }
401
402
403 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
404 static CHAR_T const weekday_name[][10] =
405 {
406 L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
407 L_("Thursday"), L_("Friday"), L_("Saturday")
408 };
409 static CHAR_T const month_name[][10] =
410 {
411 L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
412 L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
413 L_("November"), L_("December")
414 };
415 #endif
416
417
418 #ifdef emacs
419 # define my_strftime emacs_strftimeu
420 # define ut_argument , ut
421 # define ut_argument_spec int ut;
422 # define ut_argument_spec_iso , int ut
423 #else
424 # ifdef COMPILE_WIDE
425 # define my_strftime wcsftime
426 # else
427 # define my_strftime strftime
428 # endif
429 # define ut_argument
430 # define ut_argument_spec
431 # define ut_argument_spec_iso
432 /* We don't have this information in general. */
433 # define ut 0
434 #endif
435
436 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
437 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
438 Work around this bug by copying *tp before it might be munged. */
439 size_t _strftime_copytm __P ((char *, size_t, const char *,
440 const struct tm * ut_argument_spec_iso));
441 size_t
442 my_strftime (s, maxsize, format, tp ut_argument)
443 CHAR_T *s;
444 size_t maxsize;
445 const CHAR_T *format;
446 const struct tm *tp;
447 ut_argument_spec
448 {
449 struct tm tmcopy;
450 tmcopy = *tp;
451 return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
452 }
453 # undef my_strftime
454 # define my_strftime(S, Maxsize, Format, Tp) \
455 _strftime_copytm (S, Maxsize, Format, Tp)
456 #endif
457
458
459 /* Write information from TP into S according to the format
460 string FORMAT, writing no more that MAXSIZE characters
461 (including the terminating '\0') and returning number of
462 characters written. If S is NULL, nothing will be written
463 anywhere, so to determine how many characters would be
464 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
465 size_t
466 my_strftime (s, maxsize, format, tp ut_argument)
467 CHAR_T *s;
468 size_t maxsize;
469 const CHAR_T *format;
470 const struct tm *tp;
471 ut_argument_spec
472 {
473 int hour12 = tp->tm_hour;
474 #ifdef _NL_CURRENT
475 /* We cannot make the following values variables since we must delay
476 the evaluation of these values until really needed since some
477 expressions might not be valid in every situation. The `struct tm'
478 might be generated by a strptime() call that initialized
479 only a few elements. Dereference the pointers only if the format
480 requires this. Then it is ok to fail if the pointers are invalid. */
481 # define a_wkday \
482 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
483 # define f_wkday \
484 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
485 # define a_month \
486 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
487 # define f_month \
488 ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
489 # define ampm \
490 ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
491 ? NLW(PM_STR) : NLW(AM_STR)))
492
493 # define aw_len STRLEN (a_wkday)
494 # define am_len STRLEN (a_month)
495 # define ap_len STRLEN (ampm)
496 #else
497 # if !HAVE_STRFTIME
498 # define f_wkday (weekday_name[tp->tm_wday])
499 # define f_month (month_name[tp->tm_mon])
500 # define a_wkday f_wkday
501 # define a_month f_month
502 # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
503
504 size_t aw_len = 3;
505 size_t am_len = 3;
506 size_t ap_len = 2;
507 # endif
508 #endif
509 const char *zone;
510 size_t i = 0;
511 CHAR_T *p = s;
512 const CHAR_T *f;
513
514 zone = NULL;
515 #if HAVE_TM_ZONE
516 /* The POSIX test suite assumes that setting
517 the environment variable TZ to a new value before calling strftime()
518 will influence the result (the %Z format) even if the information in
519 TP is computed with a totally different time zone.
520 This is bogus: though POSIX allows bad behavior like this,
521 POSIX does not require it. Do the right thing instead. */
522 zone = (const char *) tp->tm_zone;
523 #endif
524 #if HAVE_TZNAME
525 if (ut)
526 {
527 if (! (zone && *zone))
528 zone = "GMT";
529 }
530 else
531 {
532 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
533 time zone names contained in the external variable `tzname' shall
534 be set as if the tzset() function had been called. */
535 # if HAVE_TZSET
536 tzset ();
537 # endif
538 }
539 #endif
540
541 if (hour12 > 12)
542 hour12 -= 12;
543 else
544 if (hour12 == 0)
545 hour12 = 12;
546
547 for (f = format; *f != '\0'; ++f)
548 {
549 int pad = 0; /* Padding for number ('-', '_', or 0). */
550 int modifier; /* Field modifier ('E', 'O', or 0). */
551 int digits; /* Max digits for numeric format. */
552 int number_value; /* Numeric value to be printed. */
553 int negative_number; /* 1 if the number is negative. */
554 const CHAR_T *subfmt;
555 CHAR_T *bufp;
556 CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
557 ? INT_STRLEN_BOUND (time_t)
558 : INT_STRLEN_BOUND (int))];
559 int width = -1;
560 int to_lowcase = 0;
561 int to_uppcase = 0;
562 int change_case = 0;
563 int format_char;
564
565 #if DO_MULTIBYTE && !defined COMPILE_WIDE
566 switch (*f)
567 {
568 case L_('%'):
569 break;
570
571 case L_('\a'): case L_('\b'): case L_('\t'): case L_('\n'):
572 case L_('\v'): case L_('\f'): case L_('\r'):
573 case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
574 case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
575 case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
576 case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
577 case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
578 case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
579 case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
580 case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
581 case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
582 case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
583 case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
584 case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
585 case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
586 case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
587 case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
588 case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
589 case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
590 case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
591 case L_('~'):
592 /* The C Standard requires these 98 characters (plus '%') to
593 be in the basic execution character set. None of these
594 characters can start a multibyte sequence, so they need
595 not be analyzed further. */
596 add (1, *p = *f);
597 continue;
598
599 default:
600 /* Copy this multibyte sequence until we reach its end, find
601 an error, or come back to the initial shift state. */
602 {
603 mbstate_t mbstate = mbstate_zero;
604 size_t len = 0;
605
606 do
607 {
608 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
609
610 if (bytes == 0)
611 break;
612
613 if (bytes == (size_t) -2)
614 {
615 len += strlen (f + len);
616 break;
617 }
618
619 if (bytes == (size_t) -1)
620 {
621 len++;
622 break;
623 }
624
625 len += bytes;
626 }
627 while (! mbsinit (&mbstate));
628
629 cpy (len, f);
630 f += len - 1;
631 continue;
632 }
633 }
634
635 #else /* ! DO_MULTIBYTE */
636
637 /* Either multibyte encodings are not supported, they are
638 safe for formats, so any non-'%' byte can be copied through,
639 or this is the wide character version. */
640 if (*f != L_('%'))
641 {
642 add (1, *p = *f);
643 continue;
644 }
645
646 #endif /* ! DO_MULTIBYTE */
647
648 /* Check for flags that can modify a format. */
649 while (1)
650 {
651 switch (*++f)
652 {
653 /* This influences the number formats. */
654 case L_('_'):
655 case L_('-'):
656 case L_('0'):
657 pad = *f;
658 continue;
659
660 /* This changes textual output. */
661 case L_('^'):
662 to_uppcase = 1;
663 continue;
664 case L_('#'):
665 change_case = 1;
666 continue;
667
668 default:
669 break;
670 }
671 break;
672 }
673
674 /* As a GNU extension we allow to specify the field width. */
675 if (ISDIGIT (*f))
676 {
677 width = 0;
678 do
679 {
680 width *= 10;
681 width += *f - L_('0');
682 ++f;
683 }
684 while (ISDIGIT (*f));
685 }
686
687 /* Check for modifiers. */
688 switch (*f)
689 {
690 case L_('E'):
691 case L_('O'):
692 modifier = *f++;
693 break;
694
695 default:
696 modifier = 0;
697 break;
698 }
699
700 /* Now do the specified format. */
701 format_char = *f;
702 switch (format_char)
703 {
704 #define DO_NUMBER(d, v) \
705 digits = width == -1 ? d : width; \
706 number_value = v; goto do_number
707 #define DO_NUMBER_SPACEPAD(d, v) \
708 digits = width == -1 ? d : width; \
709 number_value = v; goto do_number_spacepad
710
711 case L_('%'):
712 if (modifier != 0)
713 goto bad_format;
714 add (1, *p = *f);
715 break;
716
717 case L_('a'):
718 if (modifier != 0)
719 goto bad_format;
720 if (change_case)
721 {
722 to_uppcase = 1;
723 to_lowcase = 0;
724 }
725 #if defined _NL_CURRENT || !HAVE_STRFTIME
726 cpy (aw_len, a_wkday);
727 break;
728 #else
729 goto underlying_strftime;
730 #endif
731
732 case 'A':
733 if (modifier != 0)
734 goto bad_format;
735 if (change_case)
736 {
737 to_uppcase = 1;
738 to_lowcase = 0;
739 }
740 #if defined _NL_CURRENT || !HAVE_STRFTIME
741 cpy (STRLEN (f_wkday), f_wkday);
742 break;
743 #else
744 goto underlying_strftime;
745 #endif
746
747 case L_('b'):
748 case L_('h'): /* POSIX.2 extension. */
749 if (modifier != 0)
750 goto bad_format;
751 #if defined _NL_CURRENT || !HAVE_STRFTIME
752 cpy (am_len, a_month);
753 break;
754 #else
755 goto underlying_strftime;
756 #endif
757
758 case L_('B'):
759 if (modifier != 0)
760 goto bad_format;
761 if (change_case)
762 {
763 to_uppcase = 1;
764 to_lowcase = 0;
765 }
766 #if defined _NL_CURRENT || !HAVE_STRFTIME
767 cpy (STRLEN (f_month), f_month);
768 break;
769 #else
770 goto underlying_strftime;
771 #endif
772
773 case L_('c'):
774 if (modifier == L_('O'))
775 goto bad_format;
776 #ifdef _NL_CURRENT
777 if (! (modifier == 'E'
778 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
779 NLW(ERA_D_T_FMT)))
780 != '\0')))
781 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
782 #else
783 # if HAVE_STRFTIME
784 goto underlying_strftime;
785 # else
786 subfmt = L_("%a %b %e %H:%M:%S %Y");
787 # endif
788 #endif
789
790 subformat:
791 {
792 CHAR_T *old_start = p;
793 size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp);
794 add (len, my_strftime (p, maxsize - i, subfmt, tp));
795
796 if (to_uppcase)
797 while (old_start < p)
798 {
799 *old_start = TOUPPER ((UCHAR_T) *old_start);
800 ++old_start;
801 }
802 }
803 break;
804
805 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
806 underlying_strftime:
807 {
808 /* The relevant information is available only via the
809 underlying strftime implementation, so use that. */
810 char ufmt[4];
811 char *u = ufmt;
812 char ubuf[1024]; /* enough for any single format in practice */
813 size_t len;
814 *u++ = '%';
815 if (modifier != 0)
816 *u++ = modifier;
817 *u++ = format_char;
818 *u = '\0';
819 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
820 if (len == 0 && ubuf[0] != '\0')
821 return 0;
822 cpy (len, ubuf);
823 }
824 break;
825 #endif
826
827 case L_('C'): /* POSIX.2 extension. */
828 if (modifier == L_('O'))
829 goto bad_format;
830 if (modifier == L_('E'))
831 {
832 #if HAVE_STRUCT_ERA_ENTRY
833 struct era_entry *era = _nl_get_era_entry (tp);
834 if (era)
835 {
836 # ifdef COMPILE_WIDE
837 /* The wide name is after the single byte name and
838 format. */
839 char *tcp = strchr (era->name_fmt, '\0') + 1;
840 wchar_t *ws = (wchar_t *) (strchr (tcp, '\0') + 1);
841 size_t len = wcslen (ws);
842 cpy (len, ws);
843 # else
844 size_t len = strlen (era->name_fmt);
845 cpy (len, era->name_fmt);
846 # endif
847 break;
848 }
849 #else
850 # if HAVE_STRFTIME
851 goto underlying_strftime;
852 # endif
853 #endif
854 }
855
856 {
857 int year = tp->tm_year + TM_YEAR_BASE;
858 DO_NUMBER (1, year / 100 - (year % 100 < 0));
859 }
860
861 case L_('x'):
862 if (modifier == L_('O'))
863 goto bad_format;
864 #ifdef _NL_CURRENT
865 if (! (modifier == L_('E')
866 && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
867 NLW(ERA_D_FMT)))
868 != L_('\0'))))
869 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
870 goto subformat;
871 #else
872 # if HAVE_STRFTIME
873 goto underlying_strftime;
874 # else
875 /* Fall through. */
876 # endif
877 #endif
878 case L_('D'): /* POSIX.2 extension. */
879 if (modifier != 0)
880 goto bad_format;
881 subfmt = L_("%m/%d/%y");
882 goto subformat;
883
884 case L_('d'):
885 if (modifier == L_('E'))
886 goto bad_format;
887
888 DO_NUMBER (2, tp->tm_mday);
889
890 case L_('e'): /* POSIX.2 extension. */
891 if (modifier == L_('E'))
892 goto bad_format;
893
894 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
895
896 /* All numeric formats set DIGITS and NUMBER_VALUE and then
897 jump to one of these two labels. */
898
899 do_number_spacepad:
900 /* Force `_' flag unless overwritten by `0' flag. */
901 if (pad != L_('0'))
902 pad = L_('_');
903
904 do_number:
905 /* Format the number according to the MODIFIER flag. */
906
907 if (modifier == L_('O') && 0 <= number_value)
908 {
909 #ifdef _NL_CURRENT
910 /* Get the locale specific alternate representation of
911 the number NUMBER_VALUE. If none exist NULL is returned. */
912 # ifdef COMPILE_WIDE
913 const wchar_t *cp = _nl_get_walt_digit (number_value);
914 # else
915 const char *cp = _nl_get_alt_digit (number_value);
916 # endif
917
918 if (cp != NULL)
919 {
920 size_t digitlen = STRLEN (cp);
921 if (digitlen != 0)
922 {
923 cpy (digitlen, cp);
924 break;
925 }
926 }
927 #else
928 # if HAVE_STRFTIME
929 goto underlying_strftime;
930 # endif
931 #endif
932 }
933 {
934 unsigned int u = number_value;
935
936 bufp = buf + sizeof (buf) / sizeof (buf[0]);
937 negative_number = number_value < 0;
938
939 if (negative_number)
940 u = -u;
941
942 do
943 *--bufp = u % 10 + L_('0');
944 while ((u /= 10) != 0);
945 }
946
947 do_number_sign_and_padding:
948 if (negative_number)
949 *--bufp = L_('-');
950
951 if (pad != L_('-'))
952 {
953 int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
954 - bufp);
955
956 if (pad == L_('_'))
957 {
958 while (0 < padding--)
959 *--bufp = L_(' ');
960 }
961 else
962 {
963 bufp += negative_number;
964 while (0 < padding--)
965 *--bufp = L_('0');
966 if (negative_number)
967 *--bufp = L_('-');
968 }
969 }
970
971 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
972 break;
973
974 case L_('F'):
975 if (modifier != 0)
976 goto bad_format;
977 subfmt = L_("%Y-%m-%d");
978 goto subformat;
979
980 case L_('H'):
981 if (modifier == L_('E'))
982 goto bad_format;
983
984 DO_NUMBER (2, tp->tm_hour);
985
986 case L_('I'):
987 if (modifier == L_('E'))
988 goto bad_format;
989
990 DO_NUMBER (2, hour12);
991
992 case L_('k'): /* GNU extension. */
993 if (modifier == L_('E'))
994 goto bad_format;
995
996 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
997
998 case L_('l'): /* GNU extension. */
999 if (modifier == L_('E'))
1000 goto bad_format;
1001
1002 DO_NUMBER_SPACEPAD (2, hour12);
1003
1004 case L_('j'):
1005 if (modifier == L_('E'))
1006 goto bad_format;
1007
1008 DO_NUMBER (3, 1 + tp->tm_yday);
1009
1010 case L_('M'):
1011 if (modifier == L_('E'))
1012 goto bad_format;
1013
1014 DO_NUMBER (2, tp->tm_min);
1015
1016 case L_('m'):
1017 if (modifier == L_('E'))
1018 goto bad_format;
1019
1020 DO_NUMBER (2, tp->tm_mon + 1);
1021
1022 case L_('n'): /* POSIX.2 extension. */
1023 add (1, *p = L_('\n'));
1024 break;
1025
1026 case L_('P'):
1027 to_lowcase = 1;
1028 #if !defined _NL_CURRENT && HAVE_STRFTIME
1029 format_char = L_('p');
1030 #endif
1031 /* FALLTHROUGH */
1032
1033 case L_('p'):
1034 if (change_case)
1035 {
1036 to_uppcase = 0;
1037 to_lowcase = 1;
1038 }
1039 #if defined _NL_CURRENT || !HAVE_STRFTIME
1040 cpy (ap_len, ampm);
1041 break;
1042 #else
1043 goto underlying_strftime;
1044 #endif
1045
1046 case L_('R'): /* GNU extension. */
1047 subfmt = L_("%H:%M");
1048 goto subformat;
1049
1050 case L_('r'): /* POSIX.2 extension. */
1051 #ifdef _NL_CURRENT
1052 if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1053 NLW(T_FMT_AMPM))) == L_('\0'))
1054 #endif
1055 subfmt = L_("%I:%M:%S %p");
1056 goto subformat;
1057
1058 case L_('S'):
1059 if (modifier == L_('E'))
1060 goto bad_format;
1061
1062 DO_NUMBER (2, tp->tm_sec);
1063
1064 case L_('s'): /* GNU extension. */
1065 {
1066 struct tm ltm;
1067 time_t t;
1068
1069 ltm = *tp;
1070 t = mktime (&ltm);
1071
1072 /* Generate string value for T using time_t arithmetic;
1073 this works even if sizeof (long) < sizeof (time_t). */
1074
1075 bufp = buf + sizeof (buf) / sizeof (buf[0]);
1076 negative_number = t < 0;
1077
1078 do
1079 {
1080 int d = t % 10;
1081 t /= 10;
1082
1083 if (negative_number)
1084 {
1085 d = -d;
1086
1087 /* Adjust if division truncates to minus infinity. */
1088 if (0 < -1 % 10 && d < 0)
1089 {
1090 t++;
1091 d += 10;
1092 }
1093 }
1094
1095 *--bufp = d + L_('0');
1096 }
1097 while (t != 0);
1098
1099 digits = 1;
1100 goto do_number_sign_and_padding;
1101 }
1102
1103 case L_('X'):
1104 if (modifier == L_('O'))
1105 goto bad_format;
1106 #ifdef _NL_CURRENT
1107 if (! (modifier == L_('E')
1108 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
1109 NLW(ERA_T_FMT)))
1110 != L_('\0'))))
1111 subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1112 goto subformat;
1113 #else
1114 # if HAVE_STRFTIME
1115 goto underlying_strftime;
1116 # else
1117 /* Fall through. */
1118 # endif
1119 #endif
1120 case L_('T'): /* POSIX.2 extension. */
1121 subfmt = L_("%H:%M:%S");
1122 goto subformat;
1123
1124 case L_('t'): /* POSIX.2 extension. */
1125 add (1, *p = L_('\t'));
1126 break;
1127
1128 case L_('u'): /* POSIX.2 extension. */
1129 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1130
1131 case L_('U'):
1132 if (modifier == L_('E'))
1133 goto bad_format;
1134
1135 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1136
1137 case L_('V'):
1138 case L_('g'): /* GNU extension. */
1139 case L_('G'): /* GNU extension. */
1140 if (modifier == L_('E'))
1141 goto bad_format;
1142 {
1143 int year = tp->tm_year + TM_YEAR_BASE;
1144 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1145
1146 if (days < 0)
1147 {
1148 /* This ISO week belongs to the previous year. */
1149 year--;
1150 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1151 tp->tm_wday);
1152 }
1153 else
1154 {
1155 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1156 tp->tm_wday);
1157 if (0 <= d)
1158 {
1159 /* This ISO week belongs to the next year. */
1160 year++;
1161 days = d;
1162 }
1163 }
1164
1165 switch (*f)
1166 {
1167 case L_('g'):
1168 DO_NUMBER (2, (year % 100 + 100) % 100);
1169
1170 case L_('G'):
1171 DO_NUMBER (1, year);
1172
1173 default:
1174 DO_NUMBER (2, days / 7 + 1);
1175 }
1176 }
1177
1178 case L_('W'):
1179 if (modifier == L_('E'))
1180 goto bad_format;
1181
1182 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1183
1184 case L_('w'):
1185 if (modifier == L_('E'))
1186 goto bad_format;
1187
1188 DO_NUMBER (1, tp->tm_wday);
1189
1190 case L_('Y'):
1191 if (modifier == 'E')
1192 {
1193 #if HAVE_STRUCT_ERA_ENTRY
1194 struct era_entry *era = _nl_get_era_entry (tp);
1195 if (era)
1196 {
1197 # ifdef COMPILE_WIDE
1198 /* The wide name is after the single byte name and
1199 format. */
1200 char *tcp = strchr (era->name_fmt, '\0') + 1;
1201 subfmt = (wchar_t *) (strchr (tcp, '\0') + 1);
1202 subfmt = wcschr (subfmt, L'\0') + 1;
1203 # else
1204 subfmt = strchr (era->name_fmt, '\0') + 1;
1205 # endif
1206 goto subformat;
1207 }
1208 #else
1209 # if HAVE_STRFTIME
1210 goto underlying_strftime;
1211 # endif
1212 #endif
1213 }
1214 if (modifier == L_('O'))
1215 goto bad_format;
1216 else
1217 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1218
1219 case L_('y'):
1220 if (modifier == L_('E'))
1221 {
1222 #if HAVE_STRUCT_ERA_ENTRY
1223 struct era_entry *era = _nl_get_era_entry (tp);
1224 if (era)
1225 {
1226 int delta = tp->tm_year - era->start_date[0];
1227 DO_NUMBER (1, (era->offset
1228 + (era->direction == '-' ? -delta : delta)));
1229 }
1230 #else
1231 # if HAVE_STRFTIME
1232 goto underlying_strftime;
1233 # endif
1234 #endif
1235 }
1236 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1237
1238 case L_('Z'):
1239 if (change_case)
1240 {
1241 to_uppcase = 0;
1242 to_lowcase = 1;
1243 }
1244
1245 #if HAVE_TZNAME
1246 /* The tzset() call might have changed the value. */
1247 if (!(zone && *zone) && tp->tm_isdst >= 0)
1248 zone = tzname[tp->tm_isdst];
1249 #endif
1250 if (! zone)
1251 zone = ""; /* POSIX.2 requires the empty string here. */
1252
1253 #ifdef COMPILE_WIDE
1254 {
1255 /* The zone string is always given in multibyte form. We have
1256 to transform it first. */
1257 wchar_t *wczone;
1258 size_t len;
1259 widen (zone, wczone, len);
1260 cpy (len, wczone);
1261 }
1262 #else
1263 cpy (strlen (zone), zone);
1264 #endif
1265 break;
1266
1267 case L_('z'): /* GNU extension. */
1268 if (tp->tm_isdst < 0)
1269 break;
1270
1271 {
1272 int diff;
1273 #if HAVE_TM_GMTOFF
1274 diff = tp->tm_gmtoff;
1275 #else
1276 if (ut)
1277 diff = 0;
1278 else
1279 {
1280 struct tm gtm;
1281 struct tm ltm;
1282 time_t lt;
1283
1284 ltm = *tp;
1285 lt = mktime (&ltm);
1286
1287 if (lt == (time_t) -1)
1288 {
1289 /* mktime returns -1 for errors, but -1 is also a
1290 valid time_t value. Check whether an error really
1291 occurred. */
1292 struct tm tm;
1293
1294 if (! my_strftime_localtime_r (&lt, &tm)
1295 || ((ltm.tm_sec ^ tm.tm_sec)
1296 | (ltm.tm_min ^ tm.tm_min)
1297 | (ltm.tm_hour ^ tm.tm_hour)
1298 | (ltm.tm_mday ^ tm.tm_mday)
1299 | (ltm.tm_mon ^ tm.tm_mon)
1300 | (ltm.tm_year ^ tm.tm_year)))
1301 break;
1302 }
1303
1304 if (! my_strftime_gmtime_r (&lt, &gtm))
1305 break;
1306
1307 diff = tm_diff (&ltm, &gtm);
1308 }
1309 #endif
1310
1311 if (diff < 0)
1312 {
1313 add (1, *p = L_('-'));
1314 diff = -diff;
1315 }
1316 else
1317 add (1, *p = L_('+'));
1318
1319 diff /= 60;
1320 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1321 }
1322
1323 case L_('\0'): /* GNU extension: % at end of format. */
1324 --f;
1325 /* Fall through. */
1326 default:
1327 /* Unknown format; output the format, including the '%',
1328 since this is most likely the right thing to do if a
1329 multibyte string has been misparsed. */
1330 bad_format:
1331 {
1332 int flen;
1333 for (flen = 1; f[1 - flen] != L_('%'); flen++)
1334 continue;
1335 cpy (flen, &f[1 - flen]);
1336 }
1337 break;
1338 }
1339 }
1340
1341 if (p && maxsize != 0)
1342 *p = L_('\0');
1343 return i;
1344 }
1345
1346
1347 #ifdef emacs
1348 /* For Emacs we have a separate interface which corresponds to the normal
1349 strftime function and does not have the extra information whether the
1350 TP arguments comes from a `gmtime' call or not. */
1351 size_t
1352 emacs_strftime (s, maxsize, format, tp)
1353 char *s;
1354 size_t maxsize;
1355 const char *format;
1356 const struct tm *tp;
1357 {
1358 return my_strftime (s, maxsize, format, tp, 0);
1359 }
1360 #endif