Blame lib/strptime.c

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