Import strptime(3) into libc. We've got permission by Kevin Ruddy to
modify the original `no modifications' copyright message, and i've included his mail into the source file. The common localization functions between strptime(3) and strftime(3) have been broken out into timelocal.[ch].
This commit is contained in:
parent
d76419833c
commit
37486f035f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=28021
@ -135,6 +135,7 @@ void tzset __P((void));
|
||||
#endif /* not ANSI */
|
||||
|
||||
#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
|
||||
const char *strptime __P((const char *, const char *, struct tm *));
|
||||
char *timezone __P((int, int));
|
||||
void tzsetwall __P((void));
|
||||
time_t timelocal __P((struct tm * const));
|
||||
|
@ -1,14 +1,15 @@
|
||||
# Makefile.inc,v 1.2 1994/09/13 21:26:01 wollman Exp
|
||||
# $Id$
|
||||
# $Id: Makefile.inc,v 1.4 1997/05/03 03:50:04 jb Exp $
|
||||
|
||||
.PATH: ${.CURDIR}/../libc/stdtime
|
||||
|
||||
SRCS+= asctime.c localtime.c strftime.c difftime.c
|
||||
SRCS+= asctime.c localtime.c strftime.c difftime.c timelocal.c strptime.c
|
||||
|
||||
# Only build man pages with libc.
|
||||
.if ${LIB} == "c"
|
||||
MAN5+= stdtime/tzfile.5
|
||||
MAN3+= stdtime/ctime.3 stdtime/strftime.3 stdtime/time2posix.3
|
||||
MAN3+= stdtime/strptime.3
|
||||
|
||||
MLINKS+=ctime.3 asctime.3 ctime.3 difftime.3 ctime.3 gmtime.3 \
|
||||
ctime.3 localtime.3 ctime.3 mktime.3
|
||||
|
@ -198,7 +198,8 @@ is replaced by
|
||||
.Xr date 1 ,
|
||||
.Xr printf 1 ,
|
||||
.Xr ctime 3 ,
|
||||
.Xr printf 3
|
||||
.Xr printf 3 ,
|
||||
.Xr strptime 3
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Fn strftime
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#ifdef LIBC_RCS
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: strftime.c,v 1.17 1997/02/22 15:03:19 peter Exp $";
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
@ -40,72 +40,8 @@ static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
|
||||
|
||||
#include "tzfile.h"
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <sys/stat.h>
|
||||
#include "setlocale.h"
|
||||
|
||||
struct lc_time_T {
|
||||
const char * mon[12];
|
||||
const char * month[12];
|
||||
const char * wday[7];
|
||||
const char * weekday[7];
|
||||
const char * X_fmt;
|
||||
const char * x_fmt;
|
||||
const char * c_fmt;
|
||||
const char * am;
|
||||
const char * pm;
|
||||
const char * date_fmt;
|
||||
};
|
||||
|
||||
static struct lc_time_T localebuf;
|
||||
static int using_locale;
|
||||
|
||||
#define Locale (using_locale ? &localebuf : &C_time_locale)
|
||||
|
||||
static const struct lc_time_T C_time_locale = {
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
}, {
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
}, {
|
||||
"Sun", "Mon", "Tue", "Wed",
|
||||
"Thu", "Fri", "Sat"
|
||||
}, {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday"
|
||||
},
|
||||
|
||||
/* X_fmt */
|
||||
"%H:%M:%S",
|
||||
|
||||
/*
|
||||
** x_fmt
|
||||
** Since the C language standard calls for
|
||||
** "date, using locale's date format," anything goes.
|
||||
** Using just numbers (as here) makes Quakers happier;
|
||||
** it's also compatible with SVR4.
|
||||
*/
|
||||
"%m/%d/%y",
|
||||
|
||||
/*
|
||||
** c_fmt (ctime-compatible)
|
||||
** Note that
|
||||
** "%a %b %d %H:%M:%S %Y"
|
||||
** is used by Solaris 2.3.
|
||||
*/
|
||||
"%a %b %e %X %Y",
|
||||
|
||||
/* am */
|
||||
"AM",
|
||||
|
||||
/* pm */
|
||||
"PM",
|
||||
|
||||
/* date_fmt */
|
||||
"%a %b %e %X %Z %Y"
|
||||
};
|
||||
#include "timelocal.h"
|
||||
|
||||
static char * _add P((const char *, char *, const char *));
|
||||
static char * _conv P((int, const char *, char *, const char *));
|
||||
@ -461,114 +397,3 @@ _add(str, pt, ptlim)
|
||||
++pt;
|
||||
return pt;
|
||||
}
|
||||
|
||||
int
|
||||
__time_load_locale(const char *name)
|
||||
{
|
||||
static char * locale_buf;
|
||||
static char locale_buf_C[] = "C";
|
||||
|
||||
int fd;
|
||||
char * lbuf;
|
||||
char * p;
|
||||
const char ** ap;
|
||||
const char * plim;
|
||||
char filename[PATH_MAX];
|
||||
struct stat st;
|
||||
size_t namesize;
|
||||
size_t bufsize;
|
||||
int save_using_locale;
|
||||
|
||||
save_using_locale = using_locale;
|
||||
using_locale = 0;
|
||||
|
||||
if (name == NULL)
|
||||
goto no_locale;
|
||||
|
||||
if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
** If the locale name is the same as our cache, use the cache.
|
||||
*/
|
||||
lbuf = locale_buf;
|
||||
if (lbuf != NULL && strcmp(name, lbuf) == 0) {
|
||||
p = lbuf;
|
||||
for (ap = (const char **) &localebuf;
|
||||
ap < (const char **) (&localebuf + 1);
|
||||
++ap)
|
||||
*ap = p += strlen(p) + 1;
|
||||
using_locale = 1;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
** Slurp the locale file into the cache.
|
||||
*/
|
||||
namesize = strlen(name) + 1;
|
||||
|
||||
if (!_PathLocale)
|
||||
goto no_locale;
|
||||
/* Range checking not needed, 'name' size is limited */
|
||||
strcpy(filename, _PathLocale);
|
||||
strcat(filename, "/");
|
||||
strcat(filename, name);
|
||||
strcat(filename, "/LC_TIME");
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
goto no_locale;
|
||||
if (fstat(fd, &st) != 0)
|
||||
goto bad_locale;
|
||||
if (st.st_size <= 0)
|
||||
goto bad_locale;
|
||||
bufsize = namesize + st.st_size;
|
||||
locale_buf = NULL;
|
||||
lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
|
||||
malloc(bufsize) : realloc(lbuf, bufsize);
|
||||
if (lbuf == NULL)
|
||||
goto bad_locale;
|
||||
(void) strcpy(lbuf, name);
|
||||
p = lbuf + namesize;
|
||||
plim = p + st.st_size;
|
||||
if (read(fd, p, (size_t) st.st_size) != st.st_size)
|
||||
goto bad_lbuf;
|
||||
if (close(fd) != 0)
|
||||
goto bad_lbuf;
|
||||
/*
|
||||
** Parse the locale file into localebuf.
|
||||
*/
|
||||
if (plim[-1] != '\n')
|
||||
goto bad_lbuf;
|
||||
for (ap = (const char **) &localebuf;
|
||||
ap < (const char **) (&localebuf + 1);
|
||||
++ap) {
|
||||
if (p == plim)
|
||||
goto reset_locale;
|
||||
*ap = p;
|
||||
while (*p != '\n')
|
||||
++p;
|
||||
*p++ = '\0';
|
||||
}
|
||||
/*
|
||||
** Record the successful parse in the cache.
|
||||
*/
|
||||
locale_buf = lbuf;
|
||||
|
||||
using_locale = 1;
|
||||
return 0;
|
||||
|
||||
reset_locale:
|
||||
/*
|
||||
* XXX - This may not be the correct thing to do in this case.
|
||||
* setlocale() assumes that we left the old locale alone.
|
||||
*/
|
||||
locale_buf = locale_buf_C;
|
||||
localebuf = C_time_locale;
|
||||
save_using_locale = 0;
|
||||
bad_lbuf:
|
||||
free(lbuf);
|
||||
bad_locale:
|
||||
(void) close(fd);
|
||||
no_locale:
|
||||
using_locale = save_using_locale;
|
||||
return -1;
|
||||
}
|
||||
|
85
lib/libc/stdtime/strptime.3
Normal file
85
lib/libc/stdtime/strptime.3
Normal file
@ -0,0 +1,85 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1997 Joerg Wunsch
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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.
|
||||
.\"
|
||||
.\" $Id$
|
||||
.\" "
|
||||
.Dd May 8, 1997
|
||||
.Dt STRPTIME 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm strptime
|
||||
.Nd parse date and time string
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <time.h>
|
||||
.Ft const char *
|
||||
.Fn strptime "const char *buf" "const char *format" "struct tm *timeptr"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn strptime
|
||||
function parses the string in the buffer
|
||||
.Fa buf
|
||||
according to the string pointed to by
|
||||
.Fa format ,
|
||||
and fills in the elements of the structure pointed to by
|
||||
.Fa timeptr .
|
||||
Thus, it can be considered the reverse operation of
|
||||
.Xr strftime 3 .
|
||||
.Pp
|
||||
The
|
||||
.Fa format
|
||||
string consists of zero or more conversion specifications and
|
||||
ordinary characters.
|
||||
All ordinary characters are matched exactly with the buffer, where
|
||||
white space in the format string will match any amount of white space
|
||||
in the buffer.
|
||||
All conversion specifications are identical to those described in
|
||||
.Xr strftime 3 .
|
||||
.Sh RETURN VALUES
|
||||
Upon successful completion,
|
||||
.Fn strptime
|
||||
returns the pointer to the first character in
|
||||
.Fa buf
|
||||
that has not been required to satisfy the specified conversions in
|
||||
.Fa format .
|
||||
It returns
|
||||
.Dv NULL
|
||||
if one of the conversions failed.
|
||||
.Sh SEE ALSO
|
||||
.Xr date 1 ,
|
||||
.Xr scanf 3 ,
|
||||
.Xr strftime 3
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Fn strptime
|
||||
function has been contributed by Powerdog Industries.
|
||||
.Pp
|
||||
This man page was written by
|
||||
.ie t J\(:org Wunsch.
|
||||
.el Joerg Wunsch.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn strptime
|
||||
function appeared in
|
||||
.Fx 3.0 .
|
@ -1,7 +1,28 @@
|
||||
/*
|
||||
* Powerdog Industries kindly requests feedback from anyone modifying
|
||||
* this function:
|
||||
*
|
||||
* Date: Thu, 05 Jun 1997 23:17:17 -0400
|
||||
* From: Kevin Ruddy <kevin.ruddy@powerdog.com>
|
||||
* To: James FitzGibbon <james@nexis.net>
|
||||
* Subject: Re: Use of your strptime(3) code (fwd)
|
||||
*
|
||||
* The reason for the "no mod" clause was so that modifications would
|
||||
* come back and we could integrate them and reissue so that a wider
|
||||
* audience could use it (thereby spreading the wealth). This has
|
||||
* made it possible to get strptime to work on many operating systems.
|
||||
* I'm not sure why that's "plain unacceptable" to the FreeBSD team.
|
||||
*
|
||||
* Anyway, you can change it to "with or without modification" as
|
||||
* you see fit. Enjoy.
|
||||
*
|
||||
* Kevin Ruddy
|
||||
* Powerdog Industries, Inc.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994 Powerdog Industries. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without
|
||||
* 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
|
||||
@ -30,329 +51,299 @@
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef LIBC_RCS
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved.";
|
||||
static char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
|
||||
static char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* not lint */
|
||||
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
#include "timelocal.h"
|
||||
|
||||
#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
|
||||
/* #ifndef sun */
|
||||
struct dtconv {
|
||||
char *abbrev_month_names[12];
|
||||
char *month_names[12];
|
||||
char *abbrev_weekday_names[7];
|
||||
char *weekday_names[7];
|
||||
char *time_format;
|
||||
char *sdate_format;
|
||||
char *dtime_format;
|
||||
char *am_string;
|
||||
char *pm_string;
|
||||
char *ldate_format;
|
||||
};
|
||||
/* #endif */
|
||||
|
||||
static struct dtconv En_US = {
|
||||
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
|
||||
{ "January", "February", "March", "April",
|
||||
"May", "June", "July", "August",
|
||||
"September", "October", "November", "December" },
|
||||
{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
|
||||
{ "Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday" },
|
||||
"%H:%M:%S",
|
||||
"%m/%d/%y",
|
||||
"%a %b %e %T %Z %Y",
|
||||
"AM",
|
||||
"PM",
|
||||
"%A, %B, %e, %Y"
|
||||
};
|
||||
|
||||
#ifdef SUNOS4
|
||||
extern int strncasecmp();
|
||||
#endif
|
||||
|
||||
char *
|
||||
strptime(char *buf, char *fmt, struct tm *tm)
|
||||
const char *
|
||||
strptime(const char *buf, const char *fmt, struct tm *tm)
|
||||
{
|
||||
char c,
|
||||
*ptr;
|
||||
int i,
|
||||
len;
|
||||
char c;
|
||||
const char *ptr;
|
||||
int i,
|
||||
len;
|
||||
|
||||
ptr = fmt;
|
||||
while (*ptr != 0) {
|
||||
if (*buf == 0)
|
||||
break;
|
||||
ptr = fmt;
|
||||
while (*ptr != 0) {
|
||||
if (*buf == 0)
|
||||
break;
|
||||
|
||||
c = *ptr++;
|
||||
c = *ptr++;
|
||||
|
||||
if (c != '%') {
|
||||
if (isspace(c))
|
||||
while (*buf != 0 && isspace(*buf))
|
||||
buf++;
|
||||
else if (c != *buf++)
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
if (c != '%') {
|
||||
if (isspace(c))
|
||||
while (*buf != 0 && isspace(*buf))
|
||||
buf++;
|
||||
else if (c != *buf++)
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *ptr++;
|
||||
switch (c) {
|
||||
case 0:
|
||||
case '%':
|
||||
if (*buf++ != '%')
|
||||
return 0;
|
||||
break;
|
||||
c = *ptr++;
|
||||
switch (c) {
|
||||
case 0:
|
||||
case '%':
|
||||
if (*buf++ != '%')
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
buf = strptime(buf, En_US.ldate_format, tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
case 'C':
|
||||
buf = strptime(buf, Locale->date_fmt, tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
buf = strptime(buf, "%x %X", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
case 'c':
|
||||
buf = strptime(buf, "%x %X", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
buf = strptime(buf, "%m/%d/%y", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
case 'D':
|
||||
buf = strptime(buf, "%m/%d/%y", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
buf = strptime(buf, "%H:%M", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
case 'R':
|
||||
buf = strptime(buf, "%H:%M", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
buf = strptime(buf, "%I:%M:%S %p", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
case 'r':
|
||||
buf = strptime(buf, "%I:%M:%S %p", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
buf = strptime(buf, "%H:%M:%S", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
case 'T':
|
||||
buf = strptime(buf, "%H:%M:%S", tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
buf = strptime(buf, En_US.time_format, tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
case 'X':
|
||||
buf = strptime(buf, Locale->X_fmt, tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
buf = strptime(buf, En_US.sdate_format, tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
case 'x':
|
||||
buf = strptime(buf, Locale->x_fmt, tm);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
case 'j':
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (i > 365)
|
||||
return 0;
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (i > 365)
|
||||
return 0;
|
||||
|
||||
tm->tm_yday = i;
|
||||
break;
|
||||
tm->tm_yday = i;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
case 'S':
|
||||
if (*buf == 0 || isspace(*buf))
|
||||
break;
|
||||
case 'M':
|
||||
case 'S':
|
||||
if (*buf == 0 || isspace(*buf))
|
||||
break;
|
||||
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (i > 59)
|
||||
return 0;
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (i > 59)
|
||||
return 0;
|
||||
|
||||
if (c == 'M')
|
||||
tm->tm_min = i;
|
||||
else
|
||||
tm->tm_sec = i;
|
||||
if (c == 'M')
|
||||
tm->tm_min = i;
|
||||
else
|
||||
tm->tm_sec = i;
|
||||
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'k':
|
||||
case 'l':
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'k':
|
||||
case 'l':
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (c == 'H' || c == 'k') {
|
||||
if (i > 23)
|
||||
return 0;
|
||||
} else if (i > 11)
|
||||
return 0;
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (c == 'H' || c == 'k') {
|
||||
if (i > 23)
|
||||
return 0;
|
||||
} else if (i > 11)
|
||||
return 0;
|
||||
|
||||
tm->tm_hour = i;
|
||||
tm->tm_hour = i;
|
||||
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
len = strlen(En_US.am_string);
|
||||
if (strncasecmp(buf, En_US.am_string, len) == 0) {
|
||||
if (tm->tm_hour > 12)
|
||||
return 0;
|
||||
if (tm->tm_hour == 12)
|
||||
tm->tm_hour = 0;
|
||||
buf += len;
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
len = strlen(Locale->am);
|
||||
if (strncasecmp(buf, Locale->am, len) == 0) {
|
||||
if (tm->tm_hour > 12)
|
||||
return 0;
|
||||
if (tm->tm_hour == 12)
|
||||
tm->tm_hour = 0;
|
||||
buf += len;
|
||||
break;
|
||||
}
|
||||
|
||||
len = strlen(En_US.pm_string);
|
||||
if (strncasecmp(buf, En_US.pm_string, len) == 0) {
|
||||
if (tm->tm_hour > 12)
|
||||
return 0;
|
||||
if (tm->tm_hour != 12)
|
||||
tm->tm_hour += 12;
|
||||
buf += len;
|
||||
break;
|
||||
}
|
||||
len = strlen(Locale->pm);
|
||||
if (strncasecmp(buf, Locale->pm, len) == 0) {
|
||||
if (tm->tm_hour > 12)
|
||||
return 0;
|
||||
if (tm->tm_hour != 12)
|
||||
tm->tm_hour += 12;
|
||||
buf += len;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case 'A':
|
||||
case 'a':
|
||||
for (i = 0; i < asizeof(En_US.weekday_names); i++) {
|
||||
len = strlen(En_US.weekday_names[i]);
|
||||
if (strncasecmp(buf,
|
||||
En_US.weekday_names[i],
|
||||
len) == 0)
|
||||
break;
|
||||
case 'A':
|
||||
case 'a':
|
||||
for (i = 0; i < asizeof(Locale->weekday); i++) {
|
||||
len = strlen(Locale->weekday[i]);
|
||||
if (strncasecmp(buf,
|
||||
Locale->weekday[i],
|
||||
len) == 0)
|
||||
break;
|
||||
|
||||
len = strlen(En_US.abbrev_weekday_names[i]);
|
||||
if (strncasecmp(buf,
|
||||
En_US.abbrev_weekday_names[i],
|
||||
len) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == asizeof(En_US.weekday_names))
|
||||
return 0;
|
||||
len = strlen(Locale->wday[i]);
|
||||
if (strncasecmp(buf,
|
||||
Locale->wday[i],
|
||||
len) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == asizeof(Locale->weekday))
|
||||
return 0;
|
||||
|
||||
tm->tm_wday = i;
|
||||
buf += len;
|
||||
break;
|
||||
tm->tm_wday = i;
|
||||
buf += len;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'e':
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
case 'd':
|
||||
case 'e':
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (i > 31)
|
||||
return 0;
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (i > 31)
|
||||
return 0;
|
||||
|
||||
tm->tm_mday = i;
|
||||
tm->tm_mday = i;
|
||||
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
case 'b':
|
||||
case 'h':
|
||||
for (i = 0; i < asizeof(En_US.month_names); i++) {
|
||||
len = strlen(En_US.month_names[i]);
|
||||
if (strncasecmp(buf,
|
||||
En_US.month_names[i],
|
||||
len) == 0)
|
||||
break;
|
||||
case 'B':
|
||||
case 'b':
|
||||
case 'h':
|
||||
for (i = 0; i < asizeof(Locale->month); i++) {
|
||||
len = strlen(Locale->month[i]);
|
||||
if (strncasecmp(buf,
|
||||
Locale->month[i],
|
||||
len) == 0)
|
||||
break;
|
||||
|
||||
len = strlen(En_US.abbrev_month_names[i]);
|
||||
if (strncasecmp(buf,
|
||||
En_US.abbrev_month_names[i],
|
||||
len) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == asizeof(En_US.month_names))
|
||||
return 0;
|
||||
len = strlen(Locale->mon[i]);
|
||||
if (strncasecmp(buf,
|
||||
Locale->mon[i],
|
||||
len) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == asizeof(Locale->month))
|
||||
return 0;
|
||||
|
||||
tm->tm_mon = i;
|
||||
buf += len;
|
||||
break;
|
||||
tm->tm_mon = i;
|
||||
buf += len;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
case 'm':
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (i < 1 || i > 12)
|
||||
return 0;
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (i < 1 || i > 12)
|
||||
return 0;
|
||||
|
||||
tm->tm_mon = i - 1;
|
||||
tm->tm_mon = i - 1;
|
||||
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
case 'y':
|
||||
if (*buf == 0 || isspace(*buf))
|
||||
break;
|
||||
case 'Y':
|
||||
case 'y':
|
||||
if (*buf == 0 || isspace(*buf))
|
||||
break;
|
||||
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
if (!isdigit(*buf))
|
||||
return 0;
|
||||
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (c == 'Y')
|
||||
i -= 1900;
|
||||
if (i < 0)
|
||||
return 0;
|
||||
for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
|
||||
i *= 10;
|
||||
i += *buf - '0';
|
||||
}
|
||||
if (c == 'Y')
|
||||
i -= 1900;
|
||||
if (i < 0)
|
||||
return 0;
|
||||
|
||||
tm->tm_year = i;
|
||||
tm->tm_year = i;
|
||||
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*buf != 0 && isspace(*buf))
|
||||
while (*ptr != 0 && !isspace(*ptr))
|
||||
ptr++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
197
lib/libc/stdtime/timelocal.c
Normal file
197
lib/libc/stdtime/timelocal.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*-
|
||||
* Copyright (c) 1997 FreeBSD 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syslimits.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "setlocale.h"
|
||||
#include "timelocal.h"
|
||||
|
||||
struct lc_time_T _time_localebuf;
|
||||
int _time_using_locale;
|
||||
|
||||
const struct lc_time_T _C_time_locale = {
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
}, {
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
}, {
|
||||
"Sun", "Mon", "Tue", "Wed",
|
||||
"Thu", "Fri", "Sat"
|
||||
}, {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday"
|
||||
},
|
||||
|
||||
/* X_fmt */
|
||||
"%H:%M:%S",
|
||||
|
||||
/*
|
||||
** x_fmt
|
||||
** Since the C language standard calls for
|
||||
** "date, using locale's date format," anything goes.
|
||||
** Using just numbers (as here) makes Quakers happier;
|
||||
** it's also compatible with SVR4.
|
||||
*/
|
||||
"%m/%d/%y",
|
||||
|
||||
/*
|
||||
** c_fmt (ctime-compatible)
|
||||
** Note that
|
||||
** "%a %b %d %H:%M:%S %Y"
|
||||
** is used by Solaris 2.3.
|
||||
*/
|
||||
"%a %b %e %X %Y",
|
||||
|
||||
/* am */
|
||||
"AM",
|
||||
|
||||
/* pm */
|
||||
"PM",
|
||||
|
||||
/* date_fmt */
|
||||
"%a %b %e %X %Z %Y"
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
__time_load_locale(const char *name)
|
||||
{
|
||||
static char * locale_buf;
|
||||
static char locale_buf_C[] = "C";
|
||||
|
||||
int fd;
|
||||
char * lbuf;
|
||||
char * p;
|
||||
const char ** ap;
|
||||
const char * plim;
|
||||
char filename[PATH_MAX];
|
||||
struct stat st;
|
||||
size_t namesize;
|
||||
size_t bufsize;
|
||||
int save_using_locale;
|
||||
|
||||
save_using_locale = _time_using_locale;
|
||||
_time_using_locale = 0;
|
||||
|
||||
if (name == NULL)
|
||||
goto no_locale;
|
||||
|
||||
if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
** If the locale name is the same as our cache, use the cache.
|
||||
*/
|
||||
lbuf = locale_buf;
|
||||
if (lbuf != NULL && strcmp(name, lbuf) == 0) {
|
||||
p = lbuf;
|
||||
for (ap = (const char **) &_time_localebuf;
|
||||
ap < (const char **) (&_time_localebuf + 1);
|
||||
++ap)
|
||||
*ap = p += strlen(p) + 1;
|
||||
_time_using_locale = 1;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
** Slurp the locale file into the cache.
|
||||
*/
|
||||
namesize = strlen(name) + 1;
|
||||
|
||||
if (!_PathLocale)
|
||||
goto no_locale;
|
||||
/* Range checking not needed, 'name' size is limited */
|
||||
strcpy(filename, _PathLocale);
|
||||
strcat(filename, "/");
|
||||
strcat(filename, name);
|
||||
strcat(filename, "/LC_TIME");
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
goto no_locale;
|
||||
if (fstat(fd, &st) != 0)
|
||||
goto bad_locale;
|
||||
if (st.st_size <= 0)
|
||||
goto bad_locale;
|
||||
bufsize = namesize + st.st_size;
|
||||
locale_buf = NULL;
|
||||
lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
|
||||
malloc(bufsize) : realloc(lbuf, bufsize);
|
||||
if (lbuf == NULL)
|
||||
goto bad_locale;
|
||||
(void) strcpy(lbuf, name);
|
||||
p = lbuf + namesize;
|
||||
plim = p + st.st_size;
|
||||
if (read(fd, p, (size_t) st.st_size) != st.st_size)
|
||||
goto bad_lbuf;
|
||||
if (close(fd) != 0)
|
||||
goto bad_lbuf;
|
||||
/*
|
||||
** Parse the locale file into localebuf.
|
||||
*/
|
||||
if (plim[-1] != '\n')
|
||||
goto bad_lbuf;
|
||||
for (ap = (const char **) &_time_localebuf;
|
||||
ap < (const char **) (&_time_localebuf + 1);
|
||||
++ap) {
|
||||
if (p == plim)
|
||||
goto reset_locale;
|
||||
*ap = p;
|
||||
while (*p != '\n')
|
||||
++p;
|
||||
*p++ = '\0';
|
||||
}
|
||||
/*
|
||||
** Record the successful parse in the cache.
|
||||
*/
|
||||
locale_buf = lbuf;
|
||||
|
||||
_time_using_locale = 1;
|
||||
return 0;
|
||||
|
||||
reset_locale:
|
||||
/*
|
||||
* XXX - This may not be the correct thing to do in this case.
|
||||
* setlocale() assumes that we left the old locale alone.
|
||||
*/
|
||||
locale_buf = locale_buf_C;
|
||||
_time_localebuf = _C_time_locale;
|
||||
save_using_locale = 0;
|
||||
bad_lbuf:
|
||||
free(lbuf);
|
||||
bad_locale:
|
||||
(void) close(fd);
|
||||
no_locale:
|
||||
_time_using_locale = save_using_locale;
|
||||
return -1;
|
||||
}
|
51
lib/libc/stdtime/timelocal.h
Normal file
51
lib/libc/stdtime/timelocal.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*-
|
||||
* Copyright (c) 1997 FreeBSD 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Private header file for the strftime and strptime localization
|
||||
* stuff.
|
||||
*/
|
||||
struct lc_time_T {
|
||||
const char * mon[12];
|
||||
const char * month[12];
|
||||
const char * wday[7];
|
||||
const char * weekday[7];
|
||||
const char * X_fmt;
|
||||
const char * x_fmt;
|
||||
const char * c_fmt;
|
||||
const char * am;
|
||||
const char * pm;
|
||||
const char * date_fmt;
|
||||
};
|
||||
|
||||
extern struct lc_time_T _time_localebuf;
|
||||
extern int _time_using_locale;
|
||||
extern const struct lc_time_T _C_time_locale;
|
||||
|
||||
#define Locale (_time_using_locale ? &_time_localebuf : &_C_time_locale)
|
||||
|
Loading…
Reference in New Issue
Block a user