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