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