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