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