summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>1997-08-09 15:43:59 +0000
committerjoerg <joerg@FreeBSD.org>1997-08-09 15:43:59 +0000
commit7f6efbc9e18cb812351eeec3ea51132b9c0d9c21 (patch)
tree4e54883b33255f63903f8d7d56fc8493c5c13710 /lib
parent60e8157583dfe7c4848cd493225feedbc96f3037 (diff)
downloadFreeBSD-src-7f6efbc9e18cb812351eeec3ea51132b9c0d9c21.zip
FreeBSD-src-7f6efbc9e18cb812351eeec3ea51132b9c0d9c21.tar.gz
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].
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdtime/Makefile.inc5
-rw-r--r--lib/libc/stdtime/strftime.33
-rw-r--r--lib/libc/stdtime/strftime.c179
-rw-r--r--lib/libc/stdtime/strptime.385
-rw-r--r--lib/libc/stdtime/strptime.c621
-rw-r--r--lib/libc/stdtime/timelocal.c197
-rw-r--r--lib/libc/stdtime/timelocal.h51
7 files changed, 646 insertions, 495 deletions
diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc
index cdd4b8a..246be28 100644
--- a/lib/libc/stdtime/Makefile.inc
+++ b/lib/libc/stdtime/Makefile.inc
@@ -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
diff --git a/lib/libc/stdtime/strftime.3 b/lib/libc/stdtime/strftime.3
index 27c826a..7ce1b24 100644
--- a/lib/libc/stdtime/strftime.3
+++ b/lib/libc/stdtime/strftime.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
diff --git a/lib/libc/stdtime/strftime.c b/lib/libc/stdtime/strftime.c
index b44ff68..126da85 100644
--- a/lib/libc/stdtime/strftime.c
+++ b/lib/libc/stdtime/strftime.c
@@ -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;
-}
diff --git a/lib/libc/stdtime/strptime.3 b/lib/libc/stdtime/strptime.3
new file mode 100644
index 0000000..bdda0e3
--- /dev/null
+++ b/lib/libc/stdtime/strptime.3
@@ -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 .
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
index ced9e3a..0880848 100644
--- a/lib/libc/stdtime/strptime.c
+++ b/lib/libc/stdtime/strptime.c
@@ -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]))
-
-/* #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
+#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
-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;
-
- ptr = fmt;
- while (*ptr != 0) {
- if (*buf == 0)
- break;
-
- c = *ptr++;
-
- 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;
-
- case 'C':
- buf = strptime(buf, En_US.ldate_format, 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 '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 '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, En_US.sdate_format, tm);
- if (buf == 0)
- return 0;
- break;
-
- 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;
-
- tm->tm_yday = i;
- break;
-
- case 'M':
- case 'S':
- if (*buf == 0 || isspace(*buf))
- break;
-
- if (!isdigit(*buf))
- 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 (*buf != 0 && isspace(*buf))
- while (*ptr != 0 && !isspace(*ptr))
- ptr++;
- break;
-
- 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;
-
- tm->tm_hour = i;
-
- 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;
- }
-
- 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;
- }
-
- 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;
-
- 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;
-
- tm->tm_wday = i;
- buf += len;
- break;
-
- 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;
-
- tm->tm_mday = i;
-
- 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;
-
- 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;
-
- tm->tm_mon = i;
- buf += len;
- break;
-
- 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;
-
- tm->tm_mon = i - 1;
-
- if (*buf != 0 && isspace(*buf))
- while (*ptr != 0 && !isspace(*ptr))
- ptr++;
- break;
-
- case 'Y':
- case 'y':
- if (*buf == 0 || isspace(*buf))
- break;
-
- 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;
-
- tm->tm_year = i;
-
- if (*buf != 0 && isspace(*buf))
- while (*ptr != 0 && !isspace(*ptr))
- ptr++;
- break;
- }
- }
-
- return buf;
+ char c;
+ const char *ptr;
+ int i,
+ len;
+
+ ptr = fmt;
+ while (*ptr != 0) {
+ if (*buf == 0)
+ break;
+
+ c = *ptr++;
+
+ 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;
+
+ 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 '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, "%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 'X':
+ buf = strptime(buf, Locale->X_fmt, 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;
+
+ for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
+ i *= 10;
+ i += *buf - '0';
+ }
+ if (i > 365)
+ return 0;
+
+ tm->tm_yday = i;
+ break;
+
+ case 'M':
+ case 'S':
+ if (*buf == 0 || isspace(*buf))
+ break;
+
+ if (!isdigit(*buf))
+ 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 (*buf != 0 && isspace(*buf))
+ while (*ptr != 0 && !isspace(*ptr))
+ ptr++;
+ break;
+
+ 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;
+
+ tm->tm_hour = i;
+
+ if (*buf != 0 && isspace(*buf))
+ while (*ptr != 0 && !isspace(*ptr))
+ ptr++;
+ 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(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;
+
+ 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(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;
+
+ 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;
+
+ tm->tm_mday = i;
+
+ if (*buf != 0 && isspace(*buf))
+ while (*ptr != 0 && !isspace(*ptr))
+ ptr++;
+ 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(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;
+
+ 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;
+
+ tm->tm_mon = i - 1;
+
+ if (*buf != 0 && isspace(*buf))
+ while (*ptr != 0 && !isspace(*ptr))
+ ptr++;
+ break;
+
+ case 'Y':
+ case 'y':
+ if (*buf == 0 || isspace(*buf))
+ break;
+
+ 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;
+
+ tm->tm_year = i;
+
+ if (*buf != 0 && isspace(*buf))
+ while (*ptr != 0 && !isspace(*ptr))
+ ptr++;
+ break;
+ }
+ }
+
+ return buf;
}
-
diff --git a/lib/libc/stdtime/timelocal.c b/lib/libc/stdtime/timelocal.c
new file mode 100644
index 0000000..ef40035
--- /dev/null
+++ b/lib/libc/stdtime/timelocal.c
@@ -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;
+}
diff --git a/lib/libc/stdtime/timelocal.h b/lib/libc/stdtime/timelocal.h
new file mode 100644
index 0000000..8593aee
--- /dev/null
+++ b/lib/libc/stdtime/timelocal.h
@@ -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)
+
OpenPOWER on IntegriCloud