xref: /netbsd-src/external/gpl2/diffutils/dist/lib/strftime.c (revision 75f6d617e282811cb173c2ccfbf5df0dd71f7045)
1 /*	$NetBSD: strftime.c,v 1.1.1.1 2016/01/13 03:15:30 christos Exp $	*/
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
59 extern 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
184 static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
185 static struct tm *
my_strftime_gmtime_r(t,tp)186 my_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 
197 static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
198 static struct tm *
my_strftime_localtime_r(t,tp)199 my_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.  */
218 static 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 };
223 static 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 
327 static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
328 				    size_t len));
329 
330 static CHAR_T *
memcpy_lowcase(dest,src,len)331 memcpy_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 
341 static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
342 				    size_t len));
343 
344 static CHAR_T *
memcpy_uppcase(dest,src,len)345 memcpy_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
360 static int tm_diff __P ((const struct tm *, const struct tm *));
361 static int
tm_diff(a,b)362 tm_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)
394 static int iso_week_days __P ((int, int));
395 #ifdef __GNUC__
396 __inline__
397 #endif
398 static int
iso_week_days(yday,wday)399 iso_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)
412 static CHAR_T const weekday_name[][10] =
413   {
414     L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
415     L_("Thursday"), L_("Friday"), L_("Saturday")
416   };
417 static 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.  */
481 size_t
482 my_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.  */
1398 size_t
emacs_strftimeu(s,maxsize,format,tp,ut)1399 emacs_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