aboutsummaryrefslogtreecommitdiff
path: root/time/strftime.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-03-14 21:12:06 +0000
committerUlrich Drepper <drepper@redhat.com>2004-03-14 21:12:06 +0000
commitccadf7b5346a3e21c692dfcbfcf38a63433bc36a (patch)
treea1e826af3345eee581925387513b1b6c76629c31 /time/strftime.c
parent3bc9b83f49805969b7d139b52ef6b003e5136354 (diff)
downloadglibc-ccadf7b5346a3e21c692dfcbfcf38a63433bc36a.tar.xz
glibc-ccadf7b5346a3e21c692dfcbfcf38a63433bc36a.zip
Update.
2004-03-14 Ulrich Drepper <drepper@redhat.com> Make the non-_l functions wrappers around the _l functions. * include/monetary.h: Declare __vstrmon_l. * include/string.h: Add libc_hidden_proto for __strcoll_l and __strxfrm_l. * include/time.h: Define ptime_locale_status. Declare __strptime_internal. * include/wchar.h: Add libc_hidden_proto for __wcscoll_l and __wcsxfrm_l. * stdlib/strfmon.c: Move the code to strfmon_l.c. Add little wrapper around __vstrfmon_l. * stdlib/strfmon_l.c: Add real implementation. Split into new function __vstrfmon_l to allow calling it from strfmon. * stdlib/strtod.c: Move real code to strtod_l.c and add wrapper. * stdlib/strtod_l.c: Add real implementation. * stdlib/strtof.c: Adjust to changed strtod.c. * stdlib/strtof_l.c: Include strtod_l.c now. * stdlib/strtold.c: New file. * stdlib/strtold_l.c: Removed. * string/strcoll.c: Move real code to strcoll_l.c: Add wrapper. * string/strcoll_l.c: Add real implementation. * string/strxfrm.c: Move real code to strxfrm_l.c: Add wrapper. * string/strxfrm_l.c: Add real implementation. * sysdeps/generic/strtol.c: Move real implementation to strtol_l.c. Add wrappers. * sysdeps/generic/strtol_l.c: Add real implementation. * sysdeps/generic/strtold.c: Removed. * sysdeps/generic/strtold_l.c: New file. * sysdeps/generic/strtoll_l.c: Include strtol_l.c now. Adjust #defines. * sysdeps/generic/strtoul_l.c: Likewise. * sysdeps/generic/strtoull_l.c: Likewise. * sysdeps/generic/wcstol_l.c: Likewise. * sysdeps/generic/wcstoll_l.c: Likewise. * sysdeps/generic/wcstoul_l.c: Likewise. * sysdeps/generic/wcstoull_l.c: Likewise. * sysdeps/ieee754/ldbl-128/strtold.c: Removed. * sysdeps/ieee754/ldbl-128/strtold_l.c: New file. * sysdeps/ieee754/ldbl-96/strtold.c: Removed. * sysdeps/ieee754/ldbl-96/strtold_l.c: New file. * sysdeps/m68k/strtold.c: Removed. * sysdeps/m68k/strtold_l.c: New file. * time/strftime.c: Move real code to strftime_l.c. Add wrapper. * time/strftime_l.c: Add real implementation. * time/strptime.c: Move real code to strptime_l.c. Add wrapper. * time/strptime_l.c: Add real implementation. * time/wcsftime.c: Simplify since only wrappers are defined in strftime.c. * time/wcsftime_l.c: Include strftime_l.c. * wcsmbs/wcscoll.c: Simplify since the file is not used by wcscoll_l.c anymore. * wcsmbs/wcscoll_l.c: Include strcoll_l.c. * wcsmbs/wcsxfrm.c: Simplify since the file is not used by wcsxfrm_l.c anymore. * wcsmbs/wcsxfrm_l.c: Include strxfrm_l.c. * wcsmbs/wcstod.c: Prepare to include new strtod.c. * wcsmbs/wcstod_l.c: Include strtod_l.c. * wcsmbs/wcstof.c: Prepare to include new strtof.c. * wcsmbs/wcstof_l.c: Include strtof_l.c. * wcsmbs/wcstold.c: Prepare to include new strtold.c. * wcsmbs/wcstold_l.c: Include strtold_l.c. * locale/uselocale.c: Use _NL_CURRENT_LOCALE instead of __libc_tsd_get. * sysdeps/generic/strcasecmp.c: Optimize a bit. It's better to get a reference to the current locale and then use the _l functions. * sysdeps/generic/strncase.c: Likewise.
Diffstat (limited to 'time/strftime.c')
-rw-r--r--time/strftime.c1421
1 files changed, 6 insertions, 1415 deletions
diff --git a/time/strftime.c b/time/strftime.c
index 04250317e3..5a4917e352 100644
--- a/time/strftime.c
+++ b/time/strftime.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-1999, 2000, 2001, 2002, 2003
+/* Copyright (C) 1991-1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -17,1422 +17,13 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <time.h>
+#include <locale/localeinfo.h>
-#ifdef _LIBC
-# define HAVE_LIMITS_H 1
-# define HAVE_MBLEN 1
-# define HAVE_MBRLEN 1
-# define HAVE_STRUCT_ERA_ENTRY 1
-# define HAVE_TM_GMTOFF 1
-# define HAVE_TM_ZONE 1
-# define HAVE_TZNAME 1
-# define HAVE_TZSET 1
-# define MULTIBYTE_IS_FORMAT_SAFE 1
-# define STDC_HEADERS 1
-# include "../locale/localeinfo.h"
-#endif
-#if defined emacs && !defined HAVE_BCOPY
-# define HAVE_MEMCPY 1
-#endif
-
-#include <ctype.h>
-#include <sys/types.h> /* Some systems define `time_t' here. */
-
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-#if HAVE_TZNAME
-extern char *tzname[];
-#endif
-
-/* Do multibyte processing if multibytes are supported, unless
- multibyte sequences are safe in formats. Multibyte sequences are
- safe if they cannot contain byte sequences that look like format
- conversion specifications. The GNU C Library uses UTF8 multibyte
- encoding, which is safe for formats, but strftime.c can be used
- with other C libraries that use unsafe encodings. */
-#define DO_MULTIBYTE (HAVE_MBLEN && ! MULTIBYTE_IS_FORMAT_SAFE)
-
-#if DO_MULTIBYTE
-# if HAVE_MBRLEN
-# include <wchar.h>
-# else
- /* Simulate mbrlen with mblen as best we can. */
-# define mbstate_t int
-# define mbrlen(s, n, ps) mblen (s, n)
-# define mbsinit(ps) (*(ps) == 0)
-# endif
- static const mbstate_t mbstate_zero;
-#endif
-
-#if HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#if STDC_HEADERS
-# include <stddef.h>
-# include <stdlib.h>
-# include <string.h>
-#else
-# ifndef HAVE_MEMCPY
-# define memcpy(d, s, n) bcopy ((s), (d), (n))
-# endif
-#endif
-
-#ifdef COMPILE_WIDE
-# include <endian.h>
-# define CHAR_T wchar_t
-# define UCHAR_T unsigned int
-# 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)
-
-#else
-# define CHAR_T char
-# define UCHAR_T unsigned char
-# define L_(Str) Str
-# define NLW(Sym) Sym
-
-# if !defined STDC_HEADERS && !defined HAVE_MEMCPY
-# define MEMCPY(d, s, n) bcopy ((s), (d), (n))
-# else
-# define MEMCPY(d, s, n) memcpy ((d), (s), (n))
-# endif
-# define STRLEN(s) strlen (s)
-
-# ifdef _LIBC
-# define MEMPCPY(d, s, n) __mempcpy (d, s, n)
-# else
-# ifndef HAVE_MEMPCPY
-# define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
-# endif
-# endif
-#endif
-
-#ifndef __P
-# if defined __GNUC__ || (defined __STDC__ && __STDC__)
-# define __P(args) args
-# else
-# define __P(args) ()
-# endif /* GCC. */
-#endif /* Not __P. */
-
-#ifndef PTR
-# ifdef __STDC__
-# define PTR void *
-# else
-# define PTR char *
-# endif
-#endif
-
-#ifndef CHAR_BIT
-# define CHAR_BIT 8
-#endif
-
-#ifndef NULL
-# define NULL 0
-#endif
-
-#define TYPE_SIGNED(t) ((t) -1 < 0)
-
-/* Bound on length of the string representing an integer value of type t.
- Subtract one for the sign bit if t is signed;
- 302 / 1000 is log10 (2) rounded up;
- add one for integer division truncation;
- add one more for a minus sign if t is signed. */
-#define INT_STRLEN_BOUND(t) \
- ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 + 1 + TYPE_SIGNED (t))
-
-#define TM_YEAR_BASE 1900
-
-#ifndef __isleap
-/* Nonzero if YEAR is a leap year (every 4 years,
- except every 100th isn't, and every 400th is). */
-# define __isleap(year) \
- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-#endif
-
-
-#ifdef _LIBC
-# define tzname __tzname
-# define tzset __tzset
-#endif
-
-#if !HAVE_TM_GMTOFF
-/* Portable standalone applications should supply a "time_r.h" that
- declares a POSIX-compliant localtime_r, for the benefit of older
- implementations that lack localtime_r or have a nonstandard one.
- Similarly for gmtime_r. See the gnulib time_r module for one way
- to implement this. */
-# include "time_r.h"
-# undef __gmtime_r
-# undef __localtime_r
-# define __gmtime_r gmtime_r
-# define __localtime_r localtime_r
-#endif
-
-
-#if !defined memset && !defined HAVE_MEMSET && !defined _LIBC
-/* Some systems lack the `memset' function and we don't want to
- introduce additional dependencies. */
-/* The SGI compiler reportedly barfs on the trailing null
- if we use a string constant as the initializer. 28 June 1997, rms. */
-static const CHAR_T spaces[16] = /* " " */
-{
- L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
- L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
-};
-static const CHAR_T zeroes[16] = /* "0000000000000000" */
-{
- L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),
- L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0'),L_('0')
-};
-
-# define memset_space(P, Len) \
- do { \
- int _len = (Len); \
- \
- do \
- { \
- int _this = _len > 16 ? 16 : _len; \
- (P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T)); \
- _len -= _this; \
- } \
- while (_len > 0); \
- } while (0)
-
-# define memset_zero(P, Len) \
- do { \
- int _len = (Len); \
- \
- do \
- { \
- int _this = _len > 16 ? 16 : _len; \
- (P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T)); \
- _len -= _this; \
- } \
- while (_len > 0); \
- } while (0)
-#else
-# ifdef COMPILE_WIDE
-# define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
-# define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
-# else
-# define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
-# define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
-# endif
-#endif
-
-#define add(n, f) \
- do \
- { \
- int _n = (n); \
- int _delta = width - _n; \
- int _incr = _n + (_delta > 0 ? _delta : 0); \
- if ((size_t) _incr >= maxsize - i) \
- return 0; \
- if (p) \
- { \
- if (_delta > 0) \
- { \
- if (pad == L_('0')) \
- memset_zero (p, _delta); \
- else \
- memset_space (p, _delta); \
- } \
- f; \
- p += _n; \
- } \
- i += _incr; \
- } while (0)
-
-#define cpy(n, s) \
- add ((n), \
- if (to_lowcase) \
- memcpy_lowcase (p, (s), _n LOCALE_ARG); \
- else if (to_uppcase) \
- memcpy_uppcase (p, (s), _n LOCALE_ARG); \
- else \
- MEMCPY ((PTR) p, (const PTR) (s), _n))
-
-#ifdef COMPILE_WIDE
-# ifndef USE_IN_EXTENDED_LOCALE_MODEL
-# undef __mbsrtowcs_l
-# define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
-# endif
-# define widen(os, ws, l) \
- { \
- mbstate_t __st; \
- const char *__s = os; \
- memset (&__st, '\0', sizeof (__st)); \
- l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
- ws = alloca ((l + 1) * sizeof (wchar_t)); \
- (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
- }
-#endif
-
-
-#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
-/* We use this code also for the extended locale handling where the
- function gets as an additional argument the locale which has to be
- used. To access the values we have to redefine the _NL_CURRENT
- macro. */
-# define strftime __strftime_l
-# define wcsftime __wcsftime_l
-# undef _NL_CURRENT
-# define _NL_CURRENT(category, item) \
- (current->values[_NL_ITEM_INDEX (item)].string)
-# define LOCALE_PARAM , loc
-# define LOCALE_ARG , loc
-# define LOCALE_PARAM_DECL __locale_t loc;
-# define LOCALE_PARAM_PROTO , __locale_t loc
-# define HELPER_LOCALE_ARG , current
-#else
-# define LOCALE_PARAM
-# define LOCALE_PARAM_PROTO
-# define LOCALE_ARG
-# define LOCALE_PARAM_DECL
-# ifdef _LIBC
-# define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
-# else
-# define HELPER_LOCALE_ARG
-# endif
-#endif
-
-#ifdef COMPILE_WIDE
-# ifdef USE_IN_EXTENDED_LOCALE_MODEL
-# define TOUPPER(Ch, L) __towupper_l (Ch, L)
-# define TOLOWER(Ch, L) __towlower_l (Ch, L)
-# else
-# define TOUPPER(Ch, L) towupper (Ch)
-# define TOLOWER(Ch, L) towlower (Ch)
-# endif
-#else
-# ifdef _LIBC
-# ifdef USE_IN_EXTENDED_LOCALE_MODEL
-# define TOUPPER(Ch, L) __toupper_l (Ch, L)
-# define TOLOWER(Ch, L) __tolower_l (Ch, L)
-# else
-# define TOUPPER(Ch, L) toupper (Ch)
-# define TOLOWER(Ch, L) tolower (Ch)
-# endif
-# else
-# define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
-# define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
-# endif
-#endif
-/* We don't use `isdigit' here since the locale dependent
- interpretation is not what we want here. We only need to accept
- the arabic digits in the ASCII range. One day there is perhaps a
- more reliable way to accept other sets of digits. */
-#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
-
-static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
- size_t len LOCALE_PARAM_PROTO));
-
-static CHAR_T *
-memcpy_lowcase (dest, src, len LOCALE_PARAM)
- CHAR_T *dest;
- const CHAR_T *src;
- size_t len;
- LOCALE_PARAM_DECL
-{
- while (len-- > 0)
- dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
- return dest;
-}
-
-static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
- size_t len LOCALE_PARAM_PROTO));
-
-static CHAR_T *
-memcpy_uppcase (dest, src, len LOCALE_PARAM)
- CHAR_T *dest;
- const CHAR_T *src;
- size_t len;
- LOCALE_PARAM_DECL
-{
- while (len-- > 0)
- dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
- return dest;
-}
-
-
-#if ! HAVE_TM_GMTOFF
-/* Yield the difference between *A and *B,
- measured in seconds, ignoring leap seconds. */
-# define tm_diff ftime_tm_diff
-static int tm_diff __P ((const struct tm *, const struct tm *));
-static int
-tm_diff (a, b)
- const struct tm *a;
- const struct tm *b;
-{
- /* Compute intervening leap days correctly even if year is negative.
- Take care to avoid int overflow in leap day calculations,
- but it's OK to assume that A and B are close to each other. */
- int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
- int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
- int a100 = a4 / 25 - (a4 % 25 < 0);
- int b100 = b4 / 25 - (b4 % 25 < 0);
- int a400 = a100 >> 2;
- int b400 = b100 >> 2;
- int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
- int years = a->tm_year - b->tm_year;
- int days = (365 * years + intervening_leap_days
- + (a->tm_yday - b->tm_yday));
- return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
- + (a->tm_min - b->tm_min))
- + (a->tm_sec - b->tm_sec));
-}
-#endif /* ! HAVE_TM_GMTOFF */
-
-
-
-/* The number of days from the first day of the first ISO week of this
- year to the year day YDAY with week day WDAY. ISO weeks start on
- Monday; the first ISO week has the year's first Thursday. YDAY may
- be as small as YDAY_MINIMUM. */
-#define ISO_WEEK_START_WDAY 1 /* Monday */
-#define ISO_WEEK1_WDAY 4 /* Thursday */
-#define YDAY_MINIMUM (-366)
-static int iso_week_days __P ((int, int));
-#ifdef __GNUC__
-__inline__
-#endif
-static int
-iso_week_days (yday, wday)
- int yday;
- int wday;
-{
- /* Add enough to the first operand of % to make it nonnegative. */
- int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
- return (yday
- - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
- + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
-}
-
-
-#if !(defined _NL_CURRENT || HAVE_STRFTIME)
-static CHAR_T const weekday_name[][10] =
- {
- L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
- L_("Thursday"), L_("Friday"), L_("Saturday")
- };
-static CHAR_T const month_name[][10] =
- {
- L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
- L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
- L_("November"), L_("December")
- };
-#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
-#else
-# ifdef COMPILE_WIDE
-# define my_strftime wcsftime
-# define nl_get_alt_digit _nl_get_walt_digit
-# else
-# define my_strftime strftime
-# define nl_get_alt_digit _nl_get_alt_digit
-# endif
-# define ut_argument
-# define ut_argument_spec
-# define ut_argument_spec_iso
-/* We don't have this information in general. */
-# define ut 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));
- size_t
- my_strftime (s, maxsize, format, tp ut_argument)
- CHAR_T *s;
- size_t maxsize;
- const CHAR_T *format;
- const struct tm *tp;
- ut_argument_spec
- {
- struct tm tmcopy;
- tmcopy = *tp;
- return _strftime_copytm (s, maxsize, format, &tmcopy ut_argument);
- }
-# undef my_strftime
-# define my_strftime _strftime_copytm
-#endif
-
-
-/* Write information from TP into S according to the format
- string FORMAT, writing no more that MAXSIZE characters
- (including the terminating '\0') and returning number of
- characters written. If S is NULL, nothing will be written
- 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 LOCALE_PARAM)
- CHAR_T *s;
- size_t maxsize;
- const CHAR_T *format;
- const struct tm *tp;
- ut_argument_spec
- LOCALE_PARAM_DECL
-{
-#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
- struct locale_data *const current = loc->__locales[LC_TIME];
-#endif
-
- int hour12 = tp->tm_hour;
-#ifdef _NL_CURRENT
- /* We cannot make the following values variables since we must delay
- the evaluation of these values until really needed since some
- expressions might not be valid in every situation. The `struct tm'
- might be generated by a strptime() call that initialized
- only a few elements. Dereference the pointers only if the format
- requires this. Then it is ok to fail if the pointers are invalid. */
-# define a_wkday \
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
-# define f_wkday \
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
-# define a_month \
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
-# define f_month \
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
-# define ampm \
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
- ? NLW(PM_STR) : NLW(AM_STR)))
-
-# define aw_len STRLEN (a_wkday)
-# define am_len STRLEN (a_month)
-# define ap_len STRLEN (ampm)
-#else
-# if !HAVE_STRFTIME
-# define f_wkday (weekday_name[tp->tm_wday])
-# define f_month (month_name[tp->tm_mon])
-# define a_wkday f_wkday
-# define a_month f_month
-# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
-
- size_t aw_len = 3;
- size_t am_len = 3;
- size_t ap_len = 2;
-# endif
-#endif
- const char *zone;
- 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
- /* The POSIX test suite assumes that setting
- the environment variable TZ to a new value before calling strftime()
- will influence the result (the %Z format) even if the information in
- TP is computed with a totally different time zone.
- This is bogus: though POSIX allows bad behavior like this,
- POSIX does not require it. Do the right thing instead. */
- zone = (const char *) tp->tm_zone;
-#endif
-#if HAVE_TZNAME
- if (ut)
- {
- if (! (zone && *zone))
- zone = "GMT";
- }
- else
- {
- /* POSIX.1 requires that local time zone information is used as
- though strftime called tzset. */
-# if HAVE_TZSET
- tzset ();
-# endif
- }
-#endif
-
- if (hour12 > 12)
- hour12 -= 12;
- else
- if (hour12 == 0)
- hour12 = 12;
-
- for (f = format; *f != '\0'; ++f)
- {
- int pad = 0; /* Padding for number ('-', '_', or 0). */
- int modifier; /* Field modifier ('E', 'O', or 0). */
- int digits; /* Max digits for numeric format. */
- int number_value; /* Numeric value to be printed. */
- int negative_number; /* 1 if the number is negative. */
- const CHAR_T *subfmt;
- CHAR_T *bufp;
- CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
- ? INT_STRLEN_BOUND (time_t)
- : INT_STRLEN_BOUND (int))];
- int width = -1;
- int to_lowcase = 0;
- int to_uppcase = 0;
- int change_case = 0;
- int format_char;
-
-#if DO_MULTIBYTE && !defined COMPILE_WIDE
- switch (*f)
- {
- case L_('%'):
- break;
-
- case L_('\b'): case L_('\t'): case L_('\n'):
- case L_('\v'): case L_('\f'): case L_('\r'):
- case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
- case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
- case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
- case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
- case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
- case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
- case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
- case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
- case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
- case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
- case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
- case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
- case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
- case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
- case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
- case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
- case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
- case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
- case L_('~'):
- /* The C Standard requires these 98 characters (plus '%') to
- be in the basic execution character set. None of these
- characters can start a multibyte sequence, so they need
- not be analyzed further. */
- add (1, *p = *f);
- continue;
-
- default:
- /* Copy this multibyte sequence until we reach its end, find
- an error, or come back to the initial shift state. */
- {
- 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, fsize - len, &mbstate);
-
- if (bytes == 0)
- break;
-
- if (bytes == (size_t) -2)
- {
- len += strlen (f + len);
- break;
- }
-
- if (bytes == (size_t) -1)
- {
- len++;
- break;
- }
-
- len += bytes;
- }
- while (! mbsinit (&mbstate));