diff options
Diffstat (limited to 'lib/libc/stdtime/strptime.c')
-rw-r--r-- | lib/libc/stdtime/strptime.c | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c new file mode 100644 index 0000000..4c71eaa --- /dev/null +++ b/lib/libc/stdtime/strptime.c @@ -0,0 +1,349 @@ +/* + * 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, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgement: + * This product includes software developed by Powerdog Industries. + * 4. The name of Powerdog Industries may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``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 POWERDOG INDUSTRIES 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. + */ + +#ifdef LIBC_RCS +static const char rcsid[] = + "$Id: strptime.c,v 1.3 1997/08/13 13:11:53 ache Exp $"; +#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"; +#endif /* !defined NOID */ +#endif /* not lint */ + +#include <time.h> +#include <ctype.h> +#include <string.h> +#include "timelocal.h" + +#define asizeof(a) (sizeof (a) / sizeof ((a)[0])) + +char * +strptime(const char *buf, const char *fmt, struct tm *tm) +{ + char c; + const char *ptr; + int i, + len; + + ptr = fmt; + while (*ptr != 0) { + if (*buf == 0) + break; + + c = *ptr++; + + if (c != '%') { + if (isspace((unsigned char)c)) + while (*buf != 0 && isspace((unsigned char)*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((unsigned char)*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit((unsigned char)*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((unsigned char)*buf)) + break; + + if (!isdigit((unsigned char)*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit((unsigned char)*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((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + + case 'H': + case 'I': + case 'k': + case 'l': + if (!isdigit((unsigned char)*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit((unsigned char)*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((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*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((unsigned char)*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i > 31) + return 0; + + tm->tm_mday = i; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*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((unsigned char)*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i < 1 || i > 12) + return 0; + + tm->tm_mon = i - 1; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + + case 'Y': + case 'y': + if (*buf == 0 || isspace((unsigned char)*buf)) + break; + + if (!isdigit((unsigned char)*buf)) + return 0; + + for (i = 0; *buf != 0 && isdigit((unsigned char)*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((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ptr++; + break; + } + } + + return (char *)buf; +} |