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