+ case 'A':
+ if (modifier != 0)
+ goto bad_format;
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (STRLEN (f_wkday), f_wkday);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('b'):
+ case L_('h'): /* POSIX.2 extension. */
+ if (modifier != 0)
+ goto bad_format;
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (am_len, a_month);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('B'):
+ if (modifier != 0)
+ goto bad_format;
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (STRLEN (f_month), f_month);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('c'):
+ if (modifier == L_('O'))
+ goto bad_format;
+#ifdef _NL_CURRENT
+ if (! (modifier == 'E'
+ && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
+ NLW(ERA_D_T_FMT)))
+ != '\0')))
+ subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# else
+ subfmt = L_("%a %b %e %H:%M:%S %Y");
+# endif
+#endif
+
+ subformat:
+ {
+ CHAR_T *old_start = p;
+ size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp);
+ add (len, my_strftime (p, maxsize - i, subfmt, tp));
+
+ if (to_uppcase)
+ while (old_start < p)
+ {
+ *old_start = TOUPPER ((UCHAR_T) *old_start);
+ ++old_start;
+ }
+ }
+ break;
+
+#if HAVE_STRFTIME && ! (defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
+ underlying_strftime:
+ {
+ /* The relevant information is available only via the
+ underlying strftime implementation, so use that. */
+ char ufmt[4];
+ char *u = ufmt;
+ char ubuf[1024]; /* enough for any single format in practice */
+ size_t len;
+ /* Make sure we're calling the actual underlying strftime.
+ In some cases, config.h contains something like
+ "#define strftime rpl_strftime". */
+# ifdef strftime
+# undef strftime
+ size_t strftime ();
+# endif
+
+ *u++ = '%';
+ if (modifier != 0)
+ *u++ = modifier;
+ *u++ = format_char;
+ *u = '\0';
+ len = strftime (ubuf, sizeof ubuf, ufmt, tp);
+ if (len == 0 && ubuf[0] != '\0')
+ return 0;
+ cpy (len, ubuf);
+ }
+ break;
+#endif
+
+ case L_('C'): /* POSIX.2 extension. */
+ if (modifier == L_('O'))
+ goto bad_format;
+ if (modifier == L_('E'))
+ {
+#if HAVE_STRUCT_ERA_ENTRY
+ struct era_entry *era = _nl_get_era_entry (tp);
+ if (era)
+ {
+# ifdef COMPILE_WIDE
+ size_t len = wcslen (era->era_wname);
+ cpy (len, era->era_wname);
+# else
+ size_t len = strlen (era->era_name);
+ cpy (len, era->era_name);
+# endif
+ break;
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+
+ {
+ int year = tp->tm_year + TM_YEAR_BASE;
+ DO_NUMBER (1, year / 100 - (year % 100 < 0));
+ }
+
+ case L_('x'):
+ if (modifier == L_('O'))
+ goto bad_format;
+#ifdef _NL_CURRENT
+ if (! (modifier == L_('E')
+ && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
+ NLW(ERA_D_FMT)))
+ != L_('\0'))))
+ subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
+ goto subformat;
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# else
+ /* Fall through. */
+# endif
+#endif
+ case L_('D'): /* POSIX.2 extension. */
+ if (modifier != 0)
+ goto bad_format;
+ subfmt = L_("%m/%d/%y");
+ goto subformat;
+
+ case L_('d'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_mday);
+
+ case L_('e'): /* POSIX.2 extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER_SPACEPAD (2, tp->tm_mday);
+
+ /* All numeric formats set DIGITS and NUMBER_VALUE and then
+ jump to one of these two labels. */
+
+ do_number_spacepad:
+ /* Force `_' flag unless overwritten by `0' flag. */
+ if (pad != L_('0'))
+ pad = L_('_');
+
+ do_number:
+ /* Format the number according to the MODIFIER flag. */
+
+ if (modifier == L_('O') && 0 <= number_value)
+ {
+#ifdef _NL_CURRENT
+ /* Get the locale specific alternate representation of
+ the number NUMBER_VALUE. If none exist NULL is returned. */
+# ifdef COMPILE_WIDE
+ const wchar_t *cp = _nl_get_walt_digit (number_value);
+# else
+ const char *cp = _nl_get_alt_digit (number_value);
+# endif
+
+ if (cp != NULL)
+ {
+ size_t digitlen = STRLEN (cp);
+ if (digitlen != 0)
+ {
+ cpy (digitlen, cp);
+ break;
+ }
+ }
+#else
+# if HAVE_STRFTIME
+ goto underlying_strftime;
+# endif
+#endif
+ }
+ {
+ unsigned int u = number_value;
+
+ bufp = buf + sizeof (buf) / sizeof (buf[0]);
+ negative_number = number_value < 0;
+
+ if (negative_number)
+ u = -u;
+
+ do
+ *--bufp = u % 10 + L_('0');
+ while ((u /= 10) != 0);
+ }
+
+ do_number_sign_and_padding:
+ if (negative_number)
+ *--bufp = L_('-');
+
+ if (pad != L_('-'))
+ {
+ int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
+ - bufp);
+
+ if (pad == L_('_'))
+ {
+ while (0 < padding--)
+ *--bufp = L_(' ');
+ }
+ else
+ {
+ bufp += negative_number;
+ while (0 < padding--)
+ *--bufp = L_('0');
+ if (negative_number)
+ *--bufp = L_('-');
+ }
+ }
+
+ cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
+ break;
+
+ case L_('F'):
+ if (modifier != 0)
+ goto bad_format;
+ subfmt = L_("%Y-%m-%d");
+ goto subformat;
+
+ case L_('H'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_hour);
+
+ case L_('I'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, hour12);
+
+ case L_('k'): /* GNU extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER_SPACEPAD (2, tp->tm_hour);
+
+ case L_('l'): /* GNU extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER_SPACEPAD (2, hour12);
+
+ case L_('j'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (3, 1 + tp->tm_yday);
+
+ case L_('M'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_min);
+
+ case L_('m'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_mon + 1);
+
+ case L_('n'): /* POSIX.2 extension. */
+ add (1, *p = L_('\n'));
+ break;
+
+ case L_('P'):
+ to_lowcase = 1;
+#if !defined _NL_CURRENT && HAVE_STRFTIME
+ format_char = L_('p');
+#endif
+ /* FALLTHROUGH */
+
+ case L_('p'):
+ if (change_case)
+ {
+ to_uppcase = 0;
+ to_lowcase = 1;
+ }
+#if defined _NL_CURRENT || !HAVE_STRFTIME
+ cpy (ap_len, ampm);
+ break;
+#else
+ goto underlying_strftime;
+#endif
+
+ case L_('R'): /* GNU extension. */
+ subfmt = L_("%H:%M");
+ goto subformat;
+
+ case L_('r'): /* POSIX.2 extension. */
+#ifdef _NL_CURRENT
+ if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
+ NLW(T_FMT_AMPM))) == L_('\0'))
+#endif
+ subfmt = L_("%I:%M:%S %p");
+ goto subformat;
+
+ case L_('S'):
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (2, tp->tm_sec);
+
+ case L_('s'): /* GNU extension. */
+ {
+ struct tm ltm;
+ time_t t;
+
+ ltm = *tp;
+ t = mktime (<m);
+
+ /* Generate string value for T using time_t arithmetic;
+ this works even if sizeof (long) < sizeof (time_t). */
+
+ bufp = buf + sizeof (buf) / sizeof (buf[0]);
+ negative_number = t < 0;
+
+ do