summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorSheldon Hearn <sheldonh@FreeBSD.org>1999-12-08 15:49:10 +0000
committerSheldon Hearn <sheldonh@FreeBSD.org>1999-12-08 15:49:10 +0000
commit398592ffe13230e1aa04ded8b6dfb07ee5d1ab94 (patch)
treeba66f106a036d6a92727ce484a73ea0c43936ef5 /lib/libc
parent7313447c12ad468695ceb81d80d58d5e744463be (diff)
Notes
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/stdtime/strptime.339
-rw-r--r--lib/libc/stdtime/strptime.c58
2 files changed, 85 insertions, 12 deletions
diff --git a/lib/libc/stdtime/strptime.3 b/lib/libc/stdtime/strptime.3
index d6aa4a276941..82bc9e476d81 100644
--- a/lib/libc/stdtime/strptime.3
+++ b/lib/libc/stdtime/strptime.3
@@ -95,6 +95,45 @@ function appeared in
.Pp
.Sh BUGS
The
+.Fa %C
+format specifier only accepts centuries within the range 19 to 99.
+.Pp
+Both the
+.Fa %e
+and
+.Fa %l
+format specifiers may incorrectly scan one too many digits
+if the intended values comprise only a single digit
+and that digit is followed immediately by another digit.
+Both specifiers accept zero-padded values,
+even though they are both defined as taking unpadded values.
+.Pp
+The
+.Fa %p
+format specifier has no effect unless it is parsed
+.Em after
+hour-related specifiers.
+Specifying
+.Fa %l
+without
+.Fa %p
+will produce undefined results.
+Note that 12AM
+.Pq ante meridiem
+is taken as midnight
+and 12PM
+.Pq post meridiem
+is taken as noon.
+.Pp
+The
+.Fa %U
+and
+.Fa %W
+format specifiers accept any value within the range 00 to 53
+without validating against other values supplied (like month
+or day of the year, for example).
+.Pp
+The
.Fa %Z
format specifier only accepts time zone abbreviations of the local time zone,
or the value "GMT".
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
index 7570381a4f21..ef1e09d76a9f 100644
--- a/lib/libc/stdtime/strptime.c
+++ b/lib/libc/stdtime/strptime.c
@@ -129,9 +129,12 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
- for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ /* XXX This will break for 3-digit centuries. */
+ len = 2;
+ for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
+ len--;
}
if (i < 19)
return 0;
@@ -206,9 +209,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
- for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ len = 3;
+ for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
+ len--;
}
if (i < 1 || i > 366)
return 0;
@@ -224,9 +229,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
- for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ len = 2;
+ for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
+ len--;
}
if (c == 'M') {
@@ -248,12 +255,22 @@ label:
case 'I':
case 'k':
case 'l':
+ /*
+ * Of these, %l is the only specifier explicitly
+ * documented as not being zero-padded. However,
+ * there is no harm in allowing zero-padding.
+ *
+ * XXX The %l specifier may gobble one too many
+ * digits if used incorrectly.
+ */
if (!isdigit((unsigned char)*buf))
return 0;
- for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ len = 2;
+ for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
+ len--;
}
if (c == 'H' || c == 'k') {
if (i > 23)
@@ -269,6 +286,10 @@ label:
break;
case 'p':
+ /*
+ * XXX This is bogus if parsed before hour-related
+ * specifiers.
+ */
len = strlen(Locale->am);
if (strncasecmp(buf, Locale->am, len) == 0) {
if (tm->tm_hour > 12)
@@ -326,9 +347,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
- for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ len = 2;
+ for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
+ len--;
}
if (i > 53)
return 0;
@@ -342,10 +365,7 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
- for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
- i *= 10;
- i += *buf - '0';
- }
+ i = *buf - '0';
if (i > 6)
return 0;
@@ -358,12 +378,22 @@ label:
case 'd':
case 'e':
+ /*
+ * The %e specifier is explicitly documented as not
+ * being zero-padded but there is no harm in allowing
+ * such padding.
+ *
+ * XXX The %e specifier may gobble one too many
+ * digits if used incorrectly.
+ */
if (!isdigit((unsigned char)*buf))
return 0;
- for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ len = 2;
+ for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
+ len--;
}
if (i > 31)
return 0;
@@ -414,9 +444,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
- for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ len = 2;
+ for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
+ len--;
}
if (i < 1 || i > 12)
return 0;
@@ -436,9 +468,11 @@ label:
if (!isdigit((unsigned char)*buf))
return 0;
- for (i = 0; *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+ len = (c == 'Y') ? 4 : 2;
+ for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
i *= 10;
i += *buf - '0';
+ len--;
}
if (c == 'Y')
i -= 1900;