Blame time/strptime_l.c

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