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