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