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