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