Blame lib/strptime.c

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