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