summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/lib/roken/strptime.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/lib/roken/strptime.c')
-rw-r--r--crypto/heimdal/lib/roken/strptime.c131
1 files changed, 70 insertions, 61 deletions
diff --git a/crypto/heimdal/lib/roken/strptime.c b/crypto/heimdal/lib/roken/strptime.c
index 36f0822..9cd1333 100644
--- a/crypto/heimdal/lib/roken/strptime.c
+++ b/crypto/heimdal/lib/roken/strptime.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * Copyright (c) 1999, 2003, 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,10 +33,13 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+#ifdef TEST_STRPFTIME
+#include "strpftime-test.h"
+#endif
#include <ctype.h>
#include "roken.h"
-RCSID("$Id: strptime.c,v 1.2 1999/11/12 15:29:55 assar Exp $");
+RCSID("$Id: strptime.c 21895 2007-08-09 08:45:54Z lha $");
static const char *abb_weekdays[] = {
"Sun",
@@ -79,7 +82,7 @@ static const char *abb_month[] = {
static const char *full_month[] = {
"January",
"February",
- "Mars",
+ "March",
"April",
"May",
"June",
@@ -120,7 +123,41 @@ match_string (const char **buf, const char **strs)
}
/*
- * tm_year is relative this year */
+ * Try to match `*buf' to at the most `n' characters and return the
+ * resulting number in `num'. Returns 0 or an error. Also advance
+ * buf.
+ */
+
+static int
+parse_number (const char **buf, int n, int *num)
+{
+ char *s, *str;
+ int i;
+
+ str = malloc(n + 1);
+ if (str == NULL)
+ return -1;
+
+ /* skip whitespace */
+ for (; **buf != '\0' && isspace((unsigned char)(**buf)); (*buf)++)
+ ;
+
+ /* parse at least n characters */
+ for (i = 0; **buf != '\0' && i < n && isdigit((unsigned char)(**buf)); i++, (*buf)++)
+ str[i] = **buf;
+ str[i] = '\0';
+
+ *num = strtol (str, &s, 10);
+ free(str);
+ if (s == str)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * tm_year is relative this year
+ */
const int tm_year_base = 1900;
@@ -204,7 +241,7 @@ set_week_number_mon4 (struct tm *timeptr, int wnum)
*
*/
-char *
+char * ROKEN_LIB_FUNCTION
strptime (const char *buf, const char *format, struct tm *timeptr)
{
char c;
@@ -213,8 +250,8 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
char *s;
int ret;
- if (isspace (c)) {
- while (isspace (*buf))
+ if (isspace ((unsigned char)c)) {
+ while (isspace ((unsigned char)*buf))
++buf;
} else if (c == '%' && format[1] != '\0') {
c = *++format;
@@ -247,11 +284,9 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
timeptr->tm_mon = ret;
break;
case 'C' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
return NULL;
timeptr->tm_year = (ret * 100) - tm_year_base;
- buf = s;
break;
case 'c' :
abort ();
@@ -263,57 +298,47 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
break;
case 'd' :
case 'e' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
return NULL;
timeptr->tm_mday = ret;
- buf = s;
break;
case 'H' :
case 'k' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
return NULL;
timeptr->tm_hour = ret;
- buf = s;
break;
case 'I' :
case 'l' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
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)
+ if (parse_number(&buf, 3, &ret))
+ return NULL;
+ if (ret == 0)
return NULL;
timeptr->tm_yday = ret - 1;
- buf = s;
break;
case 'm' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ if (ret == 0)
return NULL;
timeptr->tm_mon = ret - 1;
- buf = s;
break;
case 'M' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
return NULL;
timeptr->tm_min = ret;
- buf = s;
break;
case 'n' :
- if (*buf == '\n')
- ++buf;
- else
- return NULL;
+ while (isspace ((unsigned char)*buf))
+ buf++;
break;
case 'p' :
ret = match_string (&buf, ampm);
@@ -338,17 +363,13 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
buf = s;
break;
case 'S' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
return NULL;
timeptr->tm_sec = ret;
- buf = s;
break;
case 't' :
- if (*buf == '\t')
- ++buf;
- else
- return NULL;
+ while (isspace ((unsigned char)*buf))
+ buf++;
break;
case 'T' : /* %H:%M:%S */
case 'X' :
@@ -358,39 +379,31 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
buf = s;
break;
case 'u' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 1, &ret))
+ return NULL;
+ if (ret <= 0)
return NULL;
timeptr->tm_wday = ret - 1;
- buf = s;
break;
case 'w' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 1, &ret))
return NULL;
timeptr->tm_wday = ret;
- buf = s;
break;
case 'U' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
return NULL;
set_week_number_sun (timeptr, ret);
- buf = s;
break;
case 'V' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
return NULL;
set_week_number_mon4 (timeptr, ret);
- buf = s;
break;
case 'W' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
return NULL;
set_week_number_mon (timeptr, ret);
- buf = s;
break;
case 'x' :
s = strptime (buf, "%Y:%m:%d", timeptr);
@@ -399,21 +412,17 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
buf = s;
break;
case 'y' :
- ret = strtol (buf, &s, 10);
- if (s == buf)
+ if (parse_number(&buf, 2, &ret))
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)
+ if (parse_number(&buf, 4, &ret))
return NULL;
timeptr->tm_year = ret - tm_year_base;
- buf = s;
break;
case 'Z' :
abort ();
@@ -440,5 +449,5 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
return NULL;
}
}
- return (char *)buf;
+ return rk_UNCONST(buf);
}
OpenPOWER on IntegriCloud