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