This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
LIBC - add strptime()
- From: Gary Thomas <gary at mlbassoc dot com>
- To: eCos patches <ecos-patches at sources dot redhat dot com>
- Date: 27 Jan 2003 15:10:43 -0700
- Subject: LIBC - add strptime()
Index: language/c/libc/time/current/ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/language/c/libc/time/current/ChangeLog,v
retrieving revision 1.10
diff -u -5 -p -r1.10 ChangeLog
--- language/c/libc/time/current/ChangeLog 23 May 2002 23:07:31 -0000 1.10
+++ language/c/libc/time/current/ChangeLog 27 Jan 2003 20:24:43 -0000
@@ -1,5 +1,12 @@
+2003-01-27 Gary Thomas <gary@mlbassoc.com>
+
+ * tests/strptime.c:
+ * src/strptime.cxx:
+ * include/time.h:
+ * cdl/time.cdl: Add support for strptime().
+
2002-05-14 Jesper Skov <jskov@redhat.com>
* cdl/time.cdl: Added -Wno-format to the compiler flags. This is
to avoid warnings about Y2K problems with the format specifiers
used in the strftime test.
Index: language/c/libc/time/current/cdl/time.cdl
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/language/c/libc/time/current/cdl/time.cdl,v
retrieving revision 1.5
diff -u -5 -p -r1.5 time.cdl
--- language/c/libc/time/current/cdl/time.cdl 23 May 2002 23:07:31 -0000 1.5
+++ language/c/libc/time/current/cdl/time.cdl 27 Jan 2003 20:54:42 -0000
@@ -63,15 +63,16 @@ cdl_package CYGPKG_LIBC_TIME {
"<cyg/libc/time/time.h>" }
requires CYGPKG_ISOINFRA
requires CYGINT_ISO_DIV
requires CYGINT_ISO_ABS
- compile asctime.cxx asctime_r.cxx clock.cxx \
- ctime.cxx ctime_r.cxx difftime.cxx \
- gmtime.cxx gmtime_r.cxx localtime.cxx \
- localtime_r.cxx mktime.cxx settime.cxx \
- strftime.cxx time.cxx timeutil.cxx
+ compile asctime.cxx clock.cxx \
+ ctime.cxx difftime.cxx \
+ gmtime.cxx localtime.cxx \
+ mktime.cxx settime.cxx \
+ strftime.cxx time.cxx \
+ timeutil.cxx
# ====================================================================
cdl_option CYGSEM_LIBC_TIME_CLOCK_WORKING {
@@ -112,14 +113,17 @@ cdl_package CYGPKG_LIBC_TIME {
}
cdl_option CYGFUN_LIBC_TIME_POSIX {
display "POSIX time functions"
default_value 1
+ requires CYGFUN_LIBC_STRING_BSD_FUNCS
+ compile asctime_r.cxx ctime_r.cxx gmtime_r.cxx \
+ localtime_r.cxx strptime.cxx
description "
Enabling this option allows the use of the
following functions defined in POSIX 1003.1:
- asctime_r(), ctime_r(), gmtime_r(), and
+ asctime_r(), ctime_r(), gmtime_r(), strptime(), and
localtime_r()."
}
cdl_option CYGFUN_LIBC_TIME_SUS_EXTNS {
display "Single UNIX extensions"
@@ -314,11 +318,14 @@ cdl_package CYGPKG_LIBC_TIME {
cdl_option CYGPKG_LIBC_TIME_TESTS {
display "C library time and date function tests"
flavor data
no_define
- calculated { "tests/asctime tests/clock tests/ctime tests/gmtime tests/localtime tests/mktime tests/strftime tests/time" }
+ calculated {
+ "tests/asctime tests/clock tests/ctime tests/gmtime tests/localtime tests/mktime tests/strftime tests/time "
+ . (CYGSEM_LIBC_TIME_POSIX_TIME_ROUTINES ? "tests/strptime" : "")
+ }
description "
This option specifies the set of tests for the C library
time and date functions."
}
}
Index: language/c/libc/time/current/include/time.h
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/language/c/libc/time/current/include/time.h,v
retrieving revision 1.3
diff -u -5 -p -r1.3 time.h
--- language/c/libc/time/current/include/time.h 23 May 2002 23:07:32 -0000 1.3
+++ language/c/libc/time/current/include/time.h 27 Jan 2003 20:57:08 -0000
@@ -9,10 +9,11 @@
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
@@ -141,10 +142,21 @@ gmtime_r( const time_t *__timer, struct
// stores the result in the space occupied by __result
//
extern struct tm *
localtime_r( const time_t *__timer, struct tm *__result );
+
+/////////////////////////////////////////////////////////
+// strptime() -
+/////////////////////////////////////////////////////////
+//
+// Parse a time string into a struct tm
+//
+
+extern char *
+strptime( const char *__s, const char *__format,
+ struct tm *__timeptr); //__attribute__ ((format (strftime, 2)));
#endif // ifdef CYGFUN_LIBC_TIME_POSIX
//===========================================================================
Index: language/c/libc/time/current/src/strptime.cxx
===================================================================
RCS file: language/c/libc/time/current/src/strptime.cxx
diff -N language/c/libc/time/current/src/strptime.cxx
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ language/c/libc/time/current/src/strptime.cxx 27 Jan 2003 20:33:20 -0000
@@ -0,0 +1,427 @@
+//
+// Adapted for use in eCos by Gary Thomas
+// Copyright (C) 2003 Gary Thomas
+//
+
+/*
+ * 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 <stddef.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+
+static const char *weekdays[] = {
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ NULL
+};
+
+static const char *month[] = {
+ "January",
+ "February",
+ "Mars",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December",
+ NULL,
+};
+
+static const char *ampm[] = {
+ "am",
+ "pm",
+ NULL
+};
+
+/*
+ * Try to match `*buf' to one of the strings in `strs'. Return the
+ * index of the matching string (or -1 if none). Also advance buf.
+ */
+
+static int
+match_string (const char **buf, const char **strs, int ablen)
+{
+ int i = 0;
+
+ for (i = 0; strs[i] != NULL; ++i) {
+ int len = ablen > 0 ? ablen : strlen (strs[i]);
+
+ if (strncasecmp (*buf, strs[i], len) == 0) {
+ *buf += len;
+ return i;
+ }
+ }
+ return -1;
+}
+
+/*
+ * tm_year is relative this year
+ */
+
+const int tm_year_base = 1900;
+
+/*
+ * Return TRUE iff `year' was a leap year.
+ */
+
+static int
+is_leap_year (int year)
+{
+ return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
+}
+
+/*
+ * Return the weekday [0,6] (0 = Sunday) of the first day of `year'
+ */
+
+static int
+first_day (int year)
+{
+ int ret = 4; // Jan 1, 1970 was on Thursday
+
+ for (; year > 1970; --year)
+ ret = (ret + 365 + is_leap_year (year) ? 1 : 0) % 7;
+ return ret;
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+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])
+ */
+
+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])
+ */
+
+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;
+ }
+}
+
+/*
+ *
+ */
+
+char *
+strptime (const char *buf, const char *format, struct tm *timeptr)
+{
+ char c;
+
+ timeptr->tm_yday = 1; // So it's always valid
+ timeptr->tm_isdst = 0;
+
+ 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, weekdays, 0);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_wday = ret;
+ break;
+ case 'a' :
+ ret = match_string (&buf, weekdays, 3);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_wday = ret;
+ break;
+ case 'B' :
+ ret = match_string (&buf, month, 0);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_mon = ret;
+ break;
+ case 'b' :
+ case 'h' :
+ ret = match_string (&buf, month, 3);
+ 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' :
+ // Date and Time in the current locale - unsupported
+ return NULL;
+ 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, 0);
+ 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' :
+ // Timezone spec not handled
+ return NULL;
+ 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;
+}
+
+// strptime.cxx
Index: language/c/libc/time/current/tests/strptime.c
===================================================================
RCS file: language/c/libc/time/current/tests/strptime.c
diff -N language/c/libc/time/current/tests/strptime.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ language/c/libc/time/current/tests/strptime.c 27 Jan 2003 20:24:32 -0000
@@ -0,0 +1,118 @@
+//=================================================================
+//
+// strptime.c
+//
+// Testcase for C library strptime() function
+//
+//=================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Gary Thomas
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//=================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): jlarmour
+// Contributors: gthomas
+// Date: 1999-03-05
+// Description: Contains testcode for C library strptime() function
+//
+//
+//####DESCRIPTIONEND####
+
+// CONFIGURATION
+
+#include <pkgconf/libc_time.h> // C library configuration
+
+// INCLUDES
+
+#include <time.h>
+#include <cyg/infra/testcase.h>
+
+// HOW TO START TESTS
+
+# define START_TEST( test ) test(0)
+
+// FUNCTIONS
+
+static int my_strcmp(const char *s1, const char *s2)
+{
+ for ( ; *s1 == *s2 ; s1++,s2++ )
+ {
+ if ( *s1 == '\0' )
+ break;
+ } // for
+
+ return (*s1 - *s2);
+} // my_strcmp()
+
+static void
+test( CYG_ADDRWORD data )
+{
+ struct tm tm1;
+ char s[1000], *sp, *dp, *fp;
+ size_t size;
+
+ dp = "Fri Jan 24 08:33:14 2003";
+ fp = "%a %b %d %H:%M:%S %Y";
+ sp = strptime(dp, fp, &tm1);
+ CYG_TEST_PASS_FAIL(((sp!=NULL) && (*sp=='\0')), "strptime test #1");
+ size = strftime(s, sizeof(s), fp, &tm1);
+ CYG_TEST_PASS_FAIL(((size==strlen(dp)) && (my_strcmp(s, dp) == 0)), "strptime test #2");
+
+ dp = "Friday January 24 08:33:14 2003";
+ fp = "%A %B %d %H:%M:%S %Y";
+ sp = strptime(dp, fp, &tm1);
+ CYG_TEST_PASS_FAIL(((sp!=NULL) && (*sp=='\0')), "strptime test #3");
+ size = strftime(s, sizeof(s), fp, &tm1);
+ CYG_TEST_PASS_FAIL(((size==strlen(dp)) && (my_strcmp(s, dp) == 0)), "strptime test #4");
+
+ CYG_TEST_FINISH("Finished tests from testcase " __FILE__ " for C library "
+ "strptime() function");
+} // test()
+
+
+int
+main(int argc, char *argv[])
+{
+ CYG_TEST_INIT();
+
+ CYG_TEST_INFO("Starting tests from testcase " __FILE__ " for C library "
+ "strptime() function");
+
+ START_TEST( test );
+
+ CYG_TEST_NA("Testing is not applicable to this configuration");
+
+} // main()
+
+// EOF strptime.c
--
------------------------------------------------------------
Gary Thomas |
MLB Associates | Consulting for the
+1 (970) 229-1963 | Embedded world
http://www.mlbassoc.com/ |
email: <gary@mlbassoc.com> |
gpg: http://www.chez-thomas.org/gary/gpg_key.asc
------------------------------------------------------------