Blame lib/strptime.c

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