diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libc/stdtime/Makefile.inc | 5 | ||||
| -rw-r--r-- | lib/libc/stdtime/strftime.3 | 3 | ||||
| -rw-r--r-- | lib/libc/stdtime/strftime.c | 179 | ||||
| -rw-r--r-- | lib/libc/stdtime/strptime.3 | 85 | ||||
| -rw-r--r-- | lib/libc/stdtime/strptime.c | 621 | ||||
| -rw-r--r-- | lib/libc/stdtime/timelocal.c | 197 | ||||
| -rw-r--r-- | lib/libc/stdtime/timelocal.h | 51 | 
7 files changed, 646 insertions, 495 deletions
diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc index cdd4b8a3209c..246be284987c 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 27c826a0455e..7ce1b2475295 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 b44ff683dbb2..126da8518167 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 000000000000..bdda0e348cd1 --- /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 ced9e3ab00e5..088084849458 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 000000000000..ef40035c09f4 --- /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 000000000000..8593aee3ec3e --- /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) +  | 
