Merge "Sync strptime.c with upstream."

This commit is contained in:
Elliott Hughes 2023-01-23 22:04:29 +00:00 committed by Gerrit Code Review
commit 98c641b096
6 changed files with 658 additions and 402 deletions

View file

@ -252,7 +252,10 @@ cc_library_static {
srcs: [
"tzcode/**/*.c",
"tzcode/bionic.cpp",
"upstream-openbsd/lib/libc/time/wcsftime.c", // tzcode doesn't include wcsftime, so we use the OpenBSD one.
// tzcode doesn't include strptime or wcsftime, so we use the OpenBSD
// code (with some local changes in the strptime case).
"upstream-openbsd/lib/libc/locale/_def_time.c",
"upstream-openbsd/lib/libc/time/wcsftime.c",
],
cflags: [
@ -1198,6 +1201,7 @@ cc_library_static {
"bionic/termios.cpp",
"bionic/thread_private.cpp",
"bionic/threads.cpp",
"bionic/time_l.cpp",
"bionic/timespec_get.cpp",
"bionic/tmpfile.cpp",
"bionic/umount.cpp",

View file

@ -2579,6 +2579,36 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1994 Winning Strategies, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by Winning Strategies, Inc.
4. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1996 by Internet Software Consortium.
Permission to use, copy, modify, and distribute this software for any
@ -2779,41 +2809,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
All rights reserved.
This code was contributed to The NetBSD Foundation by Klaus Klein.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the NetBSD
Foundation, Inc. and its contributors.
4. Neither the name of The NetBSD Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1997, 1998, 1999, 2004 The NetBSD Foundation, Inc.
All rights reserved.
@ -2879,6 +2874,34 @@ POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc.
All rights reserved.
This code was contributed to The NetBSD Foundation by Klaus Klein.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1997, 2005 Todd C. Miller <Todd.Miller@courtesan.com>
Permission to use, copy, modify, and distribute this software for any

34
libc/bionic/time_l.cpp Normal file
View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2022 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <time.h>
//#include <xlocale.h>
char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t) {
return strptime(buf, fmt, tm);
}

106
libc/tzcode/localedef.h Normal file
View file

@ -0,0 +1,106 @@
/* $OpenBSD: localedef.h,v 1.1 2016/05/23 00:05:15 guenther Exp $ */
/* $NetBSD: localedef.h,v 1.4 1996/04/09 20:55:31 cgd Exp $ */
/*
* Copyright (c) 1994 Winning Strategies, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Winning Strategies, Inc.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOCALEDEF_H_
#define _LOCALEDEF_H_
#include <sys/types.h>
typedef struct
{
char *yesexpr;
char *noexpr;
char *yesstr;
char *nostr;
} _MessagesLocale;
typedef struct
{
char *int_curr_symbol;
char *currency_symbol;
char *mon_decimal_point;
char *mon_thousands_sep;
char *mon_grouping;
char *positive_sign;
char *negative_sign;
char int_frac_digits;
char frac_digits;
char p_cs_precedes;
char p_sep_by_space;
char n_cs_precedes;
char n_sep_by_space;
char p_sign_posn;
char n_sign_posn;
char int_p_cs_precedes;
char int_p_sep_by_space;
char int_n_cs_precedes;
char int_n_sep_by_space;
char int_p_sign_posn;
char int_n_sign_posn;
} _MonetaryLocale;
typedef struct
{
const char *decimal_point;
const char *thousands_sep;
const char *grouping;
} _NumericLocale;
typedef struct {
const char *abday[7];
const char *day[7];
const char *abmon[12];
const char *mon[12];
const char *am_pm[2];
const char *d_t_fmt;
const char *d_fmt;
const char *t_fmt;
const char *t_fmt_ampm;
} _TimeLocale;
//__BEGIN_HIDDEN_DECLS
extern const _MessagesLocale *_CurrentMessagesLocale;
extern const _MessagesLocale _DefaultMessagesLocale;
extern const _MonetaryLocale *_CurrentMonetaryLocale;
extern const _MonetaryLocale _DefaultMonetaryLocale;
extern const _NumericLocale *_CurrentNumericLocale;
extern const _NumericLocale _DefaultNumericLocale;
extern const _TimeLocale *_CurrentTimeLocale;
extern const _TimeLocale _DefaultTimeLocale;
//__END_HIDDEN_DECLS
#endif /* !_LOCALEDEF_H_ */

View file

@ -1,8 +1,7 @@
/* $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $ */
/* $OpenBSD: strptime.c,v 1.30 2019/05/12 12:49:52 schwarze Exp $ */
/* $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $ */
/*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code was contributed to The NetBSD Foundation by Klaus Klein.
@ -15,13 +14,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@ -36,51 +28,23 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
//#include <sys/localedef.h>
#include <ctype.h>
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include "localedef.h"
#include "private.h"
#include "tzfile.h"
static const struct {
const char *abday[7];
const char *day[7];
const char *abmon[12];
const char *mon[12];
const char *am_pm[2];
const char *d_t_fmt;
const char *d_fmt;
const char *t_fmt;
const char *t_fmt_ampm;
} _DefaultTimeLocale = {
{
"Sun","Mon","Tue","Wed","Thu","Fri","Sat",
},
{
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"
},
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
},
{
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
},
{
"AM", "PM"
},
"%a %b %d %H:%M:%S %Y",
"%m/%d/%y",
"%H:%M:%S",
"%I:%M:%S %p"
};
// Android: ignore OpenBSD's DEF_WEAK() stuff.
#define DEF_WEAK(sym) /* */
// Android: this code is not pointer-sign clean.
#pragma clang diagnostic ignored "-Wpointer-sign"
#pragma clang diagnostic ignored "-Wunused-function"
#define _ctloc(x) (_DefaultTimeLocale.x)
#define _ctloc(x) (_CurrentTimeLocale->x)
/*
* We do not implement alternate representations. However, we always
@ -90,11 +54,14 @@ static const struct {
#define _ALT_O 0x02
#define _LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
struct century_relyear {
int century;
int relyear;
};
/*
* We keep track of some of the fields we set in order to compute missing ones.
*/
#define FIELD_TM_MON (1 << 0)
#define FIELD_TM_MDAY (1 << 1)
#define FIELD_TM_WDAY (1 << 2)
#define FIELD_TM_YDAY (1 << 3)
#define FIELD_TM_YEAR (1 << 4)
static char gmt[] = { "GMT" };
static char utc[] = { "UTC" };
@ -106,9 +73,15 @@ static const char * const nadt[5] = {
"EDT", "CDT", "MDT", "PDT", "\0\0\0"
};
static const int mon_lengths[2][MONSPERYEAR] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
static int _conv_num64(const unsigned char **, int64_t *, int64_t, int64_t);
static int _conv_num(const unsigned char **, int *, int, int);
static unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
struct century_relyear *);
static int leaps_thru_end_of(const int y);
static char *_strptime(const char *, const char *, struct tm *, int);
static const u_char *_find_string(const u_char *, int *, const char * const *,
const char * const *, int);
@ -116,22 +89,27 @@ static const u_char *_find_string(const u_char *, int *, const char * const *,
char *
strptime(const char *buf, const char *fmt, struct tm *tm)
{
struct century_relyear cr;
cr.century = TM_YEAR_BASE;
cr.relyear = -1;
return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
return(_strptime(buf, fmt, tm, 1));
}
DEF_WEAK(strptime);
static unsigned char *
_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
static char *
_strptime(const char *buf, const char *fmt, struct tm *tm, int initialize)
{
unsigned char c;
const unsigned char *bp, *ep;
size_t len = 0;
size_t len;
int alt_format, i, offs;
int neg = 0;
static int century, relyear, fields;
bp = (unsigned char *)buf;
if (initialize) {
century = TM_YEAR_BASE;
relyear = -1;
fields = 0;
}
bp = (const unsigned char *)buf;
while ((c = *fmt) != '\0') {
/* Clear `alternate' modifier prior to new conversion. */
alt_format = 0;
@ -176,55 +154,55 @@ literal:
*/
case 'c': /* Date and time, using the locale's format. */
_LEGAL_ALT(_ALT_E);
if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0)))
return (NULL);
break;
case 'D': /* The date as "%m/%d/%y". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0)))
return (NULL);
break;
case 'F': /* The date as "%Y-%m-%d". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%Y-%m-%d", tm, cr)))
if (!(bp = _strptime(bp, "%Y-%m-%d", tm, 0)))
return (NULL);
continue;
case 'R': /* The time as "%H:%M". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
if (!(bp = _strptime(bp, "%H:%M", tm, 0)))
return (NULL);
break;
case 'r': /* The time as "%I:%M:%S %p". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0)))
return (NULL);
break;
case 'T': /* The time as "%H:%M:%S". */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0)))
return (NULL);
break;
case 'v': /* The date as "%e-%b-%Y". */
case 'v': /* Android: the date as "%e-%b-%Y" for strftime() compat; glibc does this too. */
_LEGAL_ALT(0);
if (!(bp = _strptime(bp, "%e-%b-%Y", tm, cr)))
if (!(bp = _strptime(bp, "%e-%b-%Y", tm, 0)))
return (NULL);
break;
case 'X': /* The time, using the locale's format. */
_LEGAL_ALT(_ALT_E);
if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0)))
return (NULL);
break;
case 'x': /* The date, using the locale's format. */
_LEGAL_ALT(_ALT_E);
if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0)))
return (NULL);
break;
@ -237,12 +215,12 @@ literal:
for (i = 0; i < 7; i++) {
/* Full name. */
len = strlen(_ctloc(day[i]));
if (strncasecmp(_ctloc(day[i]), (const char*)bp, len) == 0)
if (strncasecmp(_ctloc(day[i]), bp, len) == 0)
break;
/* Abbreviated name. */
len = strlen(_ctloc(abday[i]));
if (strncasecmp(_ctloc(abday[i]), (const char*)bp, len) == 0)
if (strncasecmp(_ctloc(abday[i]), bp, len) == 0)
break;
}
@ -252,6 +230,7 @@ literal:
tm->tm_wday = i;
bp += len;
fields |= FIELD_TM_WDAY;
break;
case 'B': /* The month, using the locale's form. */
@ -261,12 +240,12 @@ literal:
for (i = 0; i < 12; i++) {
/* Full name. */
len = strlen(_ctloc(mon[i]));
if (strncasecmp(_ctloc(mon[i]), (const char*)bp, len) == 0)
if (strncasecmp(_ctloc(mon[i]), bp, len) == 0)
break;
/* Abbreviated name. */
len = strlen(_ctloc(abmon[i]));
if (strncasecmp(_ctloc(abmon[i]), (const char*)bp, len) == 0)
if (strncasecmp(_ctloc(abmon[i]), bp, len) == 0)
break;
}
@ -276,6 +255,7 @@ literal:
tm->tm_mon = i;
bp += len;
fields |= FIELD_TM_MON;
break;
case 'C': /* The century number. */
@ -283,14 +263,18 @@ literal:
if (!(_conv_num(&bp, &i, 0, 99)))
return (NULL);
cr->century = i * 100;
century = i * 100;
break;
case 'd': /* The day of month. */
case 'e':
case 'e': /* The day of month. */
if (isspace(*bp))
bp++;
/* FALLTHROUGH */
case 'd':
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
return (NULL);
fields |= FIELD_TM_MDAY;
break;
case 'k': /* The hour (24-hour clock representation). */
@ -316,6 +300,7 @@ literal:
if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
return (NULL);
tm->tm_yday--;
fields |= FIELD_TM_YDAY;
break;
case 'M': /* The minute. */
@ -329,14 +314,15 @@ literal:
if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
return (NULL);
tm->tm_mon--;
fields |= FIELD_TM_MON;
break;
case 'P':
case 'P': /* Android addition for strftime() compat; glibc does this too. */
case 'p': /* The locale's equivalent of AM/PM. */
_LEGAL_ALT(0);
/* AM? */
len = strlen(_ctloc(am_pm[0]));
if (strncasecmp(_ctloc(am_pm[0]), (const char*)bp, len) == 0) {
if (strncasecmp(_ctloc(am_pm[0]), bp, len) == 0) {
if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
return (NULL);
else if (tm->tm_hour == 12)
@ -347,7 +333,7 @@ literal:
}
/* PM? */
len = strlen(_ctloc(am_pm[1]));
if (strncasecmp(_ctloc(am_pm[1]), (const char*)bp, len) == 0) {
if (strncasecmp(_ctloc(am_pm[1]), bp, len) == 0) {
if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
return (NULL);
else if (tm->tm_hour < 12)
@ -362,29 +348,31 @@ literal:
case 'S': /* The seconds. */
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
if (!(_conv_num(&bp, &tm->tm_sec, 0, 60)))
return (NULL);
break;
case 's':
case 's': /* Seconds since epoch */
{
// Android addition, based on FreeBSD's implementation.
// Android change based on FreeBSD's implementation.
int saved_errno = errno;
errno = 0;
const unsigned char* old_bp = bp;
long n = strtol((const char*) bp, (char**) &bp, 10);
errno = saved_errno;
time_t t = n;
if (bp == old_bp || errno == ERANGE || ((long) t) != n) {
errno = saved_errno;
return NULL;
}
errno = saved_errno;
if (bp == old_bp || errno == ERANGE ||
((long) t) != n) return NULL;
if (localtime_r(&t, tm) == NULL) return NULL;
//int64_t i64;
//if (!(_conv_num64(&bp, &i64, 0, INT64_MAX)))
// return (NULL);
//if (!gmtime_r(&i64, tm))
// return (NULL);
fields = 0xffff; /* everything */
}
break;
case 'U': /* The week of year, beginning on sunday. */
case 'W': /* The week of year, beginning on monday. */
_LEGAL_ALT(_ALT_O);
@ -402,6 +390,7 @@ literal:
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
return (NULL);
fields |= FIELD_TM_WDAY;
break;
case 'u': /* The day of week, monday = 1. */
@ -409,6 +398,7 @@ literal:
if (!(_conv_num(&bp, &i, 1, 7)))
return (NULL);
tm->tm_wday = i % 7;
fields |= FIELD_TM_WDAY;
continue;
case 'g': /* The year corresponding to the ISO week
@ -436,13 +426,14 @@ literal:
if (!(_conv_num(&bp, &i, 0, 9999)))
return (NULL);
cr->relyear = -1;
relyear = -1;
tm->tm_year = i - TM_YEAR_BASE;
fields |= FIELD_TM_YEAR;
break;
case 'y': /* The year within the century (2 digits). */
_LEGAL_ALT(_ALT_E | _ALT_O);
if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
if (!(_conv_num(&bp, &relyear, 0, 99)))
return (NULL);
break;
@ -570,20 +561,56 @@ literal:
* We need to evaluate the two digit year spec (%y)
* last as we can get a century spec (%C) at any time.
*/
if (cr->relyear != -1) {
if (cr->century == TM_YEAR_BASE) {
if (cr->relyear <= 68)
tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
if (relyear != -1) {
if (century == TM_YEAR_BASE) {
if (relyear <= 68)
tm->tm_year = relyear + 2000 - TM_YEAR_BASE;
else
tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
tm->tm_year = relyear + 1900 - TM_YEAR_BASE;
} else {
tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
tm->tm_year = relyear + century - TM_YEAR_BASE;
}
fields |= FIELD_TM_YEAR;
}
/* Compute some missing values when possible. */
if (fields & FIELD_TM_YEAR) {
const int year = tm->tm_year + TM_YEAR_BASE;
const int *mon_lens = mon_lengths[isleap(year)];
if (!(fields & FIELD_TM_YDAY) &&
(fields & FIELD_TM_MON) && (fields & FIELD_TM_MDAY)) {
tm->tm_yday = tm->tm_mday - 1;
for (i = 0; i < tm->tm_mon; i++)
tm->tm_yday += mon_lens[i];
fields |= FIELD_TM_YDAY;
}
if (fields & FIELD_TM_YDAY) {
int days = tm->tm_yday;
if (!(fields & FIELD_TM_WDAY)) {
tm->tm_wday = EPOCH_WDAY +
((year - EPOCH_YEAR) % DAYSPERWEEK) *
(DAYSPERNYEAR % DAYSPERWEEK) +
leaps_thru_end_of(year - 1) -
leaps_thru_end_of(EPOCH_YEAR - 1) +
tm->tm_yday;
tm->tm_wday %= DAYSPERWEEK;
if (tm->tm_wday < 0)
tm->tm_wday += DAYSPERWEEK;
}
if (!(fields & FIELD_TM_MON)) {
tm->tm_mon = 0;
while (tm->tm_mon < MONSPERYEAR && days >= mon_lens[tm->tm_mon])
days -= mon_lens[tm->tm_mon++];
}
if (!(fields & FIELD_TM_MDAY))
tm->tm_mday = days + 1;
}
}
return (unsigned char*)bp;
return ((char *)bp);
}
static int
_conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
{
@ -607,6 +634,29 @@ _conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
return (1);
}
static int
_conv_num64(const unsigned char **buf, int64_t *dest, int64_t llim, int64_t ulim)
{
int result = 0;
int64_t rulim = ulim;
if (**buf < '0' || **buf > '9')
return (0);
/* we use rulim to break out of the loop when we run out of digits */
do {
result *= 10;
result += *(*buf)++ - '0';
rulim /= 10;
} while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
if (result < llim || result > ulim)
return (0);
*dest = result;
return (1);
}
static const u_char *
_find_string(const u_char *bp, int *tgt, const char * const *n1,
const char * const *n2, int c)
@ -629,6 +679,9 @@ _find_string(const u_char *bp, int *tgt, const char * const *n1,
return NULL;
}
char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t l) {
return strptime(buf, fmt, tm);
static int
leaps_thru_end_of(const int y)
{
return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
-(leaps_thru_end_of(-(y + 1)) + 1);
}

View file

@ -0,0 +1,36 @@
/* $OpenBSD: _def_time.c,v 1.6 2016/05/23 00:05:15 guenther Exp $ */
/*
* Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
#include <locale.h>
#include "localedef.h"
const _TimeLocale _DefaultTimeLocale =
{
{
"Sun","Mon","Tue","Wed","Thu","Fri","Sat",
},
{
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"
},
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
},
{
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
},
{
"AM", "PM"
},
"%a %b %e %H:%M:%S %Y",
"%m/%d/%y",
"%H:%M:%S",
"%I:%M:%S %p"
};
const _TimeLocale *_CurrentTimeLocale = &_DefaultTimeLocale;