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