aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--time/strptime.c119
2 files changed, 77 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index cd51ee9c35..c645f33af3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+1999-07-14 Ulrich Drepper <drepper@cygnus.com>
+
+ * time/strptime.c (get_number): Handle number parsing more
+ consistent with strftime. Only parse a given number of digits.
+ (get_alt_number): Fix implementation. Was broken.
+ (strptime_internal): Add third parameter to get_number and
+ get_alt_number calls.
+
1999-07-13 Jakub Jelinek <jj@ultra.linux.cz>
* elf/ldd.bash.in: Add support for multiple dynamic linkers.
diff --git a/time/strptime.c b/time/strptime.c
index 14814ce153..959810e0f3 100644
--- a/time/strptime.c
+++ b/time/strptime.c
@@ -83,8 +83,9 @@ localtime_r (t, tp)
#endif
/* We intentionally do not use isdigit() for testing because this will
lead to problems with the wide character version. */
-#define get_number(from, to) \
+#define get_number(from, to, n) \
do { \
+ int __n = n; \
val = 0; \
while (*rp == ' ') \
++rp; \
@@ -93,42 +94,60 @@ localtime_r (t, tp)
do { \
val *= 10; \
val += *rp++ - '0'; \
- } while (val * 10 <= to && *rp >= '0' && *rp <= '9'); \
+ } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \
if (val < from || val > to) \
return NULL; \
} while (0)
#ifdef _NL_CURRENT
-# define get_alt_number(from, to) \
- do { \
+# define get_alt_number(from, to, n) \
+ ({ \
+ __label__ do_normal; \
if (*decided != raw) \
{ \
const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \
+ int __n = n; \
+ int any = 0; \
+ while (*rp == ' ') \
+ ++rp; \
val = 0; \
- while (*alts != '\0') \
- { \
- size_t len = strlen (alts); \
- if (strncasecmp (alts, rp, len) == 0) \
+ do { \
+ val *= 10; \
+ while (*alts != '\0') \
+ { \
+ size_t len = strlen (alts); \
+ if (strncasecmp (alts, rp, len) == 0) \
+ break; \
+ alts += len + 1; \
+ ++val; \
+ } \
+ if (*alts == '\0') \
+ { \
+ if (*decided == not && ! any) \
+ goto do_normal; \
+ /* If we haven't read anything it's an error. */ \
+ if (! any) \
+ return NULL; \
+ /* Correct the premature multiplication. */ \
+ val /= 10; \
break; \
- alts = strchr (alts, '\0') + 1; \
- ++val; \
- } \
- if (*alts == '\0') \
- { \
- if (*decided == loc && val != 0) \
- return NULL; \
- } \
- else \
- { \
+ } \
+ else \
*decided = loc; \
- break; \
- } \
+ } while (--__n > 0 && val * 10 <= to); \
+ if (val < from || val > to) \
+ return NULL; \
} \
- get_number (from, to); \
- } while (0)
+ else \
+ { \
+ do_normal: \
+ get_number (from, to, n); \
+ } \
+ 0; \
+ })
#else
-# define get_alt_number(from, to) \
+# define get_alt_number(from, to, n) \
/* We don't have the alternate representation. */ \
- get_number(from, to)
+ get_number(from, to, n)
#endif
#define recursive(new_fmt) \
(*(new_fmt) != '\0' \
@@ -253,7 +272,7 @@ strptime_internal (buf, format, tm, decided)
int have_wday, want_xday;
int have_yday;
int have_mon, have_mday;
-
+
rp = buf;
fmt = format;
have_I = is_pm = 0;
@@ -399,14 +418,14 @@ strptime_internal (buf, format, tm, decided)
break;
case 'C':
/* Match century number. */
- get_number (0, 99);
+ get_number (0, 99, 2);
century = val;
want_xday = 1;
break;
case 'd':
case 'e':
/* Match day of month. */
- get_number (1, 31);
+ get_number (1, 31, 2);
tm->tm_mday = val;
have_mday = 1;
want_xday = 1;
@@ -446,32 +465,32 @@ strptime_internal (buf, format, tm, decided)
case 'k':
case 'H':
/* Match hour in 24-hour clock. */
- get_number (0, 23);
+ get_number (0, 23, 2);
tm->tm_hour = val;
have_I = 0;
break;
case 'I':
/* Match hour in 12-hour clock. */
- get_number (1, 12);
+ get_number (1, 12, 2);
tm->tm_hour = val % 12;
have_I = 1;
break;
case 'j':
/* Match day number of year. */
- get_number (1, 366);
+ get_number (1, 366, 3);
tm->tm_yday = val - 1;
have_yday = 1;
break;
case 'm':
/* Match number of month. */
- get_number (1, 12);
+ get_number (1, 12, 2);
tm->tm_mon = val - 1;
have_mon = 1;
want_xday = 1;
break;
case 'M':
/* Match minute. */
- get_number (0, 59);
+ get_number (0, 59, 2);
tm->tm_min = val;
break;
case 'n':
@@ -558,7 +577,7 @@ strptime_internal (buf, format, tm, decided)
}
break;
case 'S':
- get_number (0, 61);
+ get_number (0, 61, 2);
tm->tm_sec = val;
break;
case 'X':
@@ -585,12 +604,12 @@ strptime_internal (buf, format, tm, decided)
return NULL;
break;
case 'u':
- get_number (1, 7);
+ get_number (1, 7, 1);
tm->tm_wday = val % 7;
have_wday = 1;
break;
case 'g':
- get_number (0, 99);
+ get_number (0, 99, 2);
/* XXX This cannot determine any field in TM. */
break;
case 'G':
@@ -605,19 +624,19 @@ strptime_internal (buf, format, tm, decided)
case 'U':
case 'V':
case 'W':
- get_number (0, 53);
+ get_number (0, 53, 2);
/* XXX This cannot determine any field in TM without some
information. */
break;
case 'w':
/* Match number of weekday. */
- get_number (0, 6);
+ get_number (0, 6, 1);
tm->tm_wday = val;
have_wday = 1;
break;
case 'y':
/* Match year within century. */
- get_number (0, 99);
+ get_number (0, 99, 2);
/* The "Year 2000: The Millennium Rollover" paper suggests that
values in the range 69-99 refer to the twentieth century. */
tm->tm_year = val >= 69 ? val : val + 100;
@@ -627,7 +646,7 @@ strptime_internal (buf, format, tm, decided)
break;
case 'Y':
/* Match year including century number. */
- get_number (0, 9999);
+ get_number (0, 9999, 4);
tm->tm_year = val - 1900;
want_century = 0;
want_xday = 1;
@@ -744,7 +763,7 @@ strptime_internal (buf, format, tm, decided)
case 'd':
case 'e':
/* Match day of month using alternate numeric symbols. */
- get_alt_number (1, 31);
+ get_alt_number (1, 31, 2);
tm->tm_mday = val;
have_mday = 1;
want_xday = 1;
@@ -752,50 +771,50 @@ strptime_internal (buf, format, tm, decided)
case 'H':
/* Match hour in 24-hour clock using alternate numeric
symbols. */
- get_alt_number (0, 23);
+ get_alt_number (0, 23, 2);
tm->tm_hour = val;
have_I = 0;
break;
case 'I':
/* Match hour in 12-hour clock using alternate numeric
symbols. */
- get_alt_number (1, 12);
+ get_alt_number (1, 12, 2);
tm->tm_hour = val - 1;
have_I = 1;
break;
case 'm':
/* Match month using alternate numeric symbols. */
- get_alt_number (1, 12);
+ get_alt_number (1, 12, 2);
tm->tm_mon = val - 1;
have_mon = 1;
want_xday = 1;
break;
case 'M':
/* Match minutes using alternate numeric symbols. */
- get_alt_number (0, 59);
+ get_alt_number (0, 59, 2);
tm->tm_min = val;
break;
case 'S':
/* Match seconds using alternate numeric symbols. */
- get_alt_number (0, 61);
+ get_alt_number (0, 61, 2);
tm->tm_sec = val;
break;
case 'U':
case 'V':
case 'W':
- get_alt_number (0, 53);
+ get_alt_number (0, 53, 2);
/* XXX This cannot determine any field in TM without
further information. */
break;
case 'w':
/* Match number of weekday using alternate numeric symbols. */
- get_alt_number (0, 6);
+ get_alt_number (0, 6, 1);
tm->tm_wday = val;
have_wday = 1;
break;
case 'y':
/* Match year within century using alternate numeric symbols. */
- get_alt_number (0, 99);
+ get_alt_number (0, 99, 2);
tm->tm_year = val >= 69 ? val : val + 100;
want_xday = 1;
break;
@@ -824,9 +843,9 @@ strptime_internal (buf, format, tm, decided)
tm->tm_mon = t_mon - 1;
if (!have_mday)
tm->tm_mday = tm->tm_yday - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1;
- }
+ }
day_of_the_week (tm);
- }
+ }
if (want_xday && !have_yday)
day_of_the_year (tm);