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