Blame lib/strftime.c

Packit Service fdd496
/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
Packit Service fdd496
   This file is part of the GNU C Library.
Packit Service fdd496
Packit Service fdd496
   The GNU C Library is free software; you can redistribute it and/or
Packit Service fdd496
   modify it under the terms of the GNU General Public
Packit Service fdd496
   License as published by the Free Software Foundation; either
Packit Service fdd496
   version 3 of the License, or (at your option) any later version.
Packit Service fdd496
Packit Service fdd496
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service fdd496
   General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public
Packit Service fdd496
   License along with the GNU C Library; if not, see
Packit Service fdd496
   <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
# define USE_IN_EXTENDED_LOCALE_MODEL 1
Packit Service fdd496
# define HAVE_STRUCT_ERA_ENTRY 1
Packit Service fdd496
# define HAVE_TM_GMTOFF 1
Packit Service fdd496
# define HAVE_TM_ZONE 1
Packit Service fdd496
# define HAVE_TZNAME 1
Packit Service fdd496
# define HAVE_TZSET 1
Packit Service fdd496
# include "../locale/localeinfo.h"
Packit Service fdd496
#else
Packit Service fdd496
# include <config.h>
Packit Service fdd496
# if FPRINTFTIME
Packit Service fdd496
#  include "fprintftime.h"
Packit Service fdd496
# else
Packit Service fdd496
#  include "strftime.h"
Packit Service fdd496
# endif
Packit Service fdd496
# include "time-internal.h"
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#include <ctype.h>
Packit Service fdd496
#include <time.h>
Packit Service fdd496
Packit Service fdd496
#if HAVE_TZNAME && !HAVE_DECL_TZNAME
Packit Service fdd496
extern char *tzname[];
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* Do multibyte processing if multibyte encodings are supported, unless
Packit Service fdd496
   multibyte sequences are safe in formats.  Multibyte sequences are
Packit Service fdd496
   safe if they cannot contain byte sequences that look like format
Packit Service fdd496
   conversion specifications.  The multibyte encodings used by the
Packit Service fdd496
   C library on the various platforms (UTF-8, GB2312, GBK, CP936,
Packit Service fdd496
   GB18030, EUC-TW, BIG5, BIG5-HKSCS, CP950, EUC-JP, EUC-KR, CP949,
Packit Service fdd496
   SHIFT_JIS, CP932, JOHAB) are safe for formats, because the byte '%'
Packit Service fdd496
   cannot occur in a multibyte character except in the first byte.
Packit Service fdd496
Packit Service fdd496
   The DEC-HANYU encoding used on OSF/1 is not safe for formats, but
Packit Service fdd496
   this encoding has never been seen in real-life use, so we ignore
Packit Service fdd496
   it.  */
Packit Service fdd496
#if !(defined __osf__ && 0)
Packit Service fdd496
# define MULTIBYTE_IS_FORMAT_SAFE 1
Packit Service fdd496
#endif
Packit Service fdd496
#define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE)
Packit Service fdd496
Packit Service fdd496
#if DO_MULTIBYTE
Packit Service fdd496
# include <wchar.h>
Packit Service fdd496
  static const mbstate_t mbstate_zero;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#include <limits.h>
Packit Service fdd496
#include <stddef.h>
Packit Service fdd496
#include <stdlib.h>
Packit Service fdd496
#include <string.h>
Packit Service fdd496
#include <stdbool.h>
Packit Service fdd496
Packit Service fdd496
#ifndef FALLTHROUGH
Packit Service fdd496
# if __GNUC__ < 7
Packit Service fdd496
#  define FALLTHROUGH ((void) 0)
Packit Service fdd496
# else
Packit Service fdd496
#  define FALLTHROUGH __attribute__ ((__fallthrough__))
Packit Service fdd496
# endif
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#ifdef COMPILE_WIDE
Packit Service fdd496
# include <endian.h>
Packit Service fdd496
# define CHAR_T wchar_t
Packit Service fdd496
# define UCHAR_T unsigned int
Packit Service fdd496
# define L_(Str) L##Str
Packit Service fdd496
# define NLW(Sym) _NL_W##Sym
Packit Service fdd496
Packit Service fdd496
# define MEMCPY(d, s, n) __wmemcpy (d, s, n)
Packit Service fdd496
# define STRLEN(s) __wcslen (s)
Packit Service fdd496
Packit Service fdd496
#else
Packit Service fdd496
# define CHAR_T char
Packit Service fdd496
# define UCHAR_T unsigned char
Packit Service fdd496
# define L_(Str) Str
Packit Service fdd496
# define NLW(Sym) Sym
Packit Service fdd496
Packit Service fdd496
# define MEMCPY(d, s, n) memcpy (d, s, n)
Packit Service fdd496
# define STRLEN(s) strlen (s)
Packit Service fdd496
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* Shift A right by B bits portably, by dividing A by 2**B and
Packit Service fdd496
   truncating towards minus infinity.  A and B should be free of side
Packit Service fdd496
   effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
Packit Service fdd496
   INT_BITS is the number of useful bits in an int.  GNU code can
Packit Service fdd496
   assume that INT_BITS is at least 32.
Packit Service fdd496
Packit Service fdd496
   ISO C99 says that A >> B is implementation-defined if A < 0.  Some
Packit Service fdd496
   implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
Packit Service fdd496
   right in the usual way when A < 0, so SHR falls back on division if
Packit Service fdd496
   ordinary A >> B doesn't seem to be the usual signed shift.  */
Packit Service fdd496
#define SHR(a, b)       \
Packit Service fdd496
  (-1 >> 1 == -1        \
Packit Service fdd496
   ? (a) >> (b)         \
Packit Service fdd496
   : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
Packit Service fdd496
Packit Service fdd496
/* Bound on length of the string representing an integer type or expression T.
Packit Service fdd496
   Subtract 1 for the sign bit if t is signed; log10 (2.0) < 146/485;
Packit Service fdd496
   add 1 for integer division truncation; add 1 more for a minus sign
Packit Service fdd496
   if needed.  */
Packit Service fdd496
#define INT_STRLEN_BOUND(t) \
Packit Service fdd496
  ((sizeof (t) * CHAR_BIT - 1) * 146 / 485 + 2)
Packit Service fdd496
Packit Service fdd496
#define TM_YEAR_BASE 1900
Packit Service fdd496
Packit Service fdd496
#ifndef __isleap
Packit Service fdd496
/* Nonzero if YEAR is a leap year (every 4 years,
Packit Service fdd496
   except every 100th isn't, and every 400th is).  */
Packit Service fdd496
# define __isleap(year) \
Packit Service fdd496
  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
# define mktime_z(tz, tm) mktime (tm)
Packit Service fdd496
# define tzname __tzname
Packit Service fdd496
# define tzset __tzset
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#ifndef FPRINTFTIME
Packit Service fdd496
# define FPRINTFTIME 0
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if FPRINTFTIME
Packit Service fdd496
# define STREAM_OR_CHAR_T FILE
Packit Service fdd496
# define STRFTIME_ARG(x) /* empty */
Packit Service fdd496
#else
Packit Service fdd496
# define STREAM_OR_CHAR_T CHAR_T
Packit Service fdd496
# define STRFTIME_ARG(x) x,
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if FPRINTFTIME
Packit Service fdd496
# define memset_byte(P, Len, Byte) \
Packit Service fdd496
  do { size_t _i; for (_i = 0; _i < Len; _i++) fputc (Byte, P); } while (0)
Packit Service fdd496
# define memset_space(P, Len) memset_byte (P, Len, ' ')
Packit Service fdd496
# define memset_zero(P, Len) memset_byte (P, Len, '0')
Packit Service fdd496
#elif defined COMPILE_WIDE
Packit Service fdd496
# define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len))
Packit Service fdd496
# define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len))
Packit Service fdd496
#else
Packit Service fdd496
# define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
Packit Service fdd496
# define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if FPRINTFTIME
Packit Service fdd496
# define advance(P, N)
Packit Service fdd496
#else
Packit Service fdd496
# define advance(P, N) ((P) += (N))
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#define add(n, f)                                                             \
Packit Service fdd496
  do                                                                          \
Packit Service fdd496
    {                                                                         \
Packit Service fdd496
      size_t _n = (n);                                                        \
Packit Service fdd496
      size_t _w = (width < 0 ? 0 : width);                                    \
Packit Service fdd496
      size_t _incr = _n < _w ? _w : _n;                                       \
Packit Service fdd496
      if (_incr >= maxsize - i)                                               \
Packit Service fdd496
        return 0;                                                             \
Packit Service fdd496
      if (p)                                                                  \
Packit Service fdd496
        {                                                                     \
Packit Service fdd496
          if (digits == 0 && _n < _w)                                         \
Packit Service fdd496
            {                                                                 \
Packit Service fdd496
              size_t _delta = width - _n;                                     \
Packit Service fdd496
              if (pad == L_('0'))                                             \
Packit Service fdd496
                memset_zero (p, _delta);                                      \
Packit Service fdd496
              else                                                            \
Packit Service fdd496
                memset_space (p, _delta);                                     \
Packit Service fdd496
            }                                                                 \
Packit Service fdd496
          f;                                                                  \
Packit Service fdd496
          advance (p, _n);                                                    \
Packit Service fdd496
        }                                                                     \
Packit Service fdd496
      i += _incr;                                                             \
Packit Service fdd496
    } while (0)
Packit Service fdd496
Packit Service fdd496
#if FPRINTFTIME
Packit Service fdd496
# define add1(C) add (1, fputc (C, p))
Packit Service fdd496
#else
Packit Service fdd496
# define add1(C) add (1, *p = C)
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if FPRINTFTIME
Packit Service fdd496
# define cpy(n, s) \
Packit Service fdd496
    add ((n),                                                                 \
Packit Service fdd496
     do                                                                       \
Packit Service fdd496
       {                                                                      \
Packit Service fdd496
         if (to_lowcase)                                                      \
Packit Service fdd496
           fwrite_lowcase (p, (s), _n);                                       \
Packit Service fdd496
         else if (to_uppcase)                                                 \
Packit Service fdd496
           fwrite_uppcase (p, (s), _n);                                       \
Packit Service fdd496
         else                                                                 \
Packit Service fdd496
           {                                                                  \
Packit Service fdd496
             /* Ignore the value of fwrite.  The caller can determine whether \
Packit Service fdd496
                an error occurred by inspecting ferror (P).  All known fwrite \
Packit Service fdd496
                implementations set the stream's error indicator when they    \
Packit Service fdd496
                fail due to ENOMEM etc., even though C11 and POSIX.1-2008 do  \
Packit Service fdd496
                not require this.  */                                         \
Packit Service fdd496
             fwrite (s, _n, 1, p);                                            \
Packit Service fdd496
           }                                                                  \
Packit Service fdd496
       }                                                                      \
Packit Service fdd496
     while (0)                                                                \
Packit Service fdd496
    )
Packit Service fdd496
#else
Packit Service fdd496
# define cpy(n, s)                                                            \
Packit Service fdd496
    add ((n),                                                                 \
Packit Service fdd496
         if (to_lowcase)                                                      \
Packit Service fdd496
           memcpy_lowcase (p, (s), _n LOCALE_ARG);                            \
Packit Service fdd496
         else if (to_uppcase)                                                 \
Packit Service fdd496
           memcpy_uppcase (p, (s), _n LOCALE_ARG);                            \
Packit Service fdd496
         else                                                                 \
Packit Service fdd496
           MEMCPY ((void *) p, (void const *) (s), _n))
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#ifdef COMPILE_WIDE
Packit Service fdd496
# ifndef USE_IN_EXTENDED_LOCALE_MODEL
Packit Service fdd496
#  undef __mbsrtowcs_l
Packit Service fdd496
#  define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
Packit Service fdd496
# endif
Packit Service fdd496
# define widen(os, ws, l) \
Packit Service fdd496
  {                                                                           \
Packit Service fdd496
    mbstate_t __st;                                                           \
Packit Service fdd496
    const char *__s = os;                                                     \
Packit Service fdd496
    memset (&__st, '\0', sizeof (__st));                                      \
Packit Service fdd496
    l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc);                            \
Packit Service fdd496
    ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t));                     \
Packit Service fdd496
    (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc);                           \
Packit Service fdd496
  }
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
Packit Service fdd496
/* We use this code also for the extended locale handling where the
Packit Service fdd496
   function gets as an additional argument the locale which has to be
Packit Service fdd496
   used.  To access the values we have to redefine the _NL_CURRENT
Packit Service fdd496
   macro.  */
Packit Service fdd496
# define strftime               __strftime_l
Packit Service fdd496
# define wcsftime               __wcsftime_l
Packit Service fdd496
# undef _NL_CURRENT
Packit Service fdd496
# define _NL_CURRENT(category, item) \
Packit Service fdd496
  (current->values[_NL_ITEM_INDEX (item)].string)
Packit Service fdd496
# define LOCALE_PARAM , __locale_t loc
Packit Service fdd496
# define LOCALE_ARG , loc
Packit Service fdd496
# define HELPER_LOCALE_ARG  , current
Packit Service fdd496
#else
Packit Service fdd496
# define LOCALE_PARAM
Packit Service fdd496
# define LOCALE_ARG
Packit Service fdd496
# ifdef _LIBC
Packit Service fdd496
#  define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME)
Packit Service fdd496
# else
Packit Service fdd496
#  define HELPER_LOCALE_ARG
Packit Service fdd496
# endif
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#ifdef COMPILE_WIDE
Packit Service fdd496
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
Packit Service fdd496
#  define TOUPPER(Ch, L) __towupper_l (Ch, L)
Packit Service fdd496
#  define TOLOWER(Ch, L) __towlower_l (Ch, L)
Packit Service fdd496
# else
Packit Service fdd496
#  define TOUPPER(Ch, L) towupper (Ch)
Packit Service fdd496
#  define TOLOWER(Ch, L) towlower (Ch)
Packit Service fdd496
# endif
Packit Service fdd496
#else
Packit Service fdd496
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
Packit Service fdd496
#  define TOUPPER(Ch, L) __toupper_l (Ch, L)
Packit Service fdd496
#  define TOLOWER(Ch, L) __tolower_l (Ch, L)
Packit Service fdd496
# else
Packit Service fdd496
#  define TOUPPER(Ch, L) toupper (Ch)
Packit Service fdd496
#  define TOLOWER(Ch, L) tolower (Ch)
Packit Service fdd496
# endif
Packit Service fdd496
#endif
Packit Service fdd496
/* We don't use 'isdigit' here since the locale dependent
Packit Service fdd496
   interpretation is not what we want here.  We only need to accept
Packit Service fdd496
   the arabic digits in the ASCII range.  One day there is perhaps a
Packit Service fdd496
   more reliable way to accept other sets of digits.  */
Packit Service fdd496
#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
Packit Service fdd496
Packit Service fdd496
#if FPRINTFTIME
Packit Service fdd496
static void
Packit Service fdd496
fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len)
Packit Service fdd496
{
Packit Service fdd496
  while (len-- > 0)
Packit Service fdd496
    {
Packit Service fdd496
      fputc (TOLOWER ((UCHAR_T) *src, loc), fp);
Packit Service fdd496
      ++src;
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
static void
Packit Service fdd496
fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len)
Packit Service fdd496
{
Packit Service fdd496
  while (len-- > 0)
Packit Service fdd496
    {
Packit Service fdd496
      fputc (TOUPPER ((UCHAR_T) *src, loc), fp);
Packit Service fdd496
      ++src;
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496
#else
Packit Service fdd496
static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src,
Packit Service fdd496
                               size_t len LOCALE_PARAM);
Packit Service fdd496
Packit Service fdd496
static CHAR_T *
Packit Service fdd496
memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
Packit Service fdd496
{
Packit Service fdd496
  while (len-- > 0)
Packit Service fdd496
    dest[len] = TOLOWER ((UCHAR_T) src[len], loc);
Packit Service fdd496
  return dest;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src,
Packit Service fdd496
                               size_t len LOCALE_PARAM);
Packit Service fdd496
Packit Service fdd496
static CHAR_T *
Packit Service fdd496
memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM)
Packit Service fdd496
{
Packit Service fdd496
  while (len-- > 0)
Packit Service fdd496
    dest[len] = TOUPPER ((UCHAR_T) src[len], loc);
Packit Service fdd496
  return dest;
Packit Service fdd496
}
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
#if ! HAVE_TM_GMTOFF
Packit Service fdd496
/* Yield the difference between *A and *B,
Packit Service fdd496
   measured in seconds, ignoring leap seconds.  */
Packit Service fdd496
# define tm_diff ftime_tm_diff
Packit Service fdd496
static int tm_diff (const struct tm *, const struct tm *);
Packit Service fdd496
static int
Packit Service fdd496
tm_diff (const struct tm *a, const struct tm *b)
Packit Service fdd496
{
Packit Service fdd496
  /* Compute intervening leap days correctly even if year is negative.
Packit Service fdd496
     Take care to avoid int overflow in leap day calculations,
Packit Service fdd496
     but it's OK to assume that A and B are close to each other.  */
Packit Service fdd496
  int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
Packit Service fdd496
  int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
Packit Service fdd496
  int a100 = a4 / 25 - (a4 % 25 < 0);
Packit Service fdd496
  int b100 = b4 / 25 - (b4 % 25 < 0);
Packit Service fdd496
  int a400 = SHR (a100, 2);
Packit Service fdd496
  int b400 = SHR (b100, 2);
Packit Service fdd496
  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
Packit Service fdd496
  int years = a->tm_year - b->tm_year;
Packit Service fdd496
  int days = (365 * years + intervening_leap_days
Packit Service fdd496
              + (a->tm_yday - b->tm_yday));
Packit Service fdd496
  return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
Packit Service fdd496
                + (a->tm_min - b->tm_min))
Packit Service fdd496
          + (a->tm_sec - b->tm_sec));
Packit Service fdd496
}
Packit Service fdd496
#endif /* ! HAVE_TM_GMTOFF */
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
/* The number of days from the first day of the first ISO week of this
Packit Service fdd496
   year to the year day YDAY with week day WDAY.  ISO weeks start on
Packit Service fdd496
   Monday; the first ISO week has the year's first Thursday.  YDAY may
Packit Service fdd496
   be as small as YDAY_MINIMUM.  */
Packit Service fdd496
#define ISO_WEEK_START_WDAY 1 /* Monday */
Packit Service fdd496
#define ISO_WEEK1_WDAY 4 /* Thursday */
Packit Service fdd496
#define YDAY_MINIMUM (-366)
Packit Service fdd496
static int iso_week_days (int, int);
Packit Service fdd496
#ifdef __GNUC__
Packit Service fdd496
__inline__
Packit Service fdd496
#endif
Packit Service fdd496
static int
Packit Service fdd496
iso_week_days (int yday, int wday)
Packit Service fdd496
{
Packit Service fdd496
  /* Add enough to the first operand of % to make it nonnegative.  */
Packit Service fdd496
  int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
Packit Service fdd496
  return (yday
Packit Service fdd496
          - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
Packit Service fdd496
          + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
/* When compiling this file, GNU applications can #define my_strftime
Packit Service fdd496
   to a symbol (typically nstrftime) to get an extended strftime with
Packit Service fdd496
   extra arguments TZ and NS.  */
Packit Service fdd496
Packit Service fdd496
#if FPRINTFTIME
Packit Service fdd496
# undef my_strftime
Packit Service fdd496
# define my_strftime fprintftime
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#ifdef my_strftime
Packit Service fdd496
# undef HAVE_TZSET
Packit Service fdd496
# define extra_args , tz, ns
Packit Service fdd496
# define extra_args_spec , timezone_t tz, int ns
Packit Service fdd496
#else
Packit Service fdd496
# if defined COMPILE_WIDE
Packit Service fdd496
#  define my_strftime wcsftime
Packit Service fdd496
#  define nl_get_alt_digit _nl_get_walt_digit
Packit Service fdd496
# else
Packit Service fdd496
#  define my_strftime strftime
Packit Service fdd496
#  define nl_get_alt_digit _nl_get_alt_digit
Packit Service fdd496
# endif
Packit Service fdd496
# define extra_args
Packit Service fdd496
# define extra_args_spec
Packit Service fdd496
/* We don't have this information in general.  */
Packit Service fdd496
# define tz 1
Packit Service fdd496
# define ns 0
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t)
Packit Service fdd496
                                   const CHAR_T *, const struct tm *,
Packit Service fdd496
                                   bool, bool *
Packit Service fdd496
                                   extra_args_spec LOCALE_PARAM);
Packit Service fdd496
Packit Service fdd496
/* Write information from TP into S according to the format
Packit Service fdd496
   string FORMAT, writing no more that MAXSIZE characters
Packit Service fdd496
   (including the terminating '\0') and returning number of
Packit Service fdd496
   characters written.  If S is NULL, nothing will be written
Packit Service fdd496
   anywhere, so to determine how many characters would be
Packit Service fdd496
   written, use NULL for S and (size_t) -1 for MAXSIZE.  */
Packit Service fdd496
size_t
Packit Service fdd496
my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
Packit Service fdd496
             const CHAR_T *format,
Packit Service fdd496
             const struct tm *tp extra_args_spec LOCALE_PARAM)
Packit Service fdd496
{
Packit Service fdd496
  bool tzset_called = false;
Packit Service fdd496
  return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp,
Packit Service fdd496
                              false, &tzset_called extra_args LOCALE_ARG);
Packit Service fdd496
}
Packit Service fdd496
#if defined _LIBC && ! FPRINTFTIME
Packit Service fdd496
libc_hidden_def (my_strftime)
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* Just like my_strftime, above, but with two more parameters.
Packit Service fdd496
   UPCASE indicate that the result should be converted to upper case,
Packit Service fdd496
   and *TZSET_CALLED indicates whether tzset has been called here.  */
Packit Service fdd496
static size_t
Packit Service fdd496
__strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
Packit Service fdd496
                     const CHAR_T *format,
Packit Service fdd496
                     const struct tm *tp, bool upcase, bool *tzset_called
Packit Service fdd496
                     extra_args_spec LOCALE_PARAM)
Packit Service fdd496
{
Packit Service fdd496
#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
Packit Service fdd496
  struct __locale_data *const current = loc->__locales[LC_TIME];
Packit Service fdd496
#endif
Packit Service fdd496
#if FPRINTFTIME
Packit Service fdd496
  size_t maxsize = (size_t) -1;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
  int hour12 = tp->tm_hour;
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
  /* We cannot make the following values variables since we must delay
Packit Service fdd496
     the evaluation of these values until really needed since some
Packit Service fdd496
     expressions might not be valid in every situation.  The 'struct tm'
Packit Service fdd496
     might be generated by a strptime() call that initialized
Packit Service fdd496
     only a few elements.  Dereference the pointers only if the format
Packit Service fdd496
     requires this.  Then it is ok to fail if the pointers are invalid.  */
Packit Service fdd496
# define a_wkday \
Packit Service fdd496
  ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6                      \
Packit Service fdd496
                     ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
Packit Service fdd496
# define f_wkday \
Packit Service fdd496
  ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6                      \
Packit Service fdd496
                     ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
Packit Service fdd496
# define a_month \
Packit Service fdd496
  ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11                       \
Packit Service fdd496
                     ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
Packit Service fdd496
# define f_month \
Packit Service fdd496
  ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11                       \
Packit Service fdd496
                     ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
Packit Service fdd496
# define ampm \
Packit Service fdd496
  ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11                    \
Packit Service fdd496
                                 ? NLW(PM_STR) : NLW(AM_STR)))
Packit Service fdd496
Packit Service fdd496
# define aw_len STRLEN (a_wkday)
Packit Service fdd496
# define am_len STRLEN (a_month)
Packit Service fdd496
# define ap_len STRLEN (ampm)
Packit Service fdd496
#endif
Packit Service fdd496
#if HAVE_TZNAME
Packit Service fdd496
  char **tzname_vec = tzname;
Packit Service fdd496
#endif
Packit Service fdd496
  const char *zone;
Packit Service fdd496
  size_t i = 0;
Packit Service fdd496
  STREAM_OR_CHAR_T *p = s;
Packit Service fdd496
  const CHAR_T *f;
Packit Service fdd496
#if DO_MULTIBYTE && !defined COMPILE_WIDE
Packit Service fdd496
  const char *format_end = NULL;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if ! defined _LIBC && ! HAVE_RUN_TZSET_TEST
Packit Service fdd496
  /* Solaris 2.5.x and 2.6 tzset sometimes modify the storage returned
Packit Service fdd496
     by localtime.  On such systems, we must either use the tzset and
Packit Service fdd496
     localtime wrappers to work around the bug (which sets
Packit Service fdd496
     HAVE_RUN_TZSET_TEST) or make a copy of the structure.  */
Packit Service fdd496
  struct tm copy = *tp;
Packit Service fdd496
  tp = ©
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
  zone = NULL;
Packit Service fdd496
#if HAVE_TM_ZONE
Packit Service fdd496
  /* The POSIX test suite assumes that setting
Packit Service fdd496
     the environment variable TZ to a new value before calling strftime()
Packit Service fdd496
     will influence the result (the %Z format) even if the information in
Packit Service fdd496
     TP is computed with a totally different time zone.
Packit Service fdd496
     This is bogus: though POSIX allows bad behavior like this,
Packit Service fdd496
     POSIX does not require it.  Do the right thing instead.  */
Packit Service fdd496
  zone = (const char *) tp->tm_zone;
Packit Service fdd496
#endif
Packit Service fdd496
#if HAVE_TZNAME
Packit Service fdd496
  if (!tz)
Packit Service fdd496
    {
Packit Service fdd496
      if (! (zone && *zone))
Packit Service fdd496
        zone = "GMT";
Packit Service fdd496
    }
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
# if !HAVE_TM_ZONE
Packit Service fdd496
      /* Infer the zone name from *TZ instead of from TZNAME.  */
Packit Service fdd496
      tzname_vec = tz->tzname_copy;
Packit Service fdd496
# endif
Packit Service fdd496
    }
Packit Service fdd496
  /* The tzset() call might have changed the value.  */
Packit Service fdd496
  if (!(zone && *zone) && tp->tm_isdst >= 0)
Packit Service fdd496
    {
Packit Service fdd496
      /* POSIX.1 requires that local time zone information be used as
Packit Service fdd496
         though strftime called tzset.  */
Packit Service fdd496
# if HAVE_TZSET
Packit Service fdd496
      if (!*tzset_called)
Packit Service fdd496
        {
Packit Service fdd496
          tzset ();
Packit Service fdd496
          *tzset_called = true;
Packit Service fdd496
        }
Packit Service fdd496
# endif
Packit Service fdd496
      zone = tzname_vec[tp->tm_isdst != 0];
Packit Service fdd496
    }
Packit Service fdd496
#endif
Packit Service fdd496
  if (! zone)
Packit Service fdd496
    zone = "";
Packit Service fdd496
Packit Service fdd496
  if (hour12 > 12)
Packit Service fdd496
    hour12 -= 12;
Packit Service fdd496
  else
Packit Service fdd496
    if (hour12 == 0)
Packit Service fdd496
      hour12 = 12;
Packit Service fdd496
Packit Service fdd496
  for (f = format; *f != '\0'; ++f)
Packit Service fdd496
    {
Packit Service fdd496
      int pad = 0;              /* Padding for number ('-', '_', or 0).  */
Packit Service fdd496
      int modifier;             /* Field modifier ('E', 'O', or 0).  */
Packit Service fdd496
      int digits = 0;           /* Max digits for numeric format.  */
Packit Service fdd496
      int number_value;         /* Numeric value to be printed.  */
Packit Service fdd496
      unsigned int u_number_value; /* (unsigned int) number_value.  */
Packit Service fdd496
      bool negative_number;     /* The number is negative.  */
Packit Service fdd496
      bool always_output_a_sign; /* +/- should always be output.  */
Packit Service fdd496
      int tz_colon_mask;        /* Bitmask of where ':' should appear.  */
Packit Service fdd496
      const CHAR_T *subfmt;
Packit Service fdd496
      CHAR_T sign_char;
Packit Service fdd496
      CHAR_T *bufp;
Packit Service fdd496
      CHAR_T buf[1
Packit Service fdd496
                 + 2 /* for the two colons in a %::z or %:::z time zone */
Packit Service fdd496
                 + (sizeof (int) < sizeof (time_t)
Packit Service fdd496
                    ? INT_STRLEN_BOUND (time_t)
Packit Service fdd496
                    : INT_STRLEN_BOUND (int))];
Packit Service fdd496
      int width = -1;
Packit Service fdd496
      bool to_lowcase = false;
Packit Service fdd496
      bool to_uppcase = upcase;
Packit Service fdd496
      size_t colons;
Packit Service fdd496
      bool change_case = false;
Packit Service fdd496
      int format_char;
Packit Service fdd496
Packit Service fdd496
#if DO_MULTIBYTE && !defined COMPILE_WIDE
Packit Service fdd496
      switch (*f)
Packit Service fdd496
        {
Packit Service fdd496
        case L_('%'):
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_('\b'): case L_('\t'): case L_('\n'):
Packit Service fdd496
        case L_('\v'): case L_('\f'): case L_('\r'):
Packit Service fdd496
        case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
Packit Service fdd496
        case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
Packit Service fdd496
        case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
Packit Service fdd496
        case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
Packit Service fdd496
        case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
Packit Service fdd496
        case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
Packit Service fdd496
        case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
Packit Service fdd496
        case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
Packit Service fdd496
        case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
Packit Service fdd496
        case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
Packit Service fdd496
        case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
Packit Service fdd496
        case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
Packit Service fdd496
        case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
Packit Service fdd496
        case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
Packit Service fdd496
        case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
Packit Service fdd496
        case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
Packit Service fdd496
        case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
Packit Service fdd496
        case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
Packit Service fdd496
        case L_('~'):
Packit Service fdd496
          /* The C Standard requires these 98 characters (plus '%') to
Packit Service fdd496
             be in the basic execution character set.  None of these
Packit Service fdd496
             characters can start a multibyte sequence, so they need
Packit Service fdd496
             not be analyzed further.  */
Packit Service fdd496
          add1 (*f);
Packit Service fdd496
          continue;
Packit Service fdd496
Packit Service fdd496
        default:
Packit Service fdd496
          /* Copy this multibyte sequence until we reach its end, find
Packit Service fdd496
             an error, or come back to the initial shift state.  */
Packit Service fdd496
          {
Packit Service fdd496
            mbstate_t mbstate = mbstate_zero;
Packit Service fdd496
            size_t len = 0;
Packit Service fdd496
            size_t fsize;
Packit Service fdd496
Packit Service fdd496
            if (! format_end)
Packit Service fdd496
              format_end = f + strlen (f) + 1;
Packit Service fdd496
            fsize = format_end - f;
Packit Service fdd496
Packit Service fdd496
            do
Packit Service fdd496
              {
Packit Service fdd496
                size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
Packit Service fdd496
Packit Service fdd496
                if (bytes == 0)
Packit Service fdd496
                  break;
Packit Service fdd496
Packit Service fdd496
                if (bytes == (size_t) -2)
Packit Service fdd496
                  {
Packit Service fdd496
                    len += strlen (f + len);
Packit Service fdd496
                    break;
Packit Service fdd496
                  }
Packit Service fdd496
Packit Service fdd496
                if (bytes == (size_t) -1)
Packit Service fdd496
                  {
Packit Service fdd496
                    len++;
Packit Service fdd496
                    break;
Packit Service fdd496
                  }
Packit Service fdd496
Packit Service fdd496
                len += bytes;
Packit Service fdd496
              }
Packit Service fdd496
            while (! mbsinit (&mbstate));
Packit Service fdd496
Packit Service fdd496
            cpy (len, f);
Packit Service fdd496
            f += len - 1;
Packit Service fdd496
            continue;
Packit Service fdd496
          }
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
#else /* ! DO_MULTIBYTE */
Packit Service fdd496
Packit Service fdd496
      /* Either multibyte encodings are not supported, they are
Packit Service fdd496
         safe for formats, so any non-'%' byte can be copied through,
Packit Service fdd496
         or this is the wide character version.  */
Packit Service fdd496
      if (*f != L_('%'))
Packit Service fdd496
        {
Packit Service fdd496
          add1 (*f);
Packit Service fdd496
          continue;
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
#endif /* ! DO_MULTIBYTE */
Packit Service fdd496
Packit Service fdd496
      /* Check for flags that can modify a format.  */
Packit Service fdd496
      while (1)
Packit Service fdd496
        {
Packit Service fdd496
          switch (*++f)
Packit Service fdd496
            {
Packit Service fdd496
              /* This influences the number formats.  */
Packit Service fdd496
            case L_('_'):
Packit Service fdd496
            case L_('-'):
Packit Service fdd496
            case L_('0'):
Packit Service fdd496
              pad = *f;
Packit Service fdd496
              continue;
Packit Service fdd496
Packit Service fdd496
              /* This changes textual output.  */
Packit Service fdd496
            case L_('^'):
Packit Service fdd496
              to_uppcase = true;
Packit Service fdd496
              continue;
Packit Service fdd496
            case L_('#'):
Packit Service fdd496
              change_case = true;
Packit Service fdd496
              continue;
Packit Service fdd496
Packit Service fdd496
            default:
Packit Service fdd496
              break;
Packit Service fdd496
            }
Packit Service fdd496
          break;
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      /* As a GNU extension we allow the field width to be specified.  */
Packit Service fdd496
      if (ISDIGIT (*f))
Packit Service fdd496
        {
Packit Service fdd496
          width = 0;
Packit Service fdd496
          do
Packit Service fdd496
            {
Packit Service fdd496
              if (width > INT_MAX / 10
Packit Service fdd496
                  || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
Packit Service fdd496
                /* Avoid overflow.  */
Packit Service fdd496
                width = INT_MAX;
Packit Service fdd496
              else
Packit Service fdd496
                {
Packit Service fdd496
                  width *= 10;
Packit Service fdd496
                  width += *f - L_('0');
Packit Service fdd496
                }
Packit Service fdd496
              ++f;
Packit Service fdd496
            }
Packit Service fdd496
          while (ISDIGIT (*f));
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      /* Check for modifiers.  */
Packit Service fdd496
      switch (*f)
Packit Service fdd496
        {
Packit Service fdd496
        case L_('E'):
Packit Service fdd496
        case L_('O'):
Packit Service fdd496
          modifier = *f++;
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        default:
Packit Service fdd496
          modifier = 0;
Packit Service fdd496
          break;
Packit Service fdd496
        }
Packit Service fdd496
Packit Service fdd496
      /* Now do the specified format.  */
Packit Service fdd496
      format_char = *f;
Packit Service fdd496
      switch (format_char)
Packit Service fdd496
        {
Packit Service fdd496
#define DO_NUMBER(d, v) \
Packit Service fdd496
          do                                                                  \
Packit Service fdd496
            {                                                                 \
Packit Service fdd496
              digits = d;                                                     \
Packit Service fdd496
              number_value = v;                                               \
Packit Service fdd496
              goto do_number;                                                 \
Packit Service fdd496
            }                                                                 \
Packit Service fdd496
          while (0)
Packit Service fdd496
#define DO_SIGNED_NUMBER(d, negative, v) \
Packit Service fdd496
          do                                                                  \
Packit Service fdd496
            {                                                                 \
Packit Service fdd496
              digits = d;                                                     \
Packit Service fdd496
              negative_number = negative;                                     \
Packit Service fdd496
              u_number_value = v;                                             \
Packit Service fdd496
              goto do_signed_number;                                          \
Packit Service fdd496
            }                                                                 \
Packit Service fdd496
          while (0)
Packit Service fdd496
Packit Service fdd496
          /* The mask is not what you might think.
Packit Service fdd496
             When the ordinal i'th bit is set, insert a colon
Packit Service fdd496
             before the i'th digit of the time zone representation.  */
Packit Service fdd496
#define DO_TZ_OFFSET(d, mask, v) \
Packit Service fdd496
          do                                                                  \
Packit Service fdd496
            {                                                                 \
Packit Service fdd496
              digits = d;                                                     \
Packit Service fdd496
              tz_colon_mask = mask;                                           \
Packit Service fdd496
              u_number_value = v;                                             \
Packit Service fdd496
              goto do_tz_offset;                                              \
Packit Service fdd496
            }                                                                 \
Packit Service fdd496
          while (0)
Packit Service fdd496
#define DO_NUMBER_SPACEPAD(d, v) \
Packit Service fdd496
          do                                                                  \
Packit Service fdd496
            {                                                                 \
Packit Service fdd496
              digits = d;                                                     \
Packit Service fdd496
              number_value = v;                                               \
Packit Service fdd496
              goto do_number_spacepad;                                        \
Packit Service fdd496
            }                                                                 \
Packit Service fdd496
          while (0)
Packit Service fdd496
Packit Service fdd496
        case L_('%'):
Packit Service fdd496
          if (modifier != 0)
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
          add1 (*f);
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_('a'):
Packit Service fdd496
          if (modifier != 0)
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
          if (change_case)
Packit Service fdd496
            {
Packit Service fdd496
              to_uppcase = true;
Packit Service fdd496
              to_lowcase = false;
Packit Service fdd496
            }
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
          cpy (aw_len, a_wkday);
Packit Service fdd496
          break;
Packit Service fdd496
#else
Packit Service fdd496
          goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
        case 'A':
Packit Service fdd496
          if (modifier != 0)
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
          if (change_case)
Packit Service fdd496
            {
Packit Service fdd496
              to_uppcase = true;
Packit Service fdd496
              to_lowcase = false;
Packit Service fdd496
            }
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
          cpy (STRLEN (f_wkday), f_wkday);
Packit Service fdd496
          break;
Packit Service fdd496
#else
Packit Service fdd496
          goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
        case L_('b'):
Packit Service fdd496
        case L_('h'):
Packit Service fdd496
          if (change_case)
Packit Service fdd496
            {
Packit Service fdd496
              to_uppcase = true;
Packit Service fdd496
              to_lowcase = false;
Packit Service fdd496
            }
Packit Service fdd496
          if (modifier != 0)
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
          cpy (am_len, a_month);
Packit Service fdd496
          break;
Packit Service fdd496
#else
Packit Service fdd496
          goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
        case L_('B'):
Packit Service fdd496
          if (modifier != 0)
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
          if (change_case)
Packit Service fdd496
            {
Packit Service fdd496
              to_uppcase = true;
Packit Service fdd496
              to_lowcase = false;
Packit Service fdd496
            }
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
          cpy (STRLEN (f_month), f_month);
Packit Service fdd496
          break;
Packit Service fdd496
#else
Packit Service fdd496
          goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
        case L_('c'):
Packit Service fdd496
          if (modifier == L_('O'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
          if (! (modifier == 'E'
Packit Service fdd496
                 && (*(subfmt =
Packit Service fdd496
                       (const CHAR_T *) _NL_CURRENT (LC_TIME,
Packit Service fdd496
                                                     NLW(ERA_D_T_FMT)))
Packit Service fdd496
                     != '\0')))
Packit Service fdd496
            subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
Packit Service fdd496
#else
Packit Service fdd496
          goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
        subformat:
Packit Service fdd496
          {
Packit Service fdd496
            size_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1)
Packit Service fdd496
                                              subfmt,
Packit Service fdd496
                                              tp, to_uppcase, tzset_called
Packit Service fdd496
                                              extra_args LOCALE_ARG);
Packit Service fdd496
            add (len, __strftime_internal (p,
Packit Service fdd496
                                           STRFTIME_ARG (maxsize - i)
Packit Service fdd496
                                           subfmt,
Packit Service fdd496
                                           tp, to_uppcase, tzset_called
Packit Service fdd496
                                           extra_args LOCALE_ARG));
Packit Service fdd496
          }
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
#if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY)
Packit Service fdd496
        underlying_strftime:
Packit Service fdd496
          {
Packit Service fdd496
            /* The relevant information is available only via the
Packit Service fdd496
               underlying strftime implementation, so use that.  */
Packit Service fdd496
            char ufmt[5];
Packit Service fdd496
            char *u = ufmt;
Packit Service fdd496
            char ubuf[1024]; /* enough for any single format in practice */
Packit Service fdd496
            size_t len;
Packit Service fdd496
            /* Make sure we're calling the actual underlying strftime.
Packit Service fdd496
               In some cases, config.h contains something like
Packit Service fdd496
               "#define strftime rpl_strftime".  */
Packit Service fdd496
# ifdef strftime
Packit Service fdd496
#  undef strftime
Packit Service fdd496
            size_t strftime ();
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
            /* The space helps distinguish strftime failure from empty
Packit Service fdd496
               output.  */
Packit Service fdd496
            *u++ = ' ';
Packit Service fdd496
            *u++ = '%';
Packit Service fdd496
            if (modifier != 0)
Packit Service fdd496
              *u++ = modifier;
Packit Service fdd496
            *u++ = format_char;
Packit Service fdd496
            *u = '\0';
Packit Service fdd496
            len = strftime (ubuf, sizeof ubuf, ufmt, tp);
Packit Service fdd496
            if (len != 0)
Packit Service fdd496
              cpy (len - 1, ubuf + 1);
Packit Service fdd496
          }
Packit Service fdd496
          break;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
        case L_('C'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            {
Packit Service fdd496
#if HAVE_STRUCT_ERA_ENTRY
Packit Service fdd496
              struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
Packit Service fdd496
              if (era)
Packit Service fdd496
                {
Packit Service fdd496
# ifdef COMPILE_WIDE
Packit Service fdd496
                  size_t len = __wcslen (era->era_wname);
Packit Service fdd496
                  cpy (len, era->era_wname);
Packit Service fdd496
# else
Packit Service fdd496
                  size_t len = strlen (era->era_name);
Packit Service fdd496
                  cpy (len, era->era_name);
Packit Service fdd496
# endif
Packit Service fdd496
                  break;
Packit Service fdd496
                }
Packit Service fdd496
#else
Packit Service fdd496
              goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          {
Packit Service fdd496
            int century = tp->tm_year / 100 + TM_YEAR_BASE / 100;
Packit Service fdd496
            century -= tp->tm_year % 100 < 0 && 0 < century;
Packit Service fdd496
            DO_SIGNED_NUMBER (2, tp->tm_year < - TM_YEAR_BASE, century);
Packit Service fdd496
          }
Packit Service fdd496
Packit Service fdd496
        case L_('x'):
Packit Service fdd496
          if (modifier == L_('O'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
          if (! (modifier == L_('E')
Packit Service fdd496
                 && (*(subfmt =
Packit Service fdd496
                       (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
Packit Service fdd496
                     != L_('\0'))))
Packit Service fdd496
            subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
Packit Service fdd496
          goto subformat;
Packit Service fdd496
#else
Packit Service fdd496
          goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
        case L_('D'):
Packit Service fdd496
          if (modifier != 0)
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
          subfmt = L_("%m/%d/%y");
Packit Service fdd496
          goto subformat;
Packit Service fdd496
Packit Service fdd496
        case L_('d'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER (2, tp->tm_mday);
Packit Service fdd496
Packit Service fdd496
        case L_('e'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER_SPACEPAD (2, tp->tm_mday);
Packit Service fdd496
Packit Service fdd496
          /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE)
Packit Service fdd496
             and then jump to one of these labels.  */
Packit Service fdd496
Packit Service fdd496
        do_tz_offset:
Packit Service fdd496
          always_output_a_sign = true;
Packit Service fdd496
          goto do_number_body;
Packit Service fdd496
Packit Service fdd496
        do_number_spacepad:
Packit Service fdd496
          /* Force '_' flag unless overridden by '0' or '-' flag.  */
Packit Service fdd496
          if (pad != L_('0') && pad != L_('-'))
Packit Service fdd496
            pad = L_('_');
Packit Service fdd496
Packit Service fdd496
        do_number:
Packit Service fdd496
          /* Format NUMBER_VALUE according to the MODIFIER flag.  */
Packit Service fdd496
          negative_number = number_value < 0;
Packit Service fdd496
          u_number_value = number_value;
Packit Service fdd496
Packit Service fdd496
        do_signed_number:
Packit Service fdd496
          always_output_a_sign = false;
Packit Service fdd496
          tz_colon_mask = 0;
Packit Service fdd496
Packit Service fdd496
        do_number_body:
Packit Service fdd496
          /* Format U_NUMBER_VALUE according to the MODIFIER flag.
Packit Service fdd496
             NEGATIVE_NUMBER is nonzero if the original number was
Packit Service fdd496
             negative; in this case it was converted directly to
Packit Service fdd496
             unsigned int (i.e., modulo (UINT_MAX + 1)) without
Packit Service fdd496
             negating it.  */
Packit Service fdd496
          if (modifier == L_('O') && !negative_number)
Packit Service fdd496
            {
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
              /* Get the locale specific alternate representation of
Packit Service fdd496
                 the number.  If none exist NULL is returned.  */
Packit Service fdd496
              const CHAR_T *cp = nl_get_alt_digit (u_number_value
Packit Service fdd496
                                                   HELPER_LOCALE_ARG);
Packit Service fdd496
Packit Service fdd496
              if (cp != NULL)
Packit Service fdd496
                {
Packit Service fdd496
                  size_t digitlen = STRLEN (cp);
Packit Service fdd496
                  if (digitlen != 0)
Packit Service fdd496
                    {
Packit Service fdd496
                      cpy (digitlen, cp);
Packit Service fdd496
                      break;
Packit Service fdd496
                    }
Packit Service fdd496
                }
Packit Service fdd496
#else
Packit Service fdd496
              goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          bufp = buf + sizeof (buf) / sizeof (buf[0]);
Packit Service fdd496
Packit Service fdd496
          if (negative_number)
Packit Service fdd496
            u_number_value = - u_number_value;
Packit Service fdd496
Packit Service fdd496
          do
Packit Service fdd496
            {
Packit Service fdd496
              if (tz_colon_mask & 1)
Packit Service fdd496
                *--bufp = ':';
Packit Service fdd496
              tz_colon_mask >>= 1;
Packit Service fdd496
              *--bufp = u_number_value % 10 + L_('0');
Packit Service fdd496
              u_number_value /= 10;
Packit Service fdd496
            }
Packit Service fdd496
          while (u_number_value != 0 || tz_colon_mask != 0);
Packit Service fdd496
Packit Service fdd496
        do_number_sign_and_padding:
Packit Service fdd496
          if (digits < width)
Packit Service fdd496
            digits = width;
Packit Service fdd496
Packit Service fdd496
          sign_char = (negative_number ? L_('-')
Packit Service fdd496
                       : always_output_a_sign ? L_('+')
Packit Service fdd496
                       : 0);
Packit Service fdd496
Packit Service fdd496
          if (pad == L_('-'))
Packit Service fdd496
            {
Packit Service fdd496
              if (sign_char)
Packit Service fdd496
                add1 (sign_char);
Packit Service fdd496
            }
Packit Service fdd496
          else
Packit Service fdd496
            {
Packit Service fdd496
              int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
Packit Service fdd496
                                      - bufp) - !!sign_char;
Packit Service fdd496
Packit Service fdd496
              if (padding > 0)
Packit Service fdd496
                {
Packit Service fdd496
                  if (pad == L_('_'))
Packit Service fdd496
                    {
Packit Service fdd496
                      if ((size_t) padding >= maxsize - i)
Packit Service fdd496
                        return 0;
Packit Service fdd496
Packit Service fdd496
                      if (p)
Packit Service fdd496
                        memset_space (p, padding);
Packit Service fdd496
                      i += padding;
Packit Service fdd496
                      width = width > padding ? width - padding : 0;
Packit Service fdd496
                      if (sign_char)
Packit Service fdd496
                        add1 (sign_char);
Packit Service fdd496
                    }
Packit Service fdd496
                  else
Packit Service fdd496
                    {
Packit Service fdd496
                      if ((size_t) digits >= maxsize - i)
Packit Service fdd496
                        return 0;
Packit Service fdd496
Packit Service fdd496
                      if (sign_char)
Packit Service fdd496
                        add1 (sign_char);
Packit Service fdd496
Packit Service fdd496
                      if (p)
Packit Service fdd496
                        memset_zero (p, padding);
Packit Service fdd496
                      i += padding;
Packit Service fdd496
                      width = 0;
Packit Service fdd496
                    }
Packit Service fdd496
                }
Packit Service fdd496
              else
Packit Service fdd496
                {
Packit Service fdd496
                  if (sign_char)
Packit Service fdd496
                    add1 (sign_char);
Packit Service fdd496
                }
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_('F'):
Packit Service fdd496
          if (modifier != 0)
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
          subfmt = L_("%Y-%m-%d");
Packit Service fdd496
          goto subformat;
Packit Service fdd496
Packit Service fdd496
        case L_('H'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER (2, tp->tm_hour);
Packit Service fdd496
Packit Service fdd496
        case L_('I'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER (2, hour12);
Packit Service fdd496
Packit Service fdd496
        case L_('k'):           /* GNU extension.  */
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER_SPACEPAD (2, tp->tm_hour);
Packit Service fdd496
Packit Service fdd496
        case L_('l'):           /* GNU extension.  */
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER_SPACEPAD (2, hour12);
Packit Service fdd496
Packit Service fdd496
        case L_('j'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U);
Packit Service fdd496
Packit Service fdd496
        case L_('M'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER (2, tp->tm_min);
Packit Service fdd496
Packit Service fdd496
        case L_('m'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U);
Packit Service fdd496
Packit Service fdd496
#ifndef _LIBC
Packit Service fdd496
        case L_('N'):           /* GNU extension.  */
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          number_value = ns;
Packit Service fdd496
          if (width == -1)
Packit Service fdd496
            width = 9;
Packit Service fdd496
          else
Packit Service fdd496
            {
Packit Service fdd496
              /* Take an explicit width less than 9 as a precision.  */
Packit Service fdd496
              int j;
Packit Service fdd496
              for (j = width; j < 9; j++)
Packit Service fdd496
                number_value /= 10;
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER (width, number_value);
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
        case L_('n'):
Packit Service fdd496
          add1 (L_('\n'));
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_('P'):
Packit Service fdd496
          to_lowcase = true;
Packit Service fdd496
#ifndef _NL_CURRENT
Packit Service fdd496
          format_char = L_('p');
Packit Service fdd496
#endif
Packit Service fdd496
          FALLTHROUGH;
Packit Service fdd496
        case L_('p'):
Packit Service fdd496
          if (change_case)
Packit Service fdd496
            {
Packit Service fdd496
              to_uppcase = false;
Packit Service fdd496
              to_lowcase = true;
Packit Service fdd496
            }
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
          cpy (ap_len, ampm);
Packit Service fdd496
          break;
Packit Service fdd496
#else
Packit Service fdd496
          goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
        case L_('q'):           /* GNU extension.  */
Packit Service fdd496
          DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1);
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_('R'):
Packit Service fdd496
          subfmt = L_("%H:%M");
Packit Service fdd496
          goto subformat;
Packit Service fdd496
Packit Service fdd496
        case L_('r'):
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
          if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME,
Packit Service fdd496
                                                       NLW(T_FMT_AMPM)))
Packit Service fdd496
              == L_('\0'))
Packit Service fdd496
            subfmt = L_("%I:%M:%S %p");
Packit Service fdd496
          goto subformat;
Packit Service fdd496
#else
Packit Service fdd496
          goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
        case L_('S'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER (2, tp->tm_sec);
Packit Service fdd496
Packit Service fdd496
        case L_('s'):           /* GNU extension.  */
Packit Service fdd496
          {
Packit Service fdd496
            struct tm ltm;
Packit Service fdd496
            time_t t;
Packit Service fdd496
Packit Service fdd496
            ltm = *tp;
Packit Service fdd496
            t = mktime_z (tz, <m;;
Packit Service fdd496
Packit Service fdd496
            /* Generate string value for T using time_t arithmetic;
Packit Service fdd496
               this works even if sizeof (long) < sizeof (time_t).  */
Packit Service fdd496
Packit Service fdd496
            bufp = buf + sizeof (buf) / sizeof (buf[0]);
Packit Service fdd496
            negative_number = t < 0;
Packit Service fdd496
Packit Service fdd496
            do
Packit Service fdd496
              {
Packit Service fdd496
                int d = t % 10;
Packit Service fdd496
                t /= 10;
Packit Service fdd496
                *--bufp = (negative_number ? -d : d) + L_('0');
Packit Service fdd496
              }
Packit Service fdd496
            while (t != 0);
Packit Service fdd496
Packit Service fdd496
            digits = 1;
Packit Service fdd496
            always_output_a_sign = false;
Packit Service fdd496
            goto do_number_sign_and_padding;
Packit Service fdd496
          }
Packit Service fdd496
Packit Service fdd496
        case L_('X'):
Packit Service fdd496
          if (modifier == L_('O'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
#ifdef _NL_CURRENT
Packit Service fdd496
          if (! (modifier == L_('E')
Packit Service fdd496
                 && (*(subfmt =
Packit Service fdd496
                       (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT)))
Packit Service fdd496
                     != L_('\0'))))
Packit Service fdd496
            subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
Packit Service fdd496
          goto subformat;
Packit Service fdd496
#else
Packit Service fdd496
          goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
        case L_('T'):
Packit Service fdd496
          subfmt = L_("%H:%M:%S");
Packit Service fdd496
          goto subformat;
Packit Service fdd496
Packit Service fdd496
        case L_('t'):
Packit Service fdd496
          add1 (L_('\t'));
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_('u'):
Packit Service fdd496
          DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
Packit Service fdd496
Packit Service fdd496
        case L_('U'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
Packit Service fdd496
Packit Service fdd496
        case L_('V'):
Packit Service fdd496
        case L_('g'):
Packit Service fdd496
        case L_('G'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
          {
Packit Service fdd496
            /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE)
Packit Service fdd496
               is a leap year, except that YEAR and YEAR - 1 both work
Packit Service fdd496
               correctly even when (tp->tm_year + TM_YEAR_BASE) would
Packit Service fdd496
               overflow.  */
Packit Service fdd496
            int year = (tp->tm_year
Packit Service fdd496
                        + (tp->tm_year < 0
Packit Service fdd496
                           ? TM_YEAR_BASE % 400
Packit Service fdd496
                           : TM_YEAR_BASE % 400 - 400));
Packit Service fdd496
            int year_adjust = 0;
Packit Service fdd496
            int days = iso_week_days (tp->tm_yday, tp->tm_wday);
Packit Service fdd496
Packit Service fdd496
            if (days < 0)
Packit Service fdd496
              {
Packit Service fdd496
                /* This ISO week belongs to the previous year.  */
Packit Service fdd496
                year_adjust = -1;
Packit Service fdd496
                days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)),
Packit Service fdd496
                                      tp->tm_wday);
Packit Service fdd496
              }
Packit Service fdd496
            else
Packit Service fdd496
              {
Packit Service fdd496
                int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)),
Packit Service fdd496
                                       tp->tm_wday);
Packit Service fdd496
                if (0 <= d)
Packit Service fdd496
                  {
Packit Service fdd496
                    /* This ISO week belongs to the next year.  */
Packit Service fdd496
                    year_adjust = 1;
Packit Service fdd496
                    days = d;
Packit Service fdd496
                  }
Packit Service fdd496
              }
Packit Service fdd496
Packit Service fdd496
            switch (*f)
Packit Service fdd496
              {
Packit Service fdd496
              case L_('g'):
Packit Service fdd496
                {
Packit Service fdd496
                  int yy = (tp->tm_year % 100 + year_adjust) % 100;
Packit Service fdd496
                  DO_NUMBER (2, (0 <= yy
Packit Service fdd496
                                 ? yy
Packit Service fdd496
                                 : tp->tm_year < -TM_YEAR_BASE - year_adjust
Packit Service fdd496
                                 ? -yy
Packit Service fdd496
                                 : yy + 100));
Packit Service fdd496
                }
Packit Service fdd496
Packit Service fdd496
              case L_('G'):
Packit Service fdd496
                DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
Packit Service fdd496
                                  (tp->tm_year + (unsigned int) TM_YEAR_BASE
Packit Service fdd496
                                   + year_adjust));
Packit Service fdd496
Packit Service fdd496
              default:
Packit Service fdd496
                DO_NUMBER (2, days / 7 + 1);
Packit Service fdd496
              }
Packit Service fdd496
          }
Packit Service fdd496
Packit Service fdd496
        case L_('W'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
Packit Service fdd496
Packit Service fdd496
        case L_('w'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_NUMBER (1, tp->tm_wday);
Packit Service fdd496
Packit Service fdd496
        case L_('Y'):
Packit Service fdd496
          if (modifier == 'E')
Packit Service fdd496
            {
Packit Service fdd496
#if HAVE_STRUCT_ERA_ENTRY
Packit Service fdd496
              struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
Packit Service fdd496
              if (era)
Packit Service fdd496
                {
Packit Service fdd496
# ifdef COMPILE_WIDE
Packit Service fdd496
                  subfmt = era->era_wformat;
Packit Service fdd496
# else
Packit Service fdd496
                  subfmt = era->era_format;
Packit Service fdd496
# endif
Packit Service fdd496
                  goto subformat;
Packit Service fdd496
                }
Packit Service fdd496
#else
Packit Service fdd496
              goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
            }
Packit Service fdd496
          if (modifier == L_('O'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
Packit Service fdd496
          DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE,
Packit Service fdd496
                            tp->tm_year + (unsigned int) TM_YEAR_BASE);
Packit Service fdd496
Packit Service fdd496
        case L_('y'):
Packit Service fdd496
          if (modifier == L_('E'))
Packit Service fdd496
            {
Packit Service fdd496
#if HAVE_STRUCT_ERA_ENTRY
Packit Service fdd496
              struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
Packit Service fdd496
              if (era)
Packit Service fdd496
                {
Packit Service fdd496
                  int delta = tp->tm_year - era->start_date[0];
Packit Service fdd496
                  DO_NUMBER (1, (era->offset
Packit Service fdd496
                                 + delta * era->absolute_direction));
Packit Service fdd496
                }
Packit Service fdd496
#else
Packit Service fdd496
              goto underlying_strftime;
Packit Service fdd496
#endif
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
          {
Packit Service fdd496
            int yy = tp->tm_year % 100;
Packit Service fdd496
            if (yy < 0)
Packit Service fdd496
              yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
Packit Service fdd496
            DO_NUMBER (2, yy);
Packit Service fdd496
          }
Packit Service fdd496
Packit Service fdd496
        case L_('Z'):
Packit Service fdd496
          if (change_case)
Packit Service fdd496
            {
Packit Service fdd496
              to_uppcase = false;
Packit Service fdd496
              to_lowcase = true;
Packit Service fdd496
            }
Packit Service fdd496
Packit Service fdd496
#ifdef COMPILE_WIDE
Packit Service fdd496
          {
Packit Service fdd496
            /* The zone string is always given in multibyte form.  We have
Packit Service fdd496
               to transform it first.  */
Packit Service fdd496
            wchar_t *wczone;
Packit Service fdd496
            size_t len;
Packit Service fdd496
            widen (zone, wczone, len);
Packit Service fdd496
            cpy (len, wczone);
Packit Service fdd496
          }
Packit Service fdd496
#else
Packit Service fdd496
          cpy (strlen (zone), zone);
Packit Service fdd496
#endif
Packit Service fdd496
          break;
Packit Service fdd496
Packit Service fdd496
        case L_(':'):
Packit Service fdd496
          /* :, ::, and ::: are valid only just before 'z'.
Packit Service fdd496
             :::: etc. are rejected later.  */
Packit Service fdd496
          for (colons = 1; f[colons] == L_(':'); colons++)
Packit Service fdd496
            continue;
Packit Service fdd496
          if (f[colons] != L_('z'))
Packit Service fdd496
            goto bad_format;
Packit Service fdd496
          f += colons;
Packit Service fdd496
          goto do_z_conversion;
Packit Service fdd496
Packit Service fdd496
        case L_('z'):
Packit Service fdd496
          colons = 0;
Packit Service fdd496
Packit Service fdd496
        do_z_conversion:
Packit Service fdd496
          if (tp->tm_isdst < 0)
Packit Service fdd496
            break;
Packit Service fdd496
Packit Service fdd496
          {
Packit Service fdd496
            int diff;
Packit Service fdd496
            int hour_diff;
Packit Service fdd496
            int min_diff;
Packit Service fdd496
            int sec_diff;
Packit Service fdd496
#if HAVE_TM_GMTOFF
Packit Service fdd496
            diff = tp->tm_gmtoff;
Packit Service fdd496
#else
Packit Service fdd496
            if (!tz)
Packit Service fdd496
              diff = 0;
Packit Service fdd496
            else
Packit Service fdd496
              {
Packit Service fdd496
                struct tm gtm;
Packit Service fdd496
                struct tm ltm;
Packit Service fdd496
                time_t lt;
Packit Service fdd496
Packit Service fdd496
                /* POSIX.1 requires that local time zone information be used as
Packit Service fdd496
                   though strftime called tzset.  */
Packit Service fdd496
# if HAVE_TZSET
Packit Service fdd496
                if (!*tzset_called)
Packit Service fdd496
                  {
Packit Service fdd496
                    tzset ();
Packit Service fdd496
                    *tzset_called = true;
Packit Service fdd496
                  }
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
                ltm = *tp;
Packit Service fdd496
                lt = mktime_z (tz, <m;;
Packit Service fdd496
Packit Service fdd496
                if (lt == (time_t) -1)
Packit Service fdd496
                  {
Packit Service fdd496
                    /* mktime returns -1 for errors, but -1 is also a
Packit Service fdd496
                       valid time_t value.  Check whether an error really
Packit Service fdd496
                       occurred.  */
Packit Service fdd496
                    struct tm tm;
Packit Service fdd496
Packit Service fdd496
                    if (! localtime_rz (tz, &lt, &tm)
Packit Service fdd496
                        || ((ltm.tm_sec ^ tm.tm_sec)
Packit Service fdd496
                            | (ltm.tm_min ^ tm.tm_min)
Packit Service fdd496
                            | (ltm.tm_hour ^ tm.tm_hour)
Packit Service fdd496
                            | (ltm.tm_mday ^ tm.tm_mday)
Packit Service fdd496
                            | (ltm.tm_mon ^ tm.tm_mon)
Packit Service fdd496
                            | (ltm.tm_year ^ tm.tm_year)))
Packit Service fdd496
                      break;
Packit Service fdd496
                  }
Packit Service fdd496
Packit Service fdd496
                if (! localtime_rz (0, &lt, &gtm))
Packit Service fdd496
                  break;
Packit Service fdd496
Packit Service fdd496
                diff = tm_diff (&ltm, >m;;
Packit Service fdd496
              }
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
            negative_number = diff < 0 || (diff == 0 && *zone == '-');
Packit Service fdd496
            hour_diff = diff / 60 / 60;
Packit Service fdd496
            min_diff = diff / 60 % 60;
Packit Service fdd496
            sec_diff = diff % 60;
Packit Service fdd496
Packit Service fdd496
            switch (colons)
Packit Service fdd496
              {
Packit Service fdd496
              case 0: /* +hhmm */
Packit Service fdd496
                DO_TZ_OFFSET (5, 0, hour_diff * 100 + min_diff);
Packit Service fdd496
Packit Service fdd496
              case 1: tz_hh_mm: /* +hh:mm */
Packit Service fdd496
                DO_TZ_OFFSET (6, 04, hour_diff * 100 + min_diff);
Packit Service fdd496
Packit Service fdd496
              case 2: tz_hh_mm_ss: /* +hh:mm:ss */
Packit Service fdd496
                DO_TZ_OFFSET (9, 024,
Packit Service fdd496
                              hour_diff * 10000 + min_diff * 100 + sec_diff);
Packit Service fdd496
Packit Service fdd496
              case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */
Packit Service fdd496
                if (sec_diff != 0)
Packit Service fdd496
                  goto tz_hh_mm_ss;
Packit Service fdd496
                if (min_diff != 0)
Packit Service fdd496
                  goto tz_hh_mm;
Packit Service fdd496
                DO_TZ_OFFSET (3, 0, hour_diff);
Packit Service fdd496
Packit Service fdd496
              default:
Packit Service fdd496
                goto bad_format;
Packit Service fdd496
              }
Packit Service fdd496
          }
Packit Service fdd496
Packit Service fdd496
        case L_('\0'):          /* GNU extension: % at end of format.  */
Packit Service fdd496
            --f;
Packit Service fdd496
            FALLTHROUGH;
Packit Service fdd496
        default:
Packit Service fdd496
          /* Unknown format; output the format, including the '%',
Packit Service fdd496
             since this is most likely the right thing to do if a
Packit Service fdd496
             multibyte string has been misparsed.  */
Packit Service fdd496
        bad_format:
Packit Service fdd496
          {
Packit Service fdd496
            int flen;
Packit Service fdd496
            for (flen = 1; f[1 - flen] != L_('%'); flen++)
Packit Service fdd496
              continue;
Packit Service fdd496
            cpy (flen, &f[1 - flen]);
Packit Service fdd496
          }
Packit Service fdd496
          break;
Packit Service fdd496
        }
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
#if ! FPRINTFTIME
Packit Service fdd496
  if (p && maxsize != 0)
Packit Service fdd496
    *p = L_('\0');
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
  return i;
Packit Service fdd496
}