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