-/* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1991-1999, 2000, 2001 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
# define L_(Str) L##Str
# define NLW(Sym) _NL_W##Sym
-# define MEMCPY(d, s, n) wmemcpy (d, s, n)
-# define STRLEN(s) wcslen (s)
+# define MEMCPY(d, s, n) __wmemcpy (d, s, n)
+# define STRLEN(s) __wcslen (s)
#else
# define CHAR_T char
*tp = *l;
return tp;
}
-# endif /* ! HAVE_TM_GMTOFF */
static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
static struct tm *
*tp = *l;
return tp;
}
+# endif /* ! HAVE_TM_GMTOFF */
#endif /* ! defined _LIBC */
else if (to_uppcase) \
memcpy_uppcase (p, (s), _n); \
else \
- MEMCPY ((PTR) p, (PTR) (s), _n))
+ MEMCPY ((PTR) p, (const PTR) (s), _n))
#ifdef COMPILE_WIDE
# define widen(os, ws, l) \
#endif
-#ifdef emacs
-# define my_strftime emacs_strftimeu
-# define ut_argument , ut
-# define ut_argument_spec int ut;
-# define ut_argument_spec_iso , int ut
+/* When compiling this file, GNU applications can #define my_strftime
+ to a symbol (typically nstrftime) to get an extended strftime with
+ extra arguments UT and NS. Emacs is a special case for now, but
+ this Emacs-specific code can be removed once Emacs's config.h
+ defines my_strftime. */
+#if defined emacs && !defined my_strftime
+# define my_strftime nstrftime
+#endif
+
+#ifdef my_strftime
+# define extra_args , ut, ns
+# define extra_args_spec int ut; int ns;
+# define extra_args_spec_iso , int ut, int ns
#else
# ifdef COMPILE_WIDE
# define my_strftime wcsftime
# else
# define my_strftime strftime
# endif
-# define ut_argument
-# define ut_argument_spec
-# define ut_argument_spec_iso
+# define extra_args
+# define extra_args_spec
+# define extra_args_spec_iso
/* We don't have this information in general. */
# define ut 0
+# define ns 0
#endif
#if !defined _LIBC && HAVE_TZNAME && HAVE_TZSET
/* Solaris 2.5 tzset sometimes modifies the storage returned by localtime.
Work around this bug by copying *tp before it might be munged. */
size_t _strftime_copytm __P ((char *, size_t, const char *,
- const struct tm * ut_argument_spec_iso));
+ const struct tm * extra_args_spec_iso));
size_t
- my_strftime (s, maxsize, format, tp ut_argument)
+ my_strftime (s, maxsize, format, tp extra_args)
CHAR_T *s;
size_t maxsize;
const CHAR_T *format;
const struct tm *tp;
- ut_argument_spec
+ extra_args_spec
{
struct tm tmcopy;
tmcopy = *tp;
- return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
+ return _strftime_copytm (s, maxsize, format, &tmcopy extra_args);
}
# undef my_strftime
-# define my_strftime(S, Maxsize, Format, Tp) \
- _strftime_copytm (S, Maxsize, Format, Tp)
+# define my_strftime _strftime_copytm
#endif
anywhere, so to determine how many characters would be
written, use NULL for S and (size_t) UINT_MAX for MAXSIZE. */
size_t
-my_strftime (s, maxsize, format, tp ut_argument)
+my_strftime (s, maxsize, format, tp extra_args)
CHAR_T *s;
size_t maxsize;
const CHAR_T *format;
const struct tm *tp;
- ut_argument_spec
+ extra_args_spec
{
int hour12 = tp->tm_hour;
#ifdef _NL_CURRENT
size_t i = 0;
CHAR_T *p = s;
const CHAR_T *f;
+#if DO_MULTIBYTE && !defined COMPILE_WIDE
+ const char *format_end = NULL;
+#endif
zone = NULL;
#if HAVE_TM_ZONE
{
mbstate_t mbstate = mbstate_zero;
size_t len = 0;
+ size_t fsize;
+
+ if (! format_end)
+ format_end = f + strlen (f) + 1;
+ fsize = format_end - f;
do
{
- size_t bytes = mbrlen (f + len, (size_t) -1, &mbstate);
+ size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
if (bytes == 0)
break;
case L_('b'):
case L_('h'): /* POSIX.2 extension. */
+ if (change_case)
+ {
+ to_uppcase = 1;
+ to_lowcase = 0;
+ }
if (modifier != 0)
goto bad_format;
#if defined _NL_CURRENT || !HAVE_STRFTIME
goto bad_format;
#ifdef _NL_CURRENT
if (! (modifier == 'E'
- && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
- NLW(ERA_D_T_FMT)))
+ && (*(subfmt =
+ (const CHAR_T *) _NL_CURRENT (LC_TIME,
+ NLW(ERA_D_T_FMT)))
!= '\0')))
- subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
+ subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
#else
# if HAVE_STRFTIME
goto underlying_strftime;
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));
+ size_t len = my_strftime (NULL, (size_t) -1, subfmt,
+ tp extra_args);
+ add (len, my_strftime (p, maxsize - i, subfmt,
+ tp extra_args));
if (to_uppcase)
while (old_start < p)
"#define strftime rpl_strftime". */
# ifdef strftime
# undef strftime
+ size_t strftime ();
# endif
*u++ = '%';
if (era)
{
# ifdef COMPILE_WIDE
- size_t len = wcslen (era->era_wname);
+ size_t len = __wcslen (era->era_wname);
cpy (len, era->era_wname);
# else
size_t len = strlen (era->era_name);
goto bad_format;
#ifdef _NL_CURRENT
if (! (modifier == L_('E')
- && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
- NLW(ERA_D_FMT)))
+ && (*(subfmt =
+ (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
!= L_('\0'))))
- subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
+ subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
goto subformat;
#else
# if HAVE_STRFTIME
DO_NUMBER (2, tp->tm_mon + 1);
+ case L_('N'): /* GNU extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ number_value = ns;
+ if (width != -1)
+ {
+ /* Take an explicit width less than 9 as a precision. */
+ int j;
+ for (j = width; j < 9; j++)
+ number_value /= 10;
+ }
+
+ DO_NUMBER (9, number_value);
+
case L_('n'): /* POSIX.2 extension. */
add (1, *p = L_('\n'));
break;
goto underlying_strftime;
#endif
- case L_('R'): /* GNU extension. */
+ case L_('R'): /* ISO C99 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'))
+ if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
+ NLW(T_FMT_AMPM)))
+ == L_('\0'))
#endif
subfmt = L_("%I:%M:%S %p");
goto subformat;
goto bad_format;
#ifdef _NL_CURRENT
if (! (modifier == L_('E')
- && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
- NLW(ERA_T_FMT)))
+ && (*(subfmt =
+ (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
!= L_('\0'))))
- subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
+ subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
goto subformat;
#else
# if HAVE_STRFTIME
DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
case L_('V'):
- case L_('g'): /* GNU extension. */
- case L_('G'): /* GNU extension. */
+ case L_('g'): /* ISO C99 extension. */
+ case L_('G'): /* ISO C99 extension. */
if (modifier == L_('E'))
goto bad_format;
{
#endif
break;
- case L_('z'): /* GNU extension. */
+ case L_('z'): /* ISO C99 extension. */
if (tp->tm_isdst < 0)
break;
#ifdef emacs
/* For Emacs we have a separate interface which corresponds to the normal
- strftime function and does not have the extra information whether the
- TP arguments comes from a `gmtime' call or not. */
+ strftime function plus the ut argument, but without the ns argument. */
size_t
-emacs_strftime (s, maxsize, format, tp)
+emacs_strftimeu (s, maxsize, format, tp, ut)
char *s;
size_t maxsize;
const char *format;
const struct tm *tp;
+ int ut;
{
- return my_strftime (s, maxsize, format, tp, 0);
+ return my_strftime (s, maxsize, format, tp, ut, 0);
}
#endif