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