1 /* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc.
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.
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 /* Some systems need this in order to declare localtime_r properly. */
31 # define HAVE_LIMITS_H 1
33 # define HAVE_MBRLEN 1
34 # define HAVE_STRUCT_ERA_ENTRY 1
35 # define HAVE_TM_GMTOFF 1
36 # define HAVE_TM_ZONE 1
37 # define HAVE_TZNAME 1
39 # define MULTIBYTE_IS_FORMAT_SAFE 1
40 # define STDC_HEADERS 1
41 # include "../locale/localeinfo.h"
44 #if defined emacs && !defined HAVE_BCOPY
45 # define HAVE_MEMCPY 1
49 #include <sys/types.h> /* Some systems define `time_t' here. */
51 /* Some systems require <unistd.h> to be included before <time.h>
52 for localtime_r to be declared properly. */
57 #ifdef TIME_WITH_SYS_TIME
58 # include <sys/time.h>
61 # ifdef HAVE_SYS_TIME_H
62 # include <sys/time.h>
68 extern char *tzname[];
71 /* Do multibyte processing if multibytes are supported, unless
72 multibyte sequences are safe in formats. Multibyte sequences are
73 safe if they cannot contain byte sequences that look like format
74 conversion specifications. The GNU C Library uses UTF8 multibyte
75 encoding, which is safe for formats, but strftime.c can be used
76 with other C libraries that use unsafe encodings. */
77 #define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
83 /* Simulate mbrlen with mblen as best we can. */
84 # define mbstate_t int
85 # define mbrlen(s, n, ps) mblen (s, n)
86 # define mbsinit(ps) (*(ps) == 0)
88 static const mbstate_t mbstate_zero;
101 # define memcpy(d, s, n) bcopy ((s), (d), (n))
106 # define MEMPCPY(d, s, n) __mempcpy (d, s, n)
108 # ifndef HAVE_MEMPCPY
109 # define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
114 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
115 # define __P(args) args
117 # define __P(args) ()
119 #endif /* Not __P. */
137 #define TYPE_SIGNED(t) ((t) -1 < 0)
139 /* Bound on length of the string representing an integer value of type t.
140 Subtract one for the sign bit if t is signed;
141 302 / 1000 is log10 (2) rounded up;
142 add one for integer division truncation;
143 add one more for a minus sign if t is signed. */
144 #define INT_STRLEN_BOUND(t) \
145 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 100 + 1 + TYPE_SIGNED (t))
147 #define TM_YEAR_BASE 1900
150 /* Nonzero if YEAR is a leap year (every 4 years,
151 except every 100th isn't, and every 400th is). */
152 # define __isleap(year) \
153 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
158 # define gmtime_r __gmtime_r
159 # define localtime_r __localtime_r
160 # define tzname __tzname
161 # define tzset __tzset
163 # if ! HAVE_LOCALTIME_R
164 # if ! HAVE_TM_GMTOFF
165 /* Approximate gmtime_r as best we can in its absence. */
167 # define gmtime_r my_gmtime_r
168 static struct tm *gmtime_r __P ((const time_t *, struct tm *));
174 struct tm *l = gmtime (t);
180 # endif /* ! HAVE_TM_GMTOFF */
182 /* Approximate localtime_r as best we can in its absence. */
184 # define localtime_r my_ftime_localtime_r
185 static struct tm *localtime_r __P ((const time_t *, struct tm *));
191 struct tm *l = localtime (t);
197 # endif /* ! HAVE_LOCALTIME_R */
198 #endif /* ! defined _LIBC */
201 #if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
202 /* Some systems lack the `memset' function and we don't want to
203 introduce additional dependencies. */
204 /* The SGI compiler reportedly barfs on the trailing null
205 if we use a string constant as the initializer. 28 June 1997, rms. */
206 static const char spaces[16] = /* " " */
207 { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
208 static const char zeroes[16] = /* "0000000000000000" */
209 { '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0' };
211 # define memset_space(P, Len) \
217 int _this = _len > 16 ? 16 : _len; \
218 (P) = MEMPCPY ((P), spaces, _this); \
224 # define memset_zero(P, Len) \
230 int _this = _len > 16 ? 16 : _len; \
231 (P) = MEMPCPY ((P), zeroes, _this); \
237 # define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
238 # define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
245 int _delta = width - _n; \
246 int _incr = _n + (_delta > 0 ? _delta : 0); \
247 if (i + _incr >= maxsize) \
254 memset_zero (p, _delta); \
256 memset_space (p, _delta); \
267 memcpy_lowcase (p, (s), _n); \
268 else if (to_uppcase) \
269 memcpy_uppcase (p, (s), _n); \
271 memcpy ((PTR) p, (PTR) (s), _n))
276 # define TOUPPER(Ch) toupper (Ch)
277 # define TOLOWER(Ch) tolower (Ch)
279 # define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
280 # define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
282 /* We don't use `isdigit' here since the locale dependent
283 interpretation is not what we want here. We only need to accept
284 the arabic digits in the ASCII range. One day there is perhaps a
285 more reliable way to accept other sets of digits. */
286 #define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
288 static char *memcpy_lowcase __P ((char *dest, const char *src, size_t len));
291 memcpy_lowcase (dest, src, len)
297 dest[len] = TOLOWER ((unsigned char) src[len]);
301 static char *memcpy_uppcase __P ((char *dest, const char *src, size_t len));
304 memcpy_uppcase (dest, src, len)
310 dest[len] = TOUPPER ((unsigned char) src[len]);
316 /* Yield the difference between *A and *B,
317 measured in seconds, ignoring leap seconds. */
318 # define tm_diff ftime_tm_diff
319 static int tm_diff __P ((const struct tm *, const struct tm *));
325 /* Compute intervening leap days correctly even if year is negative.
326 Take care to avoid int overflow in leap day calculations,
327 but it's OK to assume that A and B are close to each other. */
328 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
329 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
330 int a100 = a4 / 25 - (a4 % 25 < 0);
331 int b100 = b4 / 25 - (b4 % 25 < 0);
332 int a400 = a100 >> 2;
333 int b400 = b100 >> 2;
334 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
335 int years = a->tm_year - b->tm_year;
336 int days = (365 * years + intervening_leap_days
337 + (a->tm_yday - b->tm_yday));
338 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
339 + (a->tm_min - b->tm_min))
340 + (a->tm_sec - b->tm_sec));
342 #endif /* ! HAVE_TM_GMTOFF */
346 /* The number of days from the first day of the first ISO week of this
347 year to the year day YDAY with week day WDAY. ISO weeks start on
348 Monday; the first ISO week has the year's first Thursday. YDAY may
349 be as small as YDAY_MINIMUM. */
350 #define ISO_WEEK_START_WDAY 1 /* Monday */
351 #define ISO_WEEK1_WDAY 4 /* Thursday */
352 #define YDAY_MINIMUM (-366)
353 static int iso_week_days __P ((int, int));
358 iso_week_days (yday, wday)
362 /* Add enough to the first operand of % to make it nonnegative. */
363 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
365 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
366 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
370 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
371 static char const weekday_name[][10] =
373 "Sunday", "Monday", "Tuesday", "Wednesday",
374 "Thursday", "Friday", "Saturday"
376 static char const month_name[][10] =
378 "January", "February", "March", "April", "May", "June",
379 "July", "August", "September", "October", "November", "December"
385 # define my_strftime emacs_strftime
386 /* Emacs 20.2 uses `-Dstrftime=emacs_strftime' when compiling,
387 because that's how strftime used to be configured.
388 Undo this, since it gets in the way of accessing the underlying strftime,
389 which is needed for things like %Ec in Solaris.
390 The following two lines can be removed once Emacs stops compiling with
391 `-Dstrftime=emacs_strftime'. */
393 size_t strftime __P ((char *, size_t, const char *, const struct tm *));
395 # define my_strftime strftime
398 #if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
399 /* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
400 Work around this bug by copying *tp before it might be munged. */
401 size_t _strftime_copytm __P ((char *, size_t, const char *,
404 my_strftime (s, maxsize, format, tp)
412 return _strftime_copytm (s, maxsize, format, &tmcopy);
415 # define my_strftime(S, Maxsize, Format, Tp) \
416 _strftime_copytm (S, Maxsize, Format, Tp)
420 /* Write information from TP into S according to the format
421 string FORMAT, writing no more that MAXSIZE characters
422 (including the terminating '\0') and returning number of
423 characters written. If S is NULL, nothing will be written
424 anywhere, so to determine how many characters would be
425 written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
427 my_strftime (s, maxsize, format, tp)
433 int hour12 = tp->tm_hour;
435 const char *const a_wkday = _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday);
436 const char *const f_wkday = _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday);
437 const char *const a_month = _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon);
438 const char *const f_month = _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon);
439 const char *const ampm = _NL_CURRENT (LC_TIME,
440 hour12 > 11 ? PM_STR : AM_STR);
441 size_t aw_len = strlen (a_wkday);
442 size_t am_len = strlen (a_month);
443 size_t ap_len = strlen (ampm);
446 const char *const f_wkday = weekday_name[tp->tm_wday];
447 const char *const f_month = month_name[tp->tm_mon];
448 const char *const a_wkday = f_wkday;
449 const char *const a_month = f_month;
450 const char *const ampm = "AMPM" + 2 * (hour12 > 11);
456 #if defined _NL_CURRENT || !HAVE_STRFTIME
457 size_t wkday_len = strlen (f_wkday);
458 size_t month_len = strlen (f_month);
468 /* The POSIX test suite assumes that setting
469 the environment variable TZ to a new value before calling strftime()
470 will influence the result (the %Z format) even if the information in
471 TP is computed with a totally different time zone.
472 This is bogus: though POSIX allows bad behavior like this,
473 POSIX does not require it. Do the right thing instead. */
474 zone = (const char *) tp->tm_zone;
477 /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
478 time zone names contained in the external variable `tzname' shall
479 be set as if the tzset() function had been called. */
484 if (!(zone && *zone) && tp->tm_isdst >= 0)
485 zone = tzname[tp->tm_isdst];
488 zone = ""; /* POSIX.2 requires the empty string here. */
490 zonelen = strlen (zone);
495 if (hour12 == 0) hour12 = 12;
497 for (f = format; *f != '\0'; ++f)
499 int pad = 0; /* Padding for number ('-', '_', or 0). */
500 int modifier; /* Field modifier ('E', 'O', or 0). */
501 int digits; /* Max digits for numeric format. */
502 int number_value; /* Numeric value to be printed. */
503 int negative_number; /* 1 if the number is negative. */
506 char buf[1 + (sizeof (int) < sizeof (time_t)
507 ? INT_STRLEN_BOUND (time_t)
508 : INT_STRLEN_BOUND (int))];
522 case '\a': case '\b': case '\t': case '\n':
523 case '\v': case '\f': case '\r':
524 case ' ': case '!': case '"': case '#': case '&': case'\'':
525 case '(': case ')': case '*': case '+': case ',': case '-':
526 case '.': case '/': case '0': case '1': case '2': case '3':
527 case '4': case '5': case '6': case '7': case '8': case '9':
528 case ':': case ';': case '<': case '=': case '>': case '?':
529 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
530 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
531 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
532 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
533 case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
534 case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
535 case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
536 case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
537 case 'r': case 's': case 't': case 'u': case 'v': case 'w':
538 case 'x': case 'y': case 'z': case '{': case '|': case '}':
540 /* The C Standard requires these 98 characters (plus '%') to
541 be in the basic execution character set. None of these
542 characters can start a multibyte sequence, so they need
543 not be analyzed further. */
548 /* Copy this multibyte sequence until we reach its end, find
549 an error, or come back to the initial shift state. */
551 mbstate_t mbstate = mbstate_zero;
556 size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
561 if (bytes == (size_t) -2 || bytes == (size_t) -1)
569 while (! mbsinit (&mbstate));
576 #else /* ! DO_MULTIBYTE */
578 /* Either multibyte encodings are not supported, or they are
579 safe for formats, so any non-'%' byte can be copied through. */
586 #endif /* ! DO_MULTIBYTE */
588 /* Check for flags that can modify a format. */
593 /* This influences the number formats. */
600 /* This changes textual output. */
614 /* As a GNU extension we allow to specify the field width. */
624 while (ISDIGIT (*f));
627 /* Check for modifiers. */
640 /* Now do the specified format. */
644 #define DO_NUMBER(d, v) \
645 digits = width == -1 ? d : width; \
646 number_value = v; goto do_number
647 #define DO_NUMBER_SPACEPAD(d, v) \
648 digits = width == -1 ? d : width; \
649 number_value = v; goto do_number_spacepad
665 #if defined _NL_CURRENT || !HAVE_STRFTIME
666 cpy (aw_len, a_wkday);
669 goto underlying_strftime;
680 #if defined _NL_CURRENT || !HAVE_STRFTIME
681 cpy (wkday_len, f_wkday);
684 goto underlying_strftime;
688 case 'h': /* POSIX.2 extension. */
691 #if defined _NL_CURRENT || !HAVE_STRFTIME
692 cpy (am_len, a_month);
695 goto underlying_strftime;
706 #if defined _NL_CURRENT || !HAVE_STRFTIME
707 cpy (month_len, f_month);
710 goto underlying_strftime;
717 if (! (modifier == 'E'
718 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT)) != '\0'))
719 subfmt = _NL_CURRENT (LC_TIME, D_T_FMT);
722 goto underlying_strftime;
724 subfmt = "%a %b %e %H:%M:%S %Y";
731 size_t len = my_strftime (NULL, maxsize - i, subfmt, tp);
732 if (len == 0 && *subfmt)
734 add (len, my_strftime (p, maxsize - i, subfmt, tp));
737 while (old_start < p)
739 *old_start = TOUPPER ((unsigned char) *old_start);
745 #if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
748 /* The relevant information is available only via the
749 underlying strftime implementation, so use that. */
752 char ubuf[1024]; /* enough for any single format in practice */
760 len = strftime (ubuf, sizeof ubuf, ufmt, tp);
761 if (len == 0 && ubuf[0] != '\0')
768 case 'C': /* POSIX.2 extension. */
773 #if HAVE_STRUCT_ERA_ENTRY
774 struct era_entry *era = _nl_get_era_entry (tp);
777 size_t len = strlen (era->name_fmt);
778 cpy (len, era->name_fmt);
783 goto underlying_strftime;
789 int year = tp->tm_year + TM_YEAR_BASE;
790 DO_NUMBER (1, year / 100 - (year % 100 < 0));
797 if (! (modifier == 'E'
798 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_FMT)) != '\0'))
799 subfmt = _NL_CURRENT (LC_TIME, D_FMT);
803 goto underlying_strftime;
808 case 'D': /* POSIX.2 extension. */
818 DO_NUMBER (2, tp->tm_mday);
820 case 'e': /* POSIX.2 extension. */
824 DO_NUMBER_SPACEPAD (2, tp->tm_mday);
826 /* All numeric formats set DIGITS and NUMBER_VALUE and then
827 jump to one of these two labels. */
830 /* Force `_' flag unless overwritten by `0' flag. */
835 /* Format the number according to the MODIFIER flag. */
837 if (modifier == 'O' && 0 <= number_value)
840 /* Get the locale specific alternate representation of
841 the number NUMBER_VALUE. If none exist NULL is returned. */
842 const char *cp = _nl_get_alt_digit (number_value);
846 size_t digitlen = strlen (cp);
855 goto underlying_strftime;
860 unsigned int u = number_value;
862 bufp = buf + sizeof (buf);
863 negative_number = number_value < 0;
869 *--bufp = u % 10 + '0';
870 while ((u /= 10) != 0);
873 do_number_sign_and_padding:
879 int padding = digits - (buf + sizeof (buf) - bufp);
883 while (0 < padding--)
888 bufp += negative_number;
889 while (0 < padding--)
896 cpy (buf + sizeof (buf) - bufp, bufp);
909 DO_NUMBER (2, tp->tm_hour);
915 DO_NUMBER (2, hour12);
917 case 'k': /* GNU extension. */
921 DO_NUMBER_SPACEPAD (2, tp->tm_hour);
923 case 'l': /* GNU extension. */
927 DO_NUMBER_SPACEPAD (2, hour12);
933 DO_NUMBER (3, 1 + tp->tm_yday);
939 DO_NUMBER (2, tp->tm_min);
945 DO_NUMBER (2, tp->tm_mon + 1);
947 case 'n': /* POSIX.2 extension. */
953 #if !defined _NL_CURRENT && HAVE_STRFTIME
964 #if defined _NL_CURRENT || !HAVE_STRFTIME
968 goto underlying_strftime;
971 case 'R': /* GNU extension. */
975 case 'r': /* POSIX.2 extension. */
977 if (*(subfmt = _NL_CURRENT (LC_TIME, T_FMT_AMPM)) == '\0')
979 subfmt = "%I:%M:%S %p";
986 DO_NUMBER (2, tp->tm_sec);
988 case 's': /* GNU extension. */
996 /* Generate string value for T using time_t arithmetic;
997 this works even if sizeof (long) < sizeof (time_t). */
999 bufp = buf + sizeof (buf);
1000 negative_number = t < 0;
1007 if (negative_number)
1011 /* Adjust if division truncates to minus infinity. */
1012 if (0 < -1 % 10 && d < 0)
1024 goto do_number_sign_and_padding;
1028 if (modifier == 'O')
1031 if (! (modifier == 'E'
1032 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_T_FMT)) != '\0'))
1033 subfmt = _NL_CURRENT (LC_TIME, T_FMT);
1037 goto underlying_strftime;
1042 case 'T': /* POSIX.2 extension. */
1043 subfmt = "%H:%M:%S";
1046 case 't': /* POSIX.2 extension. */
1051 case 'u': /* POSIX.2 extension. */
1052 DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
1055 if (modifier == 'E')
1058 DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
1061 case 'g': /* GNU extension. */
1062 case 'G': /* GNU extension. */
1063 if (modifier == 'E')
1066 int year = tp->tm_year + TM_YEAR_BASE;
1067 int days = iso_week_days (tp->tm_yday, tp->tm_wday);
1071 /* This ISO week belongs to the previous year. */
1073 days = iso_week_days (tp->tm_yday + (365 + __isleap (year)),
1078 int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
1082 /* This ISO week belongs to the next year. */
1091 DO_NUMBER (2, (year % 100 + 100) % 100);
1094 DO_NUMBER (1, year);
1097 DO_NUMBER (2, days / 7 + 1);
1102 if (modifier == 'E')
1105 DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
1108 if (modifier == 'E')
1111 DO_NUMBER (1, tp->tm_wday);
1114 if (modifier == 'E')
1116 #if HAVE_STRUCT_ERA_ENTRY
1117 struct era_entry *era = _nl_get_era_entry (tp);
1120 subfmt = strchr (era->name_fmt, '\0') + 1;
1125 goto underlying_strftime;
1129 if (modifier == 'O')
1132 DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
1135 if (modifier == 'E')
1137 #if HAVE_STRUCT_ERA_ENTRY
1138 struct era_entry *era = _nl_get_era_entry (tp);
1141 int delta = tp->tm_year - era->start_date[0];
1142 DO_NUMBER (1, (era->offset
1143 + (era->direction == '-' ? -delta : delta)));
1147 goto underlying_strftime;
1151 DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
1159 cpy (zonelen, zone);
1162 case 'z': /* GNU extension. */
1163 if (tp->tm_isdst < 0)
1169 diff = tp->tm_gmtoff;
1178 if (lt == (time_t) -1)
1180 /* mktime returns -1 for errors, but -1 is also a
1181 valid time_t value. Check whether an error really
1184 localtime_r (<, &tm);
1186 if ((ltm.tm_sec ^ tm.tm_sec)
1187 | (ltm.tm_min ^ tm.tm_min)
1188 | (ltm.tm_hour ^ tm.tm_hour)
1189 | (ltm.tm_mday ^ tm.tm_mday)
1190 | (ltm.tm_mon ^ tm.tm_mon)
1191 | (ltm.tm_year ^ tm.tm_year))
1195 if (! gmtime_r (<, >m))
1198 diff = tm_diff (<m, >m);
1210 DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
1213 case '\0': /* GNU extension: % at end of format. */
1217 /* Unknown format; output the format, including the '%',
1218 since this is most likely the right thing to do if a
1219 multibyte string has been misparsed. */
1223 for (flen = 1; f[1 - flen] != '%'; flen++)
1225 cpy (flen, &f[1 - flen]);