Add const where necessary to avoid warnings.
[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, (const 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 =
795                        (const CHAR_T *) _NL_CURRENT (LC_TIME,
796                                                      NLW(ERA_D_T_FMT)))
797                      != '\0')))
798             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
799 #else
800 # if HAVE_STRFTIME
801           goto underlying_strftime;
802 # else
803           subfmt = L_("%a %b %e %H:%M:%S %Y");
804 # endif
805 #endif
806
807         subformat:
808           {
809             CHAR_T *old_start = p;
810             size_t len = my_strftime (NULL, (size_t) -1, subfmt,
811                                       tp ut_argument);
812             add (len, my_strftime (p, maxsize - i, subfmt,
813                                    tp ut_argument));
814
815             if (to_uppcase)
816               while (old_start < p)
817                 {
818                   *old_start = TOUPPER ((UCHAR_T) *old_start);
819                   ++old_start;
820                 }
821           }
822           break;
823
824 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
825         underlying_strftime:
826           {
827             /* The relevant information is available only via the
828                underlying strftime implementation, so use that.  */
829             char ufmt[4];
830             char *u = ufmt;
831             char ubuf[1024]; /* enough for any single format in practice */
832             size_t len;
833             /* Make sure we're calling the actual underlying strftime.
834                In some cases, config.h contains something like
835                "#define strftime rpl_strftime".  */
836 # ifdef strftime
837 #  undef strftime
838             size_t strftime ();
839 # endif
840
841             *u++ = '%';
842             if (modifier != 0)
843               *u++ = modifier;
844             *u++ = format_char;
845             *u = '\0';
846             len = strftime (ubuf, sizeof ubuf, ufmt, tp);
847             if (len == 0 && ubuf[0] != '\0')
848               return 0;
849             cpy (len, ubuf);
850           }
851           break;
852 #endif
853
854         case L_('C'):           /* POSIX.2 extension.  */
855           if (modifier == L_('O'))
856             goto bad_format;
857           if (modifier == L_('E'))
858             {
859 #if HAVE_STRUCT_ERA_ENTRY
860               struct era_entry *era = _nl_get_era_entry (tp);
861               if (era)
862                 {
863 # ifdef COMPILE_WIDE
864                   size_t len = __wcslen (era->era_wname);
865                   cpy (len, era->era_wname);
866 # else
867                   size_t len = strlen (era->era_name);
868                   cpy (len, era->era_name);
869 # endif
870                   break;
871                 }
872 #else
873 # if HAVE_STRFTIME
874               goto underlying_strftime;
875 # endif
876 #endif
877             }
878
879           {
880             int year = tp->tm_year + TM_YEAR_BASE;
881             DO_NUMBER (1, year / 100 - (year % 100 < 0));
882           }
883
884         case L_('x'):
885           if (modifier == L_('O'))
886             goto bad_format;
887 #ifdef _NL_CURRENT
888           if (! (modifier == L_('E')
889                  && (*(subfmt =
890                        (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
891                      != L_('\0'))))
892             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
893           goto subformat;
894 #else
895 # if HAVE_STRFTIME
896           goto underlying_strftime;
897 # else
898           /* Fall through.  */
899 # endif
900 #endif
901         case L_('D'):           /* POSIX.2 extension.  */
902           if (modifier != 0)
903             goto bad_format;
904           subfmt = L_("%m/%d/%y");
905           goto subformat;
906
907         case L_('d'):
908           if (modifier == L_('E'))
909             goto bad_format;
910
911           DO_NUMBER (2, tp->tm_mday);
912
913         case L_('e'):           /* POSIX.2 extension.  */
914           if (modifier == L_('E'))
915             goto bad_format;
916
917           DO_NUMBER_SPACEPAD (2, tp->tm_mday);
918
919           /* All numeric formats set DIGITS and NUMBER_VALUE and then
920              jump to one of these two labels.  */
921
922         do_number_spacepad:
923           /* Force `_' flag unless overwritten by `0' flag.  */
924           if (pad != L_('0'))
925             pad = L_('_');
926
927         do_number:
928           /* Format the number according to the MODIFIER flag.  */
929
930           if (modifier == L_('O') && 0 <= number_value)
931             {
932 #ifdef _NL_CURRENT
933               /* Get the locale specific alternate representation of
934                  the number NUMBER_VALUE.  If none exist NULL is returned.  */
935 # ifdef COMPILE_WIDE
936               const wchar_t *cp = _nl_get_walt_digit (number_value);
937 # else
938               const char *cp = _nl_get_alt_digit (number_value);
939 # endif
940
941               if (cp != NULL)
942                 {
943                   size_t digitlen = STRLEN (cp);
944                   if (digitlen != 0)
945                     {
946                       cpy (digitlen, cp);
947                       break;
948                     }
949                 }
950 #else
951 # if HAVE_STRFTIME
952               goto underlying_strftime;
953 # endif
954 #endif
955             }
956           {
957             unsigned int u = number_value;
958
959             bufp = buf + sizeof (buf) / sizeof (buf[0]);
960             negative_number = number_value < 0;
961
962             if (negative_number)
963               u = -u;
964
965             do
966               *--bufp = u % 10 + L_('0');
967             while ((u /= 10) != 0);
968           }
969
970         do_number_sign_and_padding:
971           if (negative_number)
972             *--bufp = L_('-');
973
974           if (pad != L_('-'))
975             {
976               int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
977                                       - bufp);
978
979               if (pad == L_('_'))
980                 {
981                   while (0 < padding--)
982                     *--bufp = L_(' ');
983                 }
984               else
985                 {
986                   bufp += negative_number;
987                   while (0 < padding--)
988                     *--bufp = L_('0');
989                   if (negative_number)
990                     *--bufp = L_('-');
991                 }
992             }
993
994           cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
995           break;
996
997         case L_('F'):
998           if (modifier != 0)
999             goto bad_format;
1000           subfmt = L_("%Y-%m-%d");
1001           goto subformat;
1002
1003         case L_('H'):
1004           if (modifier == L_('E'))
1005             goto bad_format;
1006
1007           DO_NUMBER (2, tp->tm_hour);
1008
1009         case L_('I'):
1010           if (modifier == L_('E'))
1011             goto bad_format;
1012
1013           DO_NUMBER (2, hour12);
1014
1015         case L_('k'):           /* GNU extension.  */
1016           if (modifier == L_('E'))
1017             goto bad_format;
1018
1019           DO_NUMBER_SPACEPAD (2, tp->tm_hour);
1020
1021         case L_('l'):           /* GNU extension.  */
1022           if (modifier == L_('E'))
1023             goto bad_format;
1024
1025           DO_NUMBER_SPACEPAD (2, hour12);
1026
1027         case L_('j'):
1028           if (modifier == L_('E'))
1029             goto bad_format;
1030
1031           DO_NUMBER (3, 1 + tp->tm_yday);
1032
1033         case L_('M'):
1034           if (modifier == L_('E'))
1035             goto bad_format;
1036
1037           DO_NUMBER (2, tp->tm_min);
1038
1039         case L_('m'):
1040           if (modifier == L_('E'))
1041             goto bad_format;
1042
1043           DO_NUMBER (2, tp->tm_mon + 1);
1044
1045         case L_('n'):           /* POSIX.2 extension.  */
1046           add (1, *p = L_('\n'));
1047           break;
1048
1049         case L_('P'):
1050           to_lowcase = 1;
1051 #if !defined _NL_CURRENT && HAVE_STRFTIME
1052           format_char = L_('p');
1053 #endif
1054           /* FALLTHROUGH */
1055
1056         case L_('p'):
1057           if (change_case)
1058             {
1059               to_uppcase = 0;
1060               to_lowcase = 1;
1061             }
1062 #if defined _NL_CURRENT || !HAVE_STRFTIME
1063           cpy (ap_len, ampm);
1064           break;
1065 #else
1066           goto underlying_strftime;
1067 #endif
1068
1069         case L_('R'):           /* GNU extension.  */
1070           subfmt = L_("%H:%M");
1071           goto subformat;
1072
1073         case L_('r'):           /* POSIX.2 extension.  */
1074 #ifdef _NL_CURRENT
1075           if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
1076                                                        NLW(T_FMT_AMPM)))
1077               == L_('\0'))
1078 #endif
1079             subfmt = L_("%I:%M:%S %p");
1080           goto subformat;
1081
1082         case L_('S'):
1083           if (modifier == L_('E'))
1084             goto bad_format;
1085
1086           DO_NUMBER (2, tp->tm_sec);
1087
1088         case L_('s'):           /* GNU extension.  */
1089           {
1090             struct tm ltm;
1091             time_t t;
1092
1093             ltm = *tp;
1094             t = mktime (&ltm);
1095
1096             /* Generate string value for T using time_t arithmetic;
1097                this works even if sizeof (long) < sizeof (time_t).  */
1098
1099             bufp = buf + sizeof (buf) / sizeof (buf[0]);
1100             negative_number = t < 0;
1101
1102             do
1103               {
1104                 int d = t % 10;
1105                 t /= 10;
1106
1107                 if (negative_number)
1108                   {
1109                     d = -d;
1110
1111                     /* Adjust if division truncates to minus infinity.  */
1112                     if (0 < -1 % 10 && d < 0)
1113                       {
1114                         t++;
1115                         d += 10;
1116                       }
1117                   }
1118
1119                 *--bufp = d + L_('0');
1120               }
1121             while (t != 0);
1122
1123             digits = 1;
1124             goto do_number_sign_and_padding;
1125           }
1126
1127         case L_('X'):
1128           if (modifier == L_('O'))
1129             goto bad_format;
1130 #ifdef _NL_CURRENT
1131           if (! (modifier == L_('E')
1132                  && (*(subfmt =
1133                        (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
1134                      != L_('\0'))))
1135             subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
1136           goto subformat;
1137 #else
1138 # if HAVE_STRFTIME
1139           goto underlying_strftime;
1140 # else
1141           /* Fall through.  */
1142 # endif
1143 #endif
1144         case L_('T'):           /* POSIX.2 extension.  */
1145           subfmt = L_("%H:%M:%S");
1146           goto subformat;
1147
1148         case L_('t'):           /* POSIX.2 extension.  */
1149           add (1, *p = L_('\t'));
1150           break;
1151
1152         case L_('u'):           /* POSIX.2 extension.  */
1153           DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1154
1155         case L_('U'):
1156           if (modifier == L_('E'))
1157             goto bad_format;
1158
1159           DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1160
1161         case L_('V'):
1162         case L_('g'):           /* GNU extension.  */
1163         case L_('G'):           /* GNU extension.  */
1164           if (modifier == L_('E'))
1165             goto bad_format;
1166           {
1167             int year = tp->tm_year + TM_YEAR_BASE;
1168             int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1169
1170             if (days < 0)
1171               {
1172                 /* This ISO week belongs to the previous year.  */
1173                 year--;
1174                 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1175                                       tp->tm_wday);
1176               }
1177             else
1178               {
1179                 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1180                                        tp->tm_wday);
1181                 if (0 <= d)
1182                   {
1183                     /* This ISO week belongs to the next year.  */
1184                     year++;
1185                     days = d;
1186                   }
1187               }
1188
1189             switch (*f)
1190               {
1191               case L_('g'):
1192                 DO_NUMBER (2, (year % 100 + 100) % 100);
1193
1194               case L_('G'):
1195                 DO_NUMBER (1, year);
1196
1197               default:
1198                 DO_NUMBER (2, days / 7 + 1);
1199               }
1200           }
1201
1202         case L_('W'):
1203           if (modifier == L_('E'))
1204             goto bad_format;
1205
1206           DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1207
1208         case L_('w'):
1209           if (modifier == L_('E'))
1210             goto bad_format;
1211
1212           DO_NUMBER (1, tp->tm_wday);
1213
1214         case L_('Y'):
1215           if (modifier == 'E')
1216             {
1217 #if HAVE_STRUCT_ERA_ENTRY
1218               struct era_entry *era = _nl_get_era_entry (tp);
1219               if (era)
1220                 {
1221 # ifdef COMPILE_WIDE
1222                   subfmt = era->era_wformat;
1223 # else
1224                   subfmt = era->era_format;
1225 # endif
1226                   goto subformat;
1227                 }
1228 #else
1229 # if HAVE_STRFTIME
1230               goto underlying_strftime;
1231 # endif
1232 #endif
1233             }
1234           if (modifier == L_('O'))
1235             goto bad_format;
1236           else
1237             DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1238
1239         case L_('y'):
1240           if (modifier == L_('E'))
1241             {
1242 #if HAVE_STRUCT_ERA_ENTRY
1243               struct era_entry *era = _nl_get_era_entry (tp);
1244               if (era)
1245                 {
1246                   int delta = tp->tm_year - era->start_date[0];
1247                   DO_NUMBER (1, (era->offset
1248                                  + delta * era->absolute_direction));
1249                 }
1250 #else
1251 # if HAVE_STRFTIME
1252               goto underlying_strftime;
1253 # endif
1254 #endif
1255             }
1256           DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1257
1258         case L_('Z'):
1259           if (change_case)
1260             {
1261               to_uppcase = 0;
1262               to_lowcase = 1;
1263             }
1264
1265 #if HAVE_TZNAME
1266           /* The tzset() call might have changed the value.  */
1267           if (!(zone && *zone) && tp->tm_isdst >= 0)
1268             zone = tzname[tp->tm_isdst];
1269 #endif
1270           if (! zone)
1271             zone = "";          /* POSIX.2 requires the empty string here.  */
1272
1273 #ifdef COMPILE_WIDE
1274           {
1275             /* The zone string is always given in multibyte form.  We have
1276                to transform it first.  */
1277             wchar_t *wczone;
1278             size_t len;
1279             widen (zone, wczone, len);
1280             cpy (len, wczone);
1281           }
1282 #else
1283           cpy (strlen (zone), zone);
1284 #endif
1285           break;
1286
1287         case L_('z'):           /* GNU extension.  */
1288           if (tp->tm_isdst < 0)
1289             break;
1290
1291           {
1292             int diff;
1293 #if HAVE_TM_GMTOFF
1294             diff = tp->tm_gmtoff;
1295 #else
1296             if (ut)
1297               diff = 0;
1298             else
1299               {
1300                 struct tm gtm;
1301                 struct tm ltm;
1302                 time_t lt;
1303
1304                 ltm = *tp;
1305                 lt = mktime (&ltm);
1306
1307                 if (lt == (time_t) -1)
1308                   {
1309                     /* mktime returns -1 for errors, but -1 is also a
1310                        valid time_t value.  Check whether an error really
1311                        occurred.  */
1312                     struct tm tm;
1313
1314                     if (! my_strftime_localtime_r (&lt, &tm)
1315                         || ((ltm.tm_sec ^ tm.tm_sec)
1316                             | (ltm.tm_min ^ tm.tm_min)
1317                             | (ltm.tm_hour ^ tm.tm_hour)
1318                             | (ltm.tm_mday ^ tm.tm_mday)
1319                             | (ltm.tm_mon ^ tm.tm_mon)
1320                             | (ltm.tm_year ^ tm.tm_year)))
1321                       break;
1322                   }
1323
1324                 if (! my_strftime_gmtime_r (&lt, &gtm))
1325                   break;
1326
1327                 diff = tm_diff (&ltm, &gtm);
1328               }
1329 #endif
1330
1331             if (diff < 0)
1332               {
1333                 add (1, *p = L_('-'));
1334                 diff = -diff;
1335               }
1336             else
1337               add (1, *p = L_('+'));
1338
1339             diff /= 60;
1340             DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1341           }
1342
1343         case L_('\0'):          /* GNU extension: % at end of format.  */
1344             --f;
1345             /* Fall through.  */
1346         default:
1347           /* Unknown format; output the format, including the '%',
1348              since this is most likely the right thing to do if a
1349              multibyte string has been misparsed.  */
1350         bad_format:
1351           {
1352             int flen;
1353             for (flen = 1; f[1 - flen] != L_('%'); flen++)
1354               continue;
1355             cpy (flen, &f[1 - flen]);
1356           }
1357           break;
1358         }
1359     }
1360
1361   if (p && maxsize != 0)
1362     *p = L_('\0');
1363   return i;
1364 }
1365
1366
1367 #ifdef emacs
1368 /* For Emacs we have a separate interface which corresponds to the normal
1369    strftime function and does not have the extra information whether the
1370    TP arguments comes from a `gmtime' call or not.  */
1371 size_t
1372 emacs_strftime (s, maxsize, format, tp)
1373       char *s;
1374       size_t maxsize;
1375       const char *format;
1376       const struct tm *tp;
1377 {
1378   return my_strftime (s, maxsize, format, tp, 0);
1379 }
1380 #endif