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