Blame lib/strptime.c

Packit 8f70b4
/* Copyright (C) 2002, 2004-2005, 2007, 2009-2018 Free Software Foundation,
Packit 8f70b4
   Inc.
Packit 8f70b4
   This file is part of the GNU C Library.
Packit 8f70b4
Packit 8f70b4
   This program is free software; you can redistribute it and/or modify
Packit 8f70b4
   it under the terms of the GNU General Public License as published by
Packit 8f70b4
   the Free Software Foundation; either version 3, or (at your option)
Packit 8f70b4
   any later version.
Packit 8f70b4
Packit 8f70b4
   This program is distributed in the hope that it will be useful,
Packit 8f70b4
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8f70b4
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8f70b4
   GNU General Public License for more details.
Packit 8f70b4
Packit 8f70b4
   You should have received a copy of the GNU General Public License along
Packit 8f70b4
   with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit 8f70b4
Packit 8f70b4
#ifndef _LIBC
Packit 8f70b4
# include <config.h>
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
#include <time.h>
Packit 8f70b4
Packit 8f70b4
#include <assert.h>
Packit 8f70b4
#include <ctype.h>
Packit 8f70b4
#ifdef _LIBC
Packit 8f70b4
# include <langinfo.h>
Packit 8f70b4
#endif
Packit 8f70b4
#include <limits.h>
Packit 8f70b4
#include <string.h>
Packit 8f70b4
#include <stdbool.h>
Packit 8f70b4
Packit 8f70b4
#ifdef _LIBC
Packit 8f70b4
# include "../locale/localeinfo.h"
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
#ifndef _LIBC
Packit 8f70b4
enum ptime_locale_status { not, loc, raw };
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#define match_char(ch1, ch2) if (ch1 != ch2) return NULL
Packit 8f70b4
#if defined _LIBC && defined __GNUC__ && __GNUC__ >= 2
Packit 8f70b4
# define match_string(cs1, s2) \
Packit 8f70b4
  ({ size_t len = strlen (cs1);                                               \
Packit 8f70b4
     int result = __strncasecmp_l ((cs1), (s2), len, locale) == 0;            \
Packit 8f70b4
     if (result) (s2) += len;                                                 \
Packit 8f70b4
     result; })
Packit 8f70b4
#else
Packit 8f70b4
/* Oh come on.  Get a reasonable compiler.  */
Packit 8f70b4
# define match_string(cs1, s2) \
Packit 8f70b4
  (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
Packit 8f70b4
#endif
Packit 8f70b4
/* We intentionally do not use isdigit() for testing because this will
Packit 8f70b4
   lead to problems with the wide character version.  */
Packit 8f70b4
#define get_number(from, to, n) \
Packit 8f70b4
  do {                                                                        \
Packit 8f70b4
    int __n = n;                                                              \
Packit 8f70b4
    val = 0;                                                                  \
Packit 8f70b4
    while (*rp == ' ')                                                        \
Packit 8f70b4
      ++rp;                                                                   \
Packit 8f70b4
    if (*rp < '0' || *rp > '9')                                               \
Packit 8f70b4
      return NULL;                                                            \
Packit 8f70b4
    do {                                                                      \
Packit 8f70b4
      val *= 10;                                                              \
Packit 8f70b4
      val += *rp++ - '0';                                                     \
Packit 8f70b4
    } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9');        \
Packit 8f70b4
    if (val < from || val > to)                                               \
Packit 8f70b4
      return NULL;                                                            \
Packit 8f70b4
  } while (0)
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
# define get_alt_number(from, to, n) \
Packit 8f70b4
  ({                                                                          \
Packit 8f70b4
     __label__ do_normal;                                                     \
Packit 8f70b4
                                                                              \
Packit 8f70b4
     if (*decided != raw)                                                     \
Packit 8f70b4
       {                                                                      \
Packit 8f70b4
         val = _nl_parse_alt_digit (&rp HELPER_LOCALE_ARG);                   \
Packit 8f70b4
         if (val == -1 && *decided != loc)                                    \
Packit 8f70b4
           {                                                                  \
Packit 8f70b4
             *decided = loc;                                                  \
Packit 8f70b4
             goto do_normal;                                                  \
Packit 8f70b4
           }                                                                  \
Packit 8f70b4
        if (val < from || val > to)                                           \
Packit 8f70b4
          return NULL;                                                        \
Packit 8f70b4
       }                                                                      \
Packit 8f70b4
     else                                                                     \
Packit 8f70b4
       {                                                                      \
Packit 8f70b4
       do_normal:                                                             \
Packit 8f70b4
         get_number (from, to, n);                                            \
Packit 8f70b4
       }                                                                      \
Packit 8f70b4
    0;                                                                        \
Packit 8f70b4
  })
Packit 8f70b4
#else
Packit 8f70b4
# define get_alt_number(from, to, n) \
Packit 8f70b4
  /* We don't have the alternate representation.  */                          \
Packit 8f70b4
  get_number(from, to, n)
Packit 8f70b4
#endif
Packit 8f70b4
#define recursive(new_fmt) \
Packit 8f70b4
  (*(new_fmt) != '\0'                                                         \
Packit 8f70b4
   && (rp = __strptime_internal (rp, (new_fmt), tm,                           \
Packit 8f70b4
                                 decided, era_cnt LOCALE_ARG)) != NULL)
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#ifdef _LIBC
Packit 8f70b4
/* This is defined in locale/C-time.c in the GNU libc.  */
Packit 8f70b4
extern const struct locale_data _nl_C_LC_TIME attribute_hidden;
Packit 8f70b4
Packit 8f70b4
# define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
Packit 8f70b4
# define ab_weekday_name \
Packit 8f70b4
  (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
Packit 8f70b4
# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
Packit 8f70b4
# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
Packit 8f70b4
# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
Packit 8f70b4
# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
Packit 8f70b4
# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
Packit 8f70b4
# define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
Packit 8f70b4
# define HERE_T_FMT_AMPM \
Packit 8f70b4
  (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
Packit 8f70b4
# define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
Packit 8f70b4
Packit 8f70b4
# define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
Packit 8f70b4
#else
Packit 8f70b4
static char const weekday_name[][10] =
Packit 8f70b4
  {
Packit 8f70b4
    "Sunday", "Monday", "Tuesday", "Wednesday",
Packit 8f70b4
    "Thursday", "Friday", "Saturday"
Packit 8f70b4
  };
Packit 8f70b4
static char const ab_weekday_name[][4] =
Packit 8f70b4
  {
Packit 8f70b4
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
Packit 8f70b4
  };
Packit 8f70b4
static char const month_name[][10] =
Packit 8f70b4
  {
Packit 8f70b4
    "January", "February", "March", "April", "May", "June",
Packit 8f70b4
    "July", "August", "September", "October", "November", "December"
Packit 8f70b4
  };
Packit 8f70b4
static char const ab_month_name[][4] =
Packit 8f70b4
  {
Packit 8f70b4
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
Packit 8f70b4
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
Packit 8f70b4
  };
Packit 8f70b4
# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
Packit 8f70b4
# define HERE_D_FMT "%m/%d/%y"
Packit 8f70b4
# define HERE_AM_STR "AM"
Packit 8f70b4
# define HERE_PM_STR "PM"
Packit 8f70b4
# define HERE_T_FMT_AMPM "%I:%M:%S %p"
Packit 8f70b4
# define HERE_T_FMT "%H:%M:%S"
Packit 8f70b4
Packit 8f70b4
static const unsigned short int __mon_yday[2][13] =
Packit 8f70b4
  {
Packit 8f70b4
    /* Normal years.  */
Packit 8f70b4
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
Packit 8f70b4
    /* Leap years.  */
Packit 8f70b4
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
Packit 8f70b4
  };
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
#if defined _LIBC
Packit 8f70b4
/* We use this code also for the extended locale handling where the
Packit 8f70b4
   function gets as an additional argument the locale which has to be
Packit 8f70b4
   used.  To access the values we have to redefine the _NL_CURRENT
Packit 8f70b4
   macro.  */
Packit 8f70b4
# define strptime               __strptime_l
Packit 8f70b4
# undef _NL_CURRENT
Packit 8f70b4
# define _NL_CURRENT(category, item) \
Packit 8f70b4
  (current->values[_NL_ITEM_INDEX (item)].string)
Packit 8f70b4
# undef _NL_CURRENT_WORD
Packit 8f70b4
# define _NL_CURRENT_WORD(category, item) \
Packit 8f70b4
  (current->values[_NL_ITEM_INDEX (item)].word)
Packit 8f70b4
# define LOCALE_PARAM , locale
Packit 8f70b4
# define LOCALE_ARG , locale
Packit 8f70b4
# define LOCALE_PARAM_PROTO , __locale_t locale
Packit 8f70b4
# define LOCALE_PARAM_DECL __locale_t locale;
Packit 8f70b4
# define HELPER_LOCALE_ARG , current
Packit 8f70b4
# define ISSPACE(Ch) __isspace_l (Ch, locale)
Packit 8f70b4
#else
Packit 8f70b4
# define LOCALE_PARAM
Packit 8f70b4
# define LOCALE_ARG
Packit 8f70b4
# define LOCALE_PARAM_DECL
Packit 8f70b4
# define LOCALE_PARAM_PROTO
Packit 8f70b4
# define HELPER_LOCALE_ARG
Packit 8f70b4
# define ISSPACE(Ch) isspace (Ch)
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#ifndef __isleap
Packit 8f70b4
/* Nonzero if YEAR is a leap year (every 4 years,
Packit 8f70b4
   except every 100th isn't, and every 400th is).  */
Packit 8f70b4
# define __isleap(year) \
Packit 8f70b4
  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/* Compute the day of the week.  */
Packit 8f70b4
static void
Packit 8f70b4
day_of_the_week (struct tm *tm)
Packit 8f70b4
{
Packit 8f70b4
  /* We know that January 1st 1970 was a Thursday (= 4).  Compute the
Packit 8f70b4
     difference between this data in the one on TM and so determine
Packit 8f70b4
     the weekday.  */
Packit 8f70b4
  int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
Packit 8f70b4
  int wday = (-473
Packit 8f70b4
              + (365 * (tm->tm_year - 70))
Packit 8f70b4
              + (corr_year / 4)
Packit 8f70b4
              - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
Packit 8f70b4
              + (((corr_year / 4) / 25) / 4)
Packit 8f70b4
              + __mon_yday[0][tm->tm_mon]
Packit 8f70b4
              + tm->tm_mday - 1);
Packit 8f70b4
  tm->tm_wday = ((wday % 7) + 7) % 7;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
/* Compute the day of the year.  */
Packit 8f70b4
static void
Packit 8f70b4
day_of_the_year (struct tm *tm)
Packit 8f70b4
{
Packit 8f70b4
  tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
Packit 8f70b4
                 + (tm->tm_mday - 1));
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#ifdef _LIBC
Packit 8f70b4
char *
Packit 8f70b4
internal_function
Packit 8f70b4
#else
Packit 8f70b4
static char *
Packit 8f70b4
#endif
Packit 8f70b4
__strptime_internal (rp, fmt, tm, decided, era_cnt LOCALE_PARAM)
Packit 8f70b4
     const char *rp;
Packit 8f70b4
     const char *fmt;
Packit 8f70b4
     struct tm *tm;
Packit 8f70b4
     enum ptime_locale_status *decided;
Packit 8f70b4
     int era_cnt;
Packit 8f70b4
     LOCALE_PARAM_DECL
Packit 8f70b4
{
Packit 8f70b4
#ifdef _LIBC
Packit 8f70b4
  struct locale_data *const current = locale->__locales[LC_TIME];
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
  int cnt;
Packit 8f70b4
  size_t val;
Packit 8f70b4
  int have_I, is_pm;
Packit 8f70b4
  int century, want_century;
Packit 8f70b4
  int want_era;
Packit 8f70b4
  int have_wday, want_xday;
Packit 8f70b4
  int have_yday;
Packit 8f70b4
  int have_mon, have_mday;
Packit 8f70b4
  int have_uweek, have_wweek;
Packit 8f70b4
  int week_no;
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
  size_t num_eras;
Packit 8f70b4
  struct era_entry *era = NULL;
Packit 8f70b4
  const char *rp_backup;
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
  have_I = is_pm = 0;
Packit 8f70b4
  century = -1;
Packit 8f70b4
  want_century = 0;
Packit 8f70b4
  want_era = 0;
Packit 8f70b4
  week_no = 0;
Packit 8f70b4
Packit 8f70b4
  have_wday = want_xday = have_yday = have_mon = have_mday = have_uweek = 0;
Packit 8f70b4
  have_wweek = 0;
Packit 8f70b4
Packit 8f70b4
  while (*fmt != '\0')
Packit 8f70b4
    {
Packit 8f70b4
      /* A white space in the format string matches 0 more or white
Packit 8f70b4
         space in the input string.  */
Packit 8f70b4
      if (ISSPACE (*fmt))
Packit 8f70b4
        {
Packit 8f70b4
          while (ISSPACE (*rp))
Packit 8f70b4
            ++rp;
Packit 8f70b4
          ++fmt;
Packit 8f70b4
          continue;
Packit 8f70b4
        }
Packit 8f70b4
Packit 8f70b4
      /* Any character but '%' must be matched by the same character
Packit 8f70b4
         in the iput string.  */
Packit 8f70b4
      if (*fmt != '%')
Packit 8f70b4
        {
Packit 8f70b4
          match_char (*fmt++, *rp++);
Packit 8f70b4
          continue;
Packit 8f70b4
        }
Packit 8f70b4
Packit 8f70b4
      ++fmt;
Packit 8f70b4
#ifndef _NL_CURRENT
Packit 8f70b4
      /* We need this for handling the 'E' modifier.  */
Packit 8f70b4
    start_over:
Packit 8f70b4
#else
Packit 8f70b4
      /* Make back up of current processing pointer.  */
Packit 8f70b4
      rp_backup = rp;
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
      switch (*fmt++)
Packit 8f70b4
        {
Packit 8f70b4
        case '%':
Packit 8f70b4
          /* Match the '%' character itself.  */
Packit 8f70b4
          match_char ('%', *rp++);
Packit 8f70b4
          break;
Packit 8f70b4
        case 'a':
Packit 8f70b4
        case 'A':
Packit 8f70b4
          /* Match day of week.  */
Packit 8f70b4
          for (cnt = 0; cnt < 7; ++cnt)
Packit 8f70b4
            {
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
              if (*decided !=raw)
Packit 8f70b4
                {
Packit 8f70b4
                  if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
Packit 8f70b4
                    {
Packit 8f70b4
                      if (*decided == not
Packit 8f70b4
                          && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
Packit 8f70b4
                                     weekday_name[cnt]))
Packit 8f70b4
                        *decided = loc;
Packit 8f70b4
                      break;
Packit 8f70b4
                    }
Packit 8f70b4
                  if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
Packit 8f70b4
                    {
Packit 8f70b4
                      if (*decided == not
Packit 8f70b4
                          && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
Packit 8f70b4
                                     ab_weekday_name[cnt]))
Packit 8f70b4
                        *decided = loc;
Packit 8f70b4
                      break;
Packit 8f70b4
                    }
Packit 8f70b4
                }
Packit 8f70b4
#endif
Packit 8f70b4
              if (*decided != loc
Packit 8f70b4
                  && (match_string (weekday_name[cnt], rp)
Packit 8f70b4
                      || match_string (ab_weekday_name[cnt], rp)))
Packit 8f70b4
                {
Packit 8f70b4
                  *decided = raw;
Packit 8f70b4
                  break;
Packit 8f70b4
                }
Packit 8f70b4
            }
Packit 8f70b4
          if (cnt == 7)
Packit 8f70b4
            /* Does not match a weekday name.  */
Packit 8f70b4
            return NULL;
Packit 8f70b4
          tm->tm_wday = cnt;
Packit 8f70b4
          have_wday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'b':
Packit 8f70b4
        case 'B':
Packit 8f70b4
        case 'h':
Packit 8f70b4
          /* Match month name.  */
Packit 8f70b4
          for (cnt = 0; cnt < 12; ++cnt)
Packit 8f70b4
            {
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
              if (*decided !=raw)
Packit 8f70b4
                {
Packit 8f70b4
                  if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
Packit 8f70b4
                    {
Packit 8f70b4
                      if (*decided == not
Packit 8f70b4
                          && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
Packit 8f70b4
                                     month_name[cnt]))
Packit 8f70b4
                        *decided = loc;
Packit 8f70b4
                      break;
Packit 8f70b4
                    }
Packit 8f70b4
                  if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
Packit 8f70b4
                    {
Packit 8f70b4
                      if (*decided == not
Packit 8f70b4
                          && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
Packit 8f70b4
                                     ab_month_name[cnt]))
Packit 8f70b4
                        *decided = loc;
Packit 8f70b4
                      break;
Packit 8f70b4
                    }
Packit 8f70b4
                }
Packit 8f70b4
#endif
Packit 8f70b4
              if (match_string (month_name[cnt], rp)
Packit 8f70b4
                  || match_string (ab_month_name[cnt], rp))
Packit 8f70b4
                {
Packit 8f70b4
                  *decided = raw;
Packit 8f70b4
                  break;
Packit 8f70b4
                }
Packit 8f70b4
            }
Packit 8f70b4
          if (cnt == 12)
Packit 8f70b4
            /* Does not match a month name.  */
Packit 8f70b4
            return NULL;
Packit 8f70b4
          tm->tm_mon = cnt;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'c':
Packit 8f70b4
          /* Match locale's date and time format.  */
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
          if (*decided != raw)
Packit 8f70b4
            {
Packit 8f70b4
              if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
Packit 8f70b4
                {
Packit 8f70b4
                  if (*decided == loc)
Packit 8f70b4
                    return NULL;
Packit 8f70b4
                  else
Packit 8f70b4
                    rp = rp_backup;
Packit 8f70b4
                }
Packit 8f70b4
              else
Packit 8f70b4
                {
Packit 8f70b4
                  if (*decided == not &&
Packit 8f70b4
                      strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
Packit 8f70b4
                    *decided = loc;
Packit 8f70b4
                  want_xday = 1;
Packit 8f70b4
                  break;
Packit 8f70b4
                }
Packit 8f70b4
              *decided = raw;
Packit 8f70b4
            }
Packit 8f70b4
#endif
Packit 8f70b4
          if (!recursive (HERE_D_T_FMT))
Packit 8f70b4
            return NULL;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'C':
Packit 8f70b4
          /* Match century number.  */
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
        match_century:
Packit 8f70b4
#endif
Packit 8f70b4
          get_number (0, 99, 2);
Packit 8f70b4
          century = val;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'd':
Packit 8f70b4
        case 'e':
Packit 8f70b4
          /* Match day of month.  */
Packit 8f70b4
          get_number (1, 31, 2);
Packit 8f70b4
          tm->tm_mday = val;
Packit 8f70b4
          have_mday = 1;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'F':
Packit 8f70b4
          if (!recursive ("%Y-%m-%d"))
Packit 8f70b4
            return NULL;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'x':
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
          if (*decided != raw)
Packit 8f70b4
            {
Packit 8f70b4
              if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
Packit 8f70b4
                {
Packit 8f70b4
                  if (*decided == loc)
Packit 8f70b4
                    return NULL;
Packit 8f70b4
                  else
Packit 8f70b4
                    rp = rp_backup;
Packit 8f70b4
                }
Packit 8f70b4
              else
Packit 8f70b4
                {
Packit 8f70b4
                  if (*decided == not
Packit 8f70b4
                      && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
Packit 8f70b4
                    *decided = loc;
Packit 8f70b4
                  want_xday = 1;
Packit 8f70b4
                  break;
Packit 8f70b4
                }
Packit 8f70b4
              *decided = raw;
Packit 8f70b4
            }
Packit 8f70b4
#endif
Packit 8f70b4
          /* Fall through.  */
Packit 8f70b4
        case 'D':
Packit 8f70b4
          /* Match standard day format.  */
Packit 8f70b4
          if (!recursive (HERE_D_FMT))
Packit 8f70b4
            return NULL;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'k':
Packit 8f70b4
        case 'H':
Packit 8f70b4
          /* Match hour in 24-hour clock.  */
Packit 8f70b4
          get_number (0, 23, 2);
Packit 8f70b4
          tm->tm_hour = val;
Packit 8f70b4
          have_I = 0;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'l':
Packit 8f70b4
          /* Match hour in 12-hour clock.  GNU extension.  */
Packit 8f70b4
        case 'I':
Packit 8f70b4
          /* Match hour in 12-hour clock.  */
Packit 8f70b4
          get_number (1, 12, 2);
Packit 8f70b4
          tm->tm_hour = val % 12;
Packit 8f70b4
          have_I = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'j':
Packit 8f70b4
          /* Match day number of year.  */
Packit 8f70b4
          get_number (1, 366, 3);
Packit 8f70b4
          tm->tm_yday = val - 1;
Packit 8f70b4
          have_yday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'm':
Packit 8f70b4
          /* Match number of month.  */
Packit 8f70b4
          get_number (1, 12, 2);
Packit 8f70b4
          tm->tm_mon = val - 1;
Packit 8f70b4
          have_mon = 1;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'M':
Packit 8f70b4
          /* Match minute.  */
Packit 8f70b4
          get_number (0, 59, 2);
Packit 8f70b4
          tm->tm_min = val;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'n':
Packit 8f70b4
        case 't':
Packit 8f70b4
          /* Match any white space.  */
Packit 8f70b4
          while (ISSPACE (*rp))
Packit 8f70b4
            ++rp;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'p':
Packit 8f70b4
          /* Match locale's equivalent of AM/PM.  */
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
          if (*decided != raw)
Packit 8f70b4
            {
Packit 8f70b4
              if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
Packit 8f70b4
                {
Packit 8f70b4
                  if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
Packit 8f70b4
                    *decided = loc;
Packit 8f70b4
                  break;
Packit 8f70b4
                }
Packit 8f70b4
              if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
Packit 8f70b4
                {
Packit 8f70b4
                  if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
Packit 8f70b4
                    *decided = loc;
Packit 8f70b4
                  is_pm = 1;
Packit 8f70b4
                  break;
Packit 8f70b4
                }
Packit 8f70b4
              *decided = raw;
Packit 8f70b4
            }
Packit 8f70b4
#endif
Packit 8f70b4
          if (!match_string (HERE_AM_STR, rp))
Packit 8f70b4
            {
Packit 8f70b4
              if (match_string (HERE_PM_STR, rp))
Packit 8f70b4
                is_pm = 1;
Packit 8f70b4
              else
Packit 8f70b4
                return NULL;
Packit 8f70b4
            }
Packit 8f70b4
          break;
Packit 8f70b4
        case 'q':
Packit 8f70b4
          /* Match quarter of year.  GNU extension.  */
Packit 8f70b4
          get_number (1, 4, 1);
Packit 8f70b4
          tm->tm_mon = (val - 1) * 3;
Packit 8f70b4
          tm->tm_mday = 1;
Packit 8f70b4
          have_mon = 1;
Packit 8f70b4
          have_mday = 1;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'r':
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
          if (*decided != raw)
Packit 8f70b4
            {
Packit 8f70b4
              if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
Packit 8f70b4
                {
Packit 8f70b4
                  if (*decided == loc)
Packit 8f70b4
                    return NULL;
Packit 8f70b4
                  else
Packit 8f70b4
                    rp = rp_backup;
Packit 8f70b4
                }
Packit 8f70b4
              else
Packit 8f70b4
                {
Packit 8f70b4
                  if (*decided == not &&
Packit 8f70b4
                      strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
Packit 8f70b4
                              HERE_T_FMT_AMPM))
Packit 8f70b4
                    *decided = loc;
Packit 8f70b4
                  break;
Packit 8f70b4
                }
Packit 8f70b4
              *decided = raw;
Packit 8f70b4
            }
Packit 8f70b4
#endif
Packit 8f70b4
          if (!recursive (HERE_T_FMT_AMPM))
Packit 8f70b4
            return NULL;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'R':
Packit 8f70b4
          if (!recursive ("%H:%M"))
Packit 8f70b4
            return NULL;
Packit 8f70b4
          break;
Packit 8f70b4
        case 's':
Packit 8f70b4
          {
Packit 8f70b4
            /* The number of seconds may be very high so we cannot use
Packit 8f70b4
               the 'get_number' macro.  Instead read the number
Packit 8f70b4
               character for character and construct the result while
Packit 8f70b4
               doing this.  */
Packit 8f70b4
            time_t secs = 0;
Packit 8f70b4
            if (*rp < '0' || *rp > '9')
Packit 8f70b4
              /* We need at least one digit.  */
Packit 8f70b4
              return NULL;
Packit 8f70b4
Packit 8f70b4
            do
Packit 8f70b4
              {
Packit 8f70b4
                secs *= 10;
Packit 8f70b4
                secs += *rp++ - '0';
Packit 8f70b4
              }
Packit 8f70b4
            while (*rp >= '0' && *rp <= '9');
Packit 8f70b4
Packit 8f70b4
            if (localtime_r (&secs, tm) == NULL)
Packit 8f70b4
              /* Error in function.  */
Packit 8f70b4
              return NULL;
Packit 8f70b4
          }
Packit 8f70b4
          break;
Packit 8f70b4
        case 'S':
Packit 8f70b4
          get_number (0, 61, 2);
Packit 8f70b4
          tm->tm_sec = val;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'X':
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
          if (*decided != raw)
Packit 8f70b4
            {
Packit 8f70b4
              if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
Packit 8f70b4
                {
Packit 8f70b4
                  if (*decided == loc)
Packit 8f70b4
                    return NULL;
Packit 8f70b4
                  else
Packit 8f70b4
                    rp = rp_backup;
Packit 8f70b4
                }
Packit 8f70b4
              else
Packit 8f70b4
                {
Packit 8f70b4
                  if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
Packit 8f70b4
                    *decided = loc;
Packit 8f70b4
                  break;
Packit 8f70b4
                }
Packit 8f70b4
              *decided = raw;
Packit 8f70b4
            }
Packit 8f70b4
#endif
Packit 8f70b4
          /* Fall through.  */
Packit 8f70b4
        case 'T':
Packit 8f70b4
          if (!recursive (HERE_T_FMT))
Packit 8f70b4
            return NULL;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'u':
Packit 8f70b4
          get_number (1, 7, 1);
Packit 8f70b4
          tm->tm_wday = val % 7;
Packit 8f70b4
          have_wday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'g':
Packit 8f70b4
          get_number (0, 99, 2);
Packit 8f70b4
          /* XXX This cannot determine any field in TM.  */
Packit 8f70b4
          break;
Packit 8f70b4
        case 'G':
Packit 8f70b4
          if (*rp < '0' || *rp > '9')
Packit 8f70b4
            return NULL;
Packit 8f70b4
          /* XXX Ignore the number since we would need some more
Packit 8f70b4
             information to compute a real date.  */
Packit 8f70b4
          do
Packit 8f70b4
            ++rp;
Packit 8f70b4
          while (*rp >= '0' && *rp <= '9');
Packit 8f70b4
          break;
Packit 8f70b4
        case 'U':
Packit 8f70b4
          get_number (0, 53, 2);
Packit 8f70b4
          week_no = val;
Packit 8f70b4
          have_uweek = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'W':
Packit 8f70b4
          get_number (0, 53, 2);
Packit 8f70b4
          week_no = val;
Packit 8f70b4
          have_wweek = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'V':
Packit 8f70b4
          get_number (0, 53, 2);
Packit 8f70b4
          /* XXX This cannot determine any field in TM without some
Packit 8f70b4
             information.  */
Packit 8f70b4
          break;
Packit 8f70b4
        case 'w':
Packit 8f70b4
          /* Match number of weekday.  */
Packit 8f70b4
          get_number (0, 6, 1);
Packit 8f70b4
          tm->tm_wday = val;
Packit 8f70b4
          have_wday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'y':
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
        match_year_in_century:
Packit 8f70b4
#endif
Packit 8f70b4
          /* Match year within century.  */
Packit 8f70b4
          get_number (0, 99, 2);
Packit 8f70b4
          /* The "Year 2000: The Millennium Rollover" paper suggests that
Packit 8f70b4
             values in the range 69-99 refer to the twentieth century.  */
Packit 8f70b4
          tm->tm_year = val >= 69 ? val : val + 100;
Packit 8f70b4
          /* Indicate that we want to use the century, if specified.  */
Packit 8f70b4
          want_century = 1;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'Y':
Packit 8f70b4
          /* Match year including century number.  */
Packit 8f70b4
          get_number (0, 9999, 4);
Packit 8f70b4
          tm->tm_year = val - 1900;
Packit 8f70b4
          want_century = 0;
Packit 8f70b4
          want_xday = 1;
Packit 8f70b4
          break;
Packit 8f70b4
        case 'Z':
Packit 8f70b4
          /* XXX How to handle this?  */
Packit 8f70b4
          break;
Packit 8f70b4
        case 'z':
Packit 8f70b4
          /* We recognize two formats: if two digits are given, these
Packit 8f70b4
             specify hours.  If fours digits are used, minutes are
Packit 8f70b4
             also specified.  */
Packit 8f70b4
          {
Packit 8f70b4
            bool neg _GL_UNUSED;
Packit 8f70b4
            int n;
Packit 8f70b4
Packit 8f70b4
            val = 0;
Packit 8f70b4
            while (*rp == ' ')
Packit 8f70b4
              ++rp;
Packit 8f70b4
            if (*rp != '+' && *rp != '-')
Packit 8f70b4
              return NULL;
Packit 8f70b4
            neg = *rp++ == '-';
Packit 8f70b4
            n = 0;
Packit 8f70b4
            while (n < 4 && *rp >= '0' && *rp <= '9')
Packit 8f70b4
              {
Packit 8f70b4
                val = val * 10 + *rp++ - '0';
Packit 8f70b4
                ++n;
Packit 8f70b4
              }
Packit 8f70b4
            if (n == 2)
Packit 8f70b4
              val *= 100;
Packit 8f70b4
            else if (n != 4)
Packit 8f70b4
              /* Only two or four digits recognized.  */
Packit 8f70b4
              return NULL;
Packit 8f70b4
            else
Packit 8f70b4
              {
Packit 8f70b4
                /* We have to convert the minutes into decimal.  */
Packit 8f70b4
                if (val % 100 >= 60)
Packit 8f70b4
                  return NULL;
Packit 8f70b4
                val = (val / 100) * 100 + ((val % 100) * 50) / 30;
Packit 8f70b4
              }
Packit 8f70b4
            if (val > 1200)
Packit 8f70b4
              return NULL;
Packit 8f70b4
#if defined _LIBC || HAVE_TM_GMTOFF
Packit 8f70b4
            tm->tm_gmtoff = (val * 3600) / 100;
Packit 8f70b4
            if (neg)
Packit 8f70b4
              tm->tm_gmtoff = -tm->tm_gmtoff;
Packit 8f70b4
#endif
Packit 8f70b4
          }
Packit 8f70b4
          break;
Packit 8f70b4
        case 'E':
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
          switch (*fmt++)
Packit 8f70b4
            {
Packit 8f70b4
            case 'c':
Packit 8f70b4
              /* Match locale's alternate date and time format.  */
Packit 8f70b4
              if (*decided != raw)
Packit 8f70b4
                {
Packit 8f70b4
                  const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
Packit 8f70b4
Packit 8f70b4
                  if (*fmt == '\0')
Packit 8f70b4
                    fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
Packit 8f70b4
Packit 8f70b4
                  if (!recursive (fmt))
Packit 8f70b4
                    {
Packit 8f70b4
                      if (*decided == loc)
Packit 8f70b4
                        return NULL;
Packit 8f70b4
                      else
Packit 8f70b4
                        rp = rp_backup;
Packit 8f70b4
                    }
Packit 8f70b4
                  else
Packit 8f70b4
                    {
Packit 8f70b4
                      if (strcmp (fmt, HERE_D_T_FMT))
Packit 8f70b4
                        *decided = loc;
Packit 8f70b4
                      want_xday = 1;
Packit 8f70b4
                      break;
Packit 8f70b4
                    }
Packit 8f70b4
                  *decided = raw;
Packit 8f70b4
                }
Packit 8f70b4
              /* The C locale has no era information, so use the
Packit 8f70b4
                 normal representation.  */
Packit 8f70b4
              if (!recursive (HERE_D_T_FMT))
Packit 8f70b4
                return NULL;
Packit 8f70b4
              want_xday = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'C':
Packit 8f70b4
              if (*decided != raw)
Packit 8f70b4
                {
Packit 8f70b4
                  if (era_cnt >= 0)
Packit 8f70b4
                    {
Packit 8f70b4
                      era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
Packit 8f70b4
                      if (era != NULL && match_string (era->era_name, rp))
Packit 8f70b4
                        {
Packit 8f70b4
                          *decided = loc;
Packit 8f70b4
                          break;
Packit 8f70b4
                        }
Packit 8f70b4
                      else
Packit 8f70b4
                        return NULL;
Packit 8f70b4
                    }
Packit 8f70b4
Packit 8f70b4
                  num_eras = _NL_CURRENT_WORD (LC_TIME,
Packit 8f70b4
                                               _NL_TIME_ERA_NUM_ENTRIES);
Packit 8f70b4
                  for (era_cnt = 0; era_cnt < (int) num_eras;
Packit 8f70b4
                       ++era_cnt, rp = rp_backup)
Packit 8f70b4
                    {
Packit 8f70b4
                      era = _nl_select_era_entry (era_cnt
Packit 8f70b4
                                                  HELPER_LOCALE_ARG);
Packit 8f70b4
                      if (era != NULL && match_string (era->era_name, rp))
Packit 8f70b4
                        {
Packit 8f70b4
                          *decided = loc;
Packit 8f70b4
                          break;
Packit 8f70b4
                        }
Packit 8f70b4
                    }
Packit 8f70b4
                  if (era_cnt != (int) num_eras)
Packit 8f70b4
                    break;
Packit 8f70b4
Packit 8f70b4
                  era_cnt = -1;
Packit 8f70b4
                  if (*decided == loc)
Packit 8f70b4
                    return NULL;
Packit 8f70b4
Packit 8f70b4
                  *decided = raw;
Packit 8f70b4
                }
Packit 8f70b4
              /* The C locale has no era information, so use the
Packit 8f70b4
                 normal representation.  */
Packit 8f70b4
              goto match_century;
Packit 8f70b4
            case 'y':
Packit 8f70b4
              if (*decided != raw)
Packit 8f70b4
                {
Packit 8f70b4
                  get_number(0, 9999, 4);
Packit 8f70b4
                  tm->tm_year = val;
Packit 8f70b4
                  want_era = 1;
Packit 8f70b4
                  want_xday = 1;
Packit 8f70b4
                  want_century = 1;
Packit 8f70b4
Packit 8f70b4
                  if (era_cnt >= 0)
Packit 8f70b4
                    {
Packit 8f70b4
                      assert (*decided == loc);
Packit 8f70b4
Packit 8f70b4
                      era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
Packit 8f70b4
                      bool match = false;
Packit 8f70b4
                      if (era != NULL)
Packit 8f70b4
                        {
Packit 8f70b4
                          int delta = ((tm->tm_year - era->offset)
Packit 8f70b4
                                       * era->absolute_direction);
Packit 8f70b4
                          match = (delta >= 0
Packit 8f70b4
                                   && delta < (((int64_t) era->stop_date[0]
Packit 8f70b4
                                                - (int64_t) era->start_date[0])
Packit 8f70b4
                                               * era->absolute_direction));
Packit 8f70b4
                        }
Packit 8f70b4
                      if (! match)
Packit 8f70b4
                        return NULL;
Packit 8f70b4
Packit 8f70b4
                      break;
Packit 8f70b4
                    }
Packit 8f70b4
Packit 8f70b4
                  num_eras = _NL_CURRENT_WORD (LC_TIME,
Packit 8f70b4
                                               _NL_TIME_ERA_NUM_ENTRIES);
Packit 8f70b4
                  for (era_cnt = 0; era_cnt < (int) num_eras; ++era_cnt)
Packit 8f70b4
                    {
Packit 8f70b4
                      era = _nl_select_era_entry (era_cnt
Packit 8f70b4
                                                  HELPER_LOCALE_ARG);
Packit 8f70b4
                      if (era != NULL)
Packit 8f70b4
                        {
Packit 8f70b4
                          int delta = ((tm->tm_year - era->offset)
Packit 8f70b4
                                       * era->absolute_direction);
Packit 8f70b4
                          if (delta >= 0
Packit 8f70b4
                              && delta < (((int64_t) era->stop_date[0]
Packit 8f70b4
                                           - (int64_t) era->start_date[0])
Packit 8f70b4
                                          * era->absolute_direction))
Packit 8f70b4
                            {
Packit 8f70b4
                              *decided = loc;
Packit 8f70b4
                              break;
Packit 8f70b4
                            }
Packit 8f70b4
                        }
Packit 8f70b4
                    }
Packit 8f70b4
                  if (era_cnt != (int) num_eras)
Packit 8f70b4
                    break;
Packit 8f70b4
Packit 8f70b4
                  era_cnt = -1;
Packit 8f70b4
                  if (*decided == loc)
Packit 8f70b4
                    return NULL;
Packit 8f70b4
Packit 8f70b4
                  *decided = raw;
Packit 8f70b4
                }
Packit 8f70b4
Packit 8f70b4
              goto match_year_in_century;
Packit 8f70b4
            case 'Y':
Packit 8f70b4
              if (*decided != raw)
Packit 8f70b4
                {
Packit 8f70b4
                  num_eras = _NL_CURRENT_WORD (LC_TIME,
Packit 8f70b4
                                               _NL_TIME_ERA_NUM_ENTRIES);
Packit 8f70b4
                  for (era_cnt = 0; era_cnt < (int) num_eras;
Packit 8f70b4
                       ++era_cnt, rp = rp_backup)
Packit 8f70b4
                    {
Packit 8f70b4
                      era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
Packit 8f70b4
                      if (era != NULL && recursive (era->era_format))
Packit 8f70b4
                        break;
Packit 8f70b4
                    }
Packit 8f70b4
                  if (era_cnt == (int) num_eras)
Packit 8f70b4
                    {
Packit 8f70b4
                      era_cnt = -1;
Packit 8f70b4
                      if (*decided == loc)
Packit 8f70b4
                        return NULL;
Packit 8f70b4
                      else
Packit 8f70b4
                        rp = rp_backup;
Packit 8f70b4
                    }
Packit 8f70b4
                  else
Packit 8f70b4
                    {
Packit 8f70b4
                      *decided = loc;
Packit 8f70b4
                      era_cnt = -1;
Packit 8f70b4
                      break;
Packit 8f70b4
                    }
Packit 8f70b4
Packit 8f70b4
                  *decided = raw;
Packit 8f70b4
                }
Packit 8f70b4
              get_number (0, 9999, 4);
Packit 8f70b4
              tm->tm_year = val - 1900;
Packit 8f70b4
              want_century = 0;
Packit 8f70b4
              want_xday = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'x':
Packit 8f70b4
              if (*decided != raw)
Packit 8f70b4
                {
Packit 8f70b4
                  const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
Packit 8f70b4
Packit 8f70b4
                  if (*fmt == '\0')
Packit 8f70b4
                    fmt = _NL_CURRENT (LC_TIME, D_FMT);
Packit 8f70b4
Packit 8f70b4
                  if (!recursive (fmt))
Packit 8f70b4
                    {
Packit 8f70b4
                      if (*decided == loc)
Packit 8f70b4
                        return NULL;
Packit 8f70b4
                      else
Packit 8f70b4
                        rp = rp_backup;
Packit 8f70b4
                    }
Packit 8f70b4
                  else
Packit 8f70b4
                    {
Packit 8f70b4
                      if (strcmp (fmt, HERE_D_FMT))
Packit 8f70b4
                        *decided = loc;
Packit 8f70b4
                      break;
Packit 8f70b4
                    }
Packit 8f70b4
                  *decided = raw;
Packit 8f70b4
                }
Packit 8f70b4
              if (!recursive (HERE_D_FMT))
Packit 8f70b4
                return NULL;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'X':
Packit 8f70b4
              if (*decided != raw)
Packit 8f70b4
                {
Packit 8f70b4
                  const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
Packit 8f70b4
Packit 8f70b4
                  if (*fmt == '\0')
Packit 8f70b4
                    fmt = _NL_CURRENT (LC_TIME, T_FMT);
Packit 8f70b4
Packit 8f70b4
                  if (!recursive (fmt))
Packit 8f70b4
                    {
Packit 8f70b4
                      if (*decided == loc)
Packit 8f70b4
                        return NULL;
Packit 8f70b4
                      else
Packit 8f70b4
                        rp = rp_backup;
Packit 8f70b4
                    }
Packit 8f70b4
                  else
Packit 8f70b4
                    {
Packit 8f70b4
                      if (strcmp (fmt, HERE_T_FMT))
Packit 8f70b4
                        *decided = loc;
Packit 8f70b4
                      break;
Packit 8f70b4
                    }
Packit 8f70b4
                  *decided = raw;
Packit 8f70b4
                }
Packit 8f70b4
              if (!recursive (HERE_T_FMT))
Packit 8f70b4
                return NULL;
Packit 8f70b4
              break;
Packit 8f70b4
            default:
Packit 8f70b4
              return NULL;
Packit 8f70b4
            }
Packit 8f70b4
          break;
Packit 8f70b4
#else
Packit 8f70b4
          /* We have no information about the era format.  Just use
Packit 8f70b4
             the normal format.  */
Packit 8f70b4
          if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
Packit 8f70b4
              && *fmt != 'x' && *fmt != 'X')
Packit 8f70b4
            /* This is an illegal format.  */
Packit 8f70b4
            return NULL;
Packit 8f70b4
Packit 8f70b4
          goto start_over;
Packit 8f70b4
#endif
Packit 8f70b4
        case 'O':
Packit 8f70b4
          switch (*fmt++)
Packit 8f70b4
            {
Packit 8f70b4
            case 'd':
Packit 8f70b4
            case 'e':
Packit 8f70b4
              /* Match day of month using alternate numeric symbols.  */
Packit 8f70b4
              get_alt_number (1, 31, 2);
Packit 8f70b4
              tm->tm_mday = val;
Packit 8f70b4
              have_mday = 1;
Packit 8f70b4
              want_xday = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'H':
Packit 8f70b4
              /* Match hour in 24-hour clock using alternate numeric
Packit 8f70b4
                 symbols.  */
Packit 8f70b4
              get_alt_number (0, 23, 2);
Packit 8f70b4
              tm->tm_hour = val;
Packit 8f70b4
              have_I = 0;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'I':
Packit 8f70b4
              /* Match hour in 12-hour clock using alternate numeric
Packit 8f70b4
                 symbols.  */
Packit 8f70b4
              get_alt_number (1, 12, 2);
Packit 8f70b4
              tm->tm_hour = val % 12;
Packit 8f70b4
              have_I = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'm':
Packit 8f70b4
              /* Match month using alternate numeric symbols.  */
Packit 8f70b4
              get_alt_number (1, 12, 2);
Packit 8f70b4
              tm->tm_mon = val - 1;
Packit 8f70b4
              have_mon = 1;
Packit 8f70b4
              want_xday = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'M':
Packit 8f70b4
              /* Match minutes using alternate numeric symbols.  */
Packit 8f70b4
              get_alt_number (0, 59, 2);
Packit 8f70b4
              tm->tm_min = val;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'q':
Packit 8f70b4
              /* Match quarter using alternate numeric symbols.  */
Packit 8f70b4
              get_alt_number (1, 4, 1);
Packit 8f70b4
              tm->tm_mon = (val - 1) * 3;
Packit 8f70b4
              tm->tm_mday = 1;
Packit 8f70b4
              have_mon = 1;
Packit 8f70b4
              have_mday = 1;
Packit 8f70b4
              want_xday = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'S':
Packit 8f70b4
              /* Match seconds using alternate numeric symbols.  */
Packit 8f70b4
              get_alt_number (0, 61, 2);
Packit 8f70b4
              tm->tm_sec = val;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'U':
Packit 8f70b4
              get_alt_number (0, 53, 2);
Packit 8f70b4
              week_no = val;
Packit 8f70b4
              have_uweek = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'W':
Packit 8f70b4
              get_alt_number (0, 53, 2);
Packit 8f70b4
              week_no = val;
Packit 8f70b4
              have_wweek = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'V':
Packit 8f70b4
              get_alt_number (0, 53, 2);
Packit 8f70b4
              /* XXX This cannot determine any field in TM without
Packit 8f70b4
                 further information.  */
Packit 8f70b4
              break;
Packit 8f70b4
            case 'w':
Packit 8f70b4
              /* Match number of weekday using alternate numeric symbols.  */
Packit 8f70b4
              get_alt_number (0, 6, 1);
Packit 8f70b4
              tm->tm_wday = val;
Packit 8f70b4
              have_wday = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            case 'y':
Packit 8f70b4
              /* Match year within century using alternate numeric symbols.  */
Packit 8f70b4
              get_alt_number (0, 99, 2);
Packit 8f70b4
              tm->tm_year = val >= 69 ? val : val + 100;
Packit 8f70b4
              want_xday = 1;
Packit 8f70b4
              break;
Packit 8f70b4
            default:
Packit 8f70b4
              return NULL;
Packit 8f70b4
            }
Packit 8f70b4
          break;
Packit 8f70b4
        default:
Packit 8f70b4
          return NULL;
Packit 8f70b4
        }
Packit 8f70b4
    }
Packit 8f70b4
Packit 8f70b4
  if (have_I && is_pm)
Packit 8f70b4
    tm->tm_hour += 12;
Packit 8f70b4
Packit 8f70b4
  if (century != -1)
Packit 8f70b4
    {
Packit 8f70b4
      if (want_century)
Packit 8f70b4
        tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
Packit 8f70b4
      else
Packit 8f70b4
        /* Only the century, but not the year.  Strange, but so be it.  */
Packit 8f70b4
        tm->tm_year = (century - 19) * 100;
Packit 8f70b4
    }
Packit 8f70b4
Packit 8f70b4
  if (era_cnt != -1)
Packit 8f70b4
    {
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
      era = _nl_select_era_entry (era_cnt HELPER_LOCALE_ARG);
Packit 8f70b4
      if (era == NULL)
Packit 8f70b4
        return NULL;
Packit 8f70b4
      if (want_era)
Packit 8f70b4
        tm->tm_year = (era->start_date[0]
Packit 8f70b4
                       + ((tm->tm_year - era->offset)
Packit 8f70b4
                          * era->absolute_direction));
Packit 8f70b4
      else
Packit 8f70b4
        /* Era start year assumed.  */
Packit 8f70b4
        tm->tm_year = era->start_date[0];
Packit 8f70b4
#endif
Packit 8f70b4
    }
Packit 8f70b4
  else
Packit 8f70b4
    if (want_era)
Packit 8f70b4
      {
Packit 8f70b4
        /* No era found but we have seen an E modifier.  Rectify some
Packit 8f70b4
           values.  */
Packit 8f70b4
        if (want_century && century == -1 && tm->tm_year < 69)
Packit 8f70b4
          tm->tm_year += 100;
Packit 8f70b4
      }
Packit 8f70b4
Packit 8f70b4
  if (want_xday && !have_wday)
Packit 8f70b4
    {
Packit 8f70b4
      if ( !(have_mon && have_mday) && have_yday)
Packit 8f70b4
        {
Packit 8f70b4
          /* We don't have tm_mon and/or tm_mday, compute them.  */
Packit 8f70b4
          int t_mon = 0;
Packit 8f70b4
          while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
Packit 8f70b4
              t_mon++;
Packit 8f70b4
          if (!have_mon)
Packit 8f70b4
              tm->tm_mon = t_mon - 1;
Packit 8f70b4
          if (!have_mday)
Packit 8f70b4
              tm->tm_mday =
Packit 8f70b4
                (tm->tm_yday
Packit 8f70b4
                 - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
Packit 8f70b4
        }
Packit 8f70b4
      day_of_the_week (tm);
Packit 8f70b4
    }
Packit 8f70b4
Packit 8f70b4
  if (want_xday && !have_yday)
Packit 8f70b4
    day_of_the_year (tm);
Packit 8f70b4
Packit 8f70b4
  if ((have_uweek || have_wweek) && have_wday)
Packit 8f70b4
    {
Packit 8f70b4
      int save_wday = tm->tm_wday;
Packit 8f70b4
      int save_mday = tm->tm_mday;
Packit 8f70b4
      int save_mon = tm->tm_mon;
Packit 8f70b4
      int w_offset = have_uweek ? 0 : 1;
Packit 8f70b4
Packit 8f70b4
      tm->tm_mday = 1;
Packit 8f70b4
      tm->tm_mon = 0;
Packit 8f70b4
      day_of_the_week (tm);
Packit 8f70b4
      if (have_mday)
Packit 8f70b4
        tm->tm_mday = save_mday;
Packit 8f70b4
      if (have_mon)
Packit 8f70b4
        tm->tm_mon = save_mon;
Packit 8f70b4
Packit 8f70b4
      if (!have_yday)
Packit 8f70b4
        tm->tm_yday = ((7 - (tm->tm_wday - w_offset)) % 7
Packit 8f70b4
                       + (week_no - 1) *7
Packit 8f70b4
                       + save_wday - w_offset);
Packit 8f70b4
Packit 8f70b4
      if (!have_mday || !have_mon)
Packit 8f70b4
        {
Packit 8f70b4
          int t_mon = 0;
Packit 8f70b4
          while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon]
Packit 8f70b4
                 <= tm->tm_yday)
Packit 8f70b4
            t_mon++;
Packit 8f70b4
          if (!have_mon)
Packit 8f70b4
            tm->tm_mon = t_mon - 1;
Packit 8f70b4
          if (!have_mday)
Packit 8f70b4
              tm->tm_mday =
Packit 8f70b4
                (tm->tm_yday
Packit 8f70b4
                 - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1);
Packit 8f70b4
        }
Packit 8f70b4
Packit 8f70b4
      tm->tm_wday = save_wday;
Packit 8f70b4
    }
Packit 8f70b4
Packit 8f70b4
  return (char *) rp;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
char *
Packit 8f70b4
strptime (buf, format, tm LOCALE_PARAM)
Packit 8f70b4
     const char *restrict buf;
Packit 8f70b4
     const char *restrict format;
Packit 8f70b4
     struct tm *restrict tm;
Packit 8f70b4
     LOCALE_PARAM_DECL
Packit 8f70b4
{
Packit 8f70b4
  enum ptime_locale_status decided;
Packit 8f70b4
Packit 8f70b4
#ifdef _NL_CURRENT
Packit 8f70b4
  decided = not;
Packit 8f70b4
#else
Packit 8f70b4
  decided = raw;
Packit 8f70b4
#endif
Packit 8f70b4
  return __strptime_internal (buf, format, tm, &decided, -1 LOCALE_ARG);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
#ifdef _LIBC
Packit 8f70b4
weak_alias (__strptime_l, strptime_l)
Packit 8f70b4
#endif