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