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