From dea7e25ca71e6a6c690f09a43b04f2858c1c348d Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Tue, 9 Apr 2002 20:55:55 +0000 Subject: [PATCH] 2002-04-09 Mark Bradshaw * libc/include/time.h: Fix strptime declaration. * libc/time/Makefile.am: Add strptime.c. * libc/time/Makefile.in: Regenerated. * libc/time/strptime.c: New file. --- newlib/ChangeLog | 7 + newlib/libc/include/time.h | 2 +- newlib/libc/time/Makefile.am | 1 + newlib/libc/time/Makefile.in | 7 +- newlib/libc/time/strptime.c | 438 +++++++++++++++++++++++++++++++++++ 5 files changed, 452 insertions(+), 3 deletions(-) create mode 100644 newlib/libc/time/strptime.c diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 69123c84e..838f1b8ff 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,10 @@ +2002-04-09 Mark Bradshaw + + * libc/include/time.h: Fix strptime declaration. + * libc/time/Makefile.am: Add strptime.c. + * libc/time/Makefile.in: Regenerated. + * libc/time/strptime.c: New file. + 2002-04-08 Jeff Johnston * libc/sys/linux/include/setjmp.h: Add sigjmp_buf type, diff --git a/newlib/libc/include/time.h b/newlib/libc/include/time.h index 1398ba4c6..fe43c285e 100644 --- a/newlib/libc/include/time.h +++ b/newlib/libc/include/time.h @@ -55,6 +55,7 @@ struct tm *_EXFUN(gmtime, (const time_t *_timer)); struct tm *_EXFUN(localtime,(const time_t *_timer)); #endif size_t _EXFUN(strftime, (char *_s, size_t _maxsize, const char *_fmt, const struct tm *_t)); +char *_EXFUN(strptime, (const char *, const char *, struct tm *)); char *_EXFUN(asctime_r, (const struct tm *, char *)); char *_EXFUN(ctime_r, (const time_t *, char *)); @@ -62,7 +63,6 @@ struct tm *_EXFUN(gmtime_r, (const time_t *, struct tm *)); struct tm *_EXFUN(localtime_r, (const time_t *, struct tm *)); #ifdef __CYGWIN__ -char *_EXFUN(strptime, (const char *, const char *, struct tm *)); #ifndef __STRICT_ANSI__ extern __IMPORT time_t _timezone; extern __IMPORT int _daylight; diff --git a/newlib/libc/time/Makefile.am b/newlib/libc/time/Makefile.am index 1ad24c0bf..3a7fbdb19 100644 --- a/newlib/libc/time/Makefile.am +++ b/newlib/libc/time/Makefile.am @@ -17,6 +17,7 @@ LIB_SOURCES = \ lcltime_r.c \ mktime.c \ strftime.c \ + strptime.c \ time.c libtime_la_LDFLAGS = -Xcompiler -nostdlib diff --git a/newlib/libc/time/Makefile.in b/newlib/libc/time/Makefile.in index 5dfdccc2b..a6fb0ba8c 100644 --- a/newlib/libc/time/Makefile.in +++ b/newlib/libc/time/Makefile.in @@ -108,6 +108,7 @@ LIB_SOURCES = \ lcltime_r.c \ mktime.c \ strftime.c \ + strptime.c \ time.c @@ -150,13 +151,15 @@ LIBS = @LIBS@ lib_a_LIBADD = @USE_LIBTOOL_FALSE@lib_a_OBJECTS = asctime.o asctime_r.o clock.o \ @USE_LIBTOOL_FALSE@ctime.o ctime_r.o difftime.o gmtime.o gmtime_r.o \ -@USE_LIBTOOL_FALSE@lcltime.o lcltime_r.o mktime.o strftime.o time.o +@USE_LIBTOOL_FALSE@lcltime.o lcltime_r.o mktime.o strftime.o strptime.o \ +@USE_LIBTOOL_FALSE@time.o LTLIBRARIES = $(noinst_LTLIBRARIES) libtime_la_LIBADD = @USE_LIBTOOL_TRUE@libtime_la_OBJECTS = asctime.lo asctime_r.lo clock.lo \ @USE_LIBTOOL_TRUE@ctime.lo ctime_r.lo difftime.lo gmtime.lo gmtime_r.lo \ -@USE_LIBTOOL_TRUE@lcltime.lo lcltime_r.lo mktime.lo strftime.lo time.lo +@USE_LIBTOOL_TRUE@lcltime.lo lcltime_r.lo mktime.lo strftime.lo \ +@USE_LIBTOOL_TRUE@strptime.lo time.lo CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) diff --git a/newlib/libc/time/strptime.c b/newlib/libc/time/strptime.c new file mode 100644 index 000000000..929ad9211 --- /dev/null +++ b/newlib/libc/time/strptime.c @@ -0,0 +1,438 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS 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 KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include +#include +#include + +static const char *abb_weekdays[] = { + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + NULL +}; + +static const char *full_weekdays[] = { + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + NULL +}; + +static const char *abb_month[] = { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + NULL +}; + +static const char *full_month[] = { + "January", + "February", + "Mars", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + NULL, +}; + +static const char *ampm[] = { + "am", + "pm", + NULL +}; + +/* + * tm_year is relative this year + */ +const int tm_year_base = 1900; + +/* + * Return TRUE iff `year' was a leap year. + * Needed for strptime. + */ +static int +is_leap_year (int year) +{ + return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0); +} + +/* Needed for strptime. */ +static int +match_string (const char **buf, const char **strs) +{ + int i = 0; + + for (i = 0; strs[i] != NULL; ++i) { + int len = strlen (strs[i]); + + if (strncasecmp (*buf, strs[i], len) == 0) { + *buf += len; + return i; + } + } + return -1; +} + +/* Needed for strptime. */ +static int +first_day (int year) +{ + int ret = 4; + + for (; year > 1970; --year) + ret = (ret + 365 + is_leap_year (year) ? 1 : 0) % 7; + return ret; +} + +/* + * Set `timeptr' given `wnum' (week number [0, 53]) + * Needed for strptime + */ + +static void +set_week_number_sun (struct tm *timeptr, int wnum) +{ + int fday = first_day (timeptr->tm_year + tm_year_base); + + timeptr->tm_yday = wnum * 7 + timeptr->tm_wday - fday; + if (timeptr->tm_yday < 0) { + timeptr->tm_wday = fday; + timeptr->tm_yday = 0; + } +} + +/* + * Set `timeptr' given `wnum' (week number [0, 53]) + * Needed for strptime + */ + +static void +set_week_number_mon (struct tm *timeptr, int wnum) +{ + int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7; + + timeptr->tm_yday = wnum * 7 + (timeptr->tm_wday + 6) % 7 - fday; + if (timeptr->tm_yday < 0) { + timeptr->tm_wday = (fday + 1) % 7; + timeptr->tm_yday = 0; + } +} + +/* + * Set `timeptr' given `wnum' (week number [0, 53]) + * Needed for strptime + */ +static void +set_week_number_mon4 (struct tm *timeptr, int wnum) +{ + int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7; + int offset = 0; + + if (fday < 4) + offset += 7; + + timeptr->tm_yday = offset + (wnum - 1) * 7 + timeptr->tm_wday - fday; + if (timeptr->tm_yday < 0) { + timeptr->tm_wday = fday; + timeptr->tm_yday = 0; + } +} + +/* strptime: roken */ +//extern "C" +char * +//strptime (const char *buf, const char *format, struct tm *timeptr) +_DEFUN (strptime, (buf, format, timeptr), + _CONST char *buf _AND + _CONST char *format _AND + struct tm *timeptr) +{ + char c; + + for (; (c = *format) != '\0'; ++format) { + char *s; + int ret; + + if (isspace (c)) { + while (isspace (*buf)) + ++buf; + } else if (c == '%' && format[1] != '\0') { + c = *++format; + if (c == 'E' || c == 'O') + c = *++format; + switch (c) { + case 'A' : + ret = match_string (&buf, full_weekdays); + if (ret < 0) + return NULL; + timeptr->tm_wday = ret; + break; + case 'a' : + ret = match_string (&buf, abb_weekdays); + if (ret < 0) + return NULL; + timeptr->tm_wday = ret; + break; + case 'B' : + ret = match_string (&buf, full_month); + if (ret < 0) + return NULL; + timeptr->tm_mon = ret; + break; + case 'b' : + case 'h' : + ret = match_string (&buf, abb_month); + if (ret < 0) + return NULL; + timeptr->tm_mon = ret; + break; + case 'C' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_year = (ret * 100) - tm_year_base; + buf = s; + break; + case 'c' : + abort (); + case 'D' : /* %m/%d/%y */ + s = strptime (buf, "%m/%d/%y", timeptr); + if (s == NULL) + return NULL; + buf = s; + break; + case 'd' : + case 'e' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_mday = ret; + buf = s; + break; + case 'H' : + case 'k' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_hour = ret; + buf = s; + break; + case 'I' : + case 'l' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + if (ret == 12) + timeptr->tm_hour = 0; + else + timeptr->tm_hour = ret; + buf = s; + break; + case 'j' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_yday = ret - 1; + buf = s; + break; + case 'm' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_mon = ret - 1; + buf = s; + break; + case 'M' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_min = ret; + buf = s; + break; + case 'n' : + if (*buf == '\n') + ++buf; + else + return NULL; + break; + case 'p' : + ret = match_string (&buf, ampm); + if (ret < 0) + return NULL; + if (timeptr->tm_hour == 0) { + if (ret == 1) + timeptr->tm_hour = 12; + } else + timeptr->tm_hour += 12; + break; + case 'r' : /* %I:%M:%S %p */ + s = strptime (buf, "%I:%M:%S %p", timeptr); + if (s == NULL) + return NULL; + buf = s; + break; + case 'R' : /* %H:%M */ + s = strptime (buf, "%H:%M", timeptr); + if (s == NULL) + return NULL; + buf = s; + break; + case 'S' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_sec = ret; + buf = s; + break; + case 't' : + if (*buf == '\t') + ++buf; + else + return NULL; + break; + case 'T' : /* %H:%M:%S */ + case 'X' : + s = strptime (buf, "%H:%M:%S", timeptr); + if (s == NULL) + return NULL; + buf = s; + break; + case 'u' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_wday = ret - 1; + buf = s; + break; + case 'w' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_wday = ret; + buf = s; + break; + case 'U' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + set_week_number_sun (timeptr, ret); + buf = s; + break; + case 'V' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + set_week_number_mon4 (timeptr, ret); + buf = s; + break; + case 'W' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + set_week_number_mon (timeptr, ret); + buf = s; + break; + case 'x' : + s = strptime (buf, "%Y:%m:%d", timeptr); + if (s == NULL) + return NULL; + buf = s; + break; + case 'y' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + if (ret < 70) + timeptr->tm_year = 100 + ret; + else + timeptr->tm_year = ret; + buf = s; + break; + case 'Y' : + ret = strtol (buf, &s, 10); + if (s == buf) + return NULL; + timeptr->tm_year = ret - tm_year_base; + buf = s; + break; + case 'Z' : + abort (); + case '\0' : + --format; + /* FALLTHROUGH */ + case '%' : + if (*buf == '%') + ++buf; + else + return NULL; + break; + default : + if (*buf == '%' || *++buf == c) + ++buf; + else + return NULL; + break; + } + } else { + if (*buf == c) + ++buf; + else + return NULL; + } + } + return (char *)buf; +} +