aboutsummaryrefslogtreecommitdiff
path: root/time/strptime.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-12-21 17:50:57 +0000
committerUlrich Drepper <drepper@redhat.com>1999-12-21 17:50:57 +0000
commit958d68077b3fa1435c010711876a9229e5cd4192 (patch)
tree156271e1ee5af5f3127c9c1fad4dbfd868a976b4 /time/strptime.c
parentbef248950aa7624e21c404948e8e5a7a3f2b83b7 (diff)
downloadglibc-958d68077b3fa1435c010711876a9229e5cd4192.tar
glibc-958d68077b3fa1435c010711876a9229e5cd4192.tar.gz
glibc-958d68077b3fa1435c010711876a9229e5cd4192.tar.bz2
glibc-958d68077b3fa1435c010711876a9229e5cd4192.zip
Update.
1999-12-21 Shinya Hanataka <hanataka@abyss.rim.or.jp> * locale/lc-time.c: Extend structure era_entry. * locale/localeinfo.h: Likewise. * locale/lc-time.c: Handle '-' direction used in locale's era part properly. * time/strptime.c: Likewise. * time/strftime.c: Likewise. * locale/programs/ld-time.c: Consider negative values in era part of locale as B.C.. * time/strptime.c (strptime_internal): Merged Yoshiyama's %E[CyY] implementation. 1999-12-21 Akira Yoshiyama <yosshy@debian.or.jp> * time/strptime.c (strptime_internal): Fix segV bugs of a couple of recursive() call. * time/strptime.c (strptime_internal): Implement `%EC',`%Ey',`%EY' parsing. 1999-12-21 Ulrich Drepper <drepper@cygnus.com> * sysdeps/arm/dl-machine.c (CLEAR_CACHE): Fix a2 value. Patch by Scott Bambrough <scottb@netwinder.org>.
Diffstat (limited to 'time/strptime.c')
-rw-r--r--time/strptime.c166
1 files changed, 144 insertions, 22 deletions
diff --git a/time/strptime.c b/time/strptime.c
index 9499e0f684..970b1c957e 100644
--- a/time/strptime.c
+++ b/time/strptime.c
@@ -151,7 +151,7 @@ localtime_r (t, tp)
#endif
#define recursive(new_fmt) \
(*(new_fmt) != '\0' \
- && (rp = strptime_internal (rp, (new_fmt), tm, decided)) != NULL)
+ && (rp = strptime_internal (rp, (new_fmt), tm, decided, era_cnt)) != NULL)
#ifdef _LIBC
@@ -250,34 +250,38 @@ static char *
#ifdef _LIBC
internal_function
#endif
-strptime_internal __P ((const char *buf, const char *format, struct tm *tm,
- enum locale_status *decided));
+strptime_internal __P ((const char *rp, const char *fmt, struct tm *tm,
+ enum locale_status *decided, int era_cnt));
static char *
#ifdef _LIBC
internal_function
#endif
-strptime_internal (buf, format, tm, decided)
- const char *buf;
- const char *format;
+strptime_internal (rp, fmt, tm, decided, era_cnt)
+ const char *rp;
+ const char *fmt;
struct tm *tm;
enum locale_status *decided;
+ int era_cnt;
{
- const char *rp;
- const char *fmt;
+ const char *rp_backup;
int cnt;
size_t val;
int have_I, is_pm;
int century, want_century;
+ int want_era;
int have_wday, want_xday;
int have_yday;
int have_mon, have_mday;
+ size_t num_eras;
+ struct era_entry *era;
- rp = buf;
- fmt = format;
have_I = is_pm = 0;
century = -1;
want_century = 0;
+ want_era = 0;
+ era = NULL;
+
have_wday = want_xday = have_yday = have_mon = have_mday = 0;
while (*fmt != '\0')
@@ -305,6 +309,10 @@ strptime_internal (buf, format, tm, decided)
/* We need this for handling the `E' modifier. */
start_over:
#endif
+
+ /* Make back up of current processing pointer. */
+ rp_backup = rp;
+
switch (*fmt++)
{
case '%':
@@ -400,6 +408,8 @@ strptime_internal (buf, format, tm, decided)
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
@@ -418,6 +428,7 @@ strptime_internal (buf, format, tm, decided)
break;
case 'C':
/* Match century number. */
+ match_century:
get_number (0, 99, 2);
century = val;
want_xday = 1;
@@ -443,6 +454,8 @@ strptime_internal (buf, format, tm, decided)
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
@@ -534,6 +547,8 @@ strptime_internal (buf, format, tm, decided)
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
@@ -588,6 +603,8 @@ strptime_internal (buf, format, tm, decided)
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
@@ -635,6 +652,7 @@ strptime_internal (buf, format, tm, decided)
have_wday = 1;
break;
case 'y':
+ match_year_in_century:
/* Match year within century. */
get_number (0, 99, 2);
/* The "Year 2000: The Millennium Rollover" paper suggests that
@@ -671,6 +689,8 @@ strptime_internal (buf, format, tm, decided)
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
@@ -688,12 +708,90 @@ strptime_internal (buf, format, tm, decided)
want_xday = 1;
break;
case 'C':
- case 'y':
+ if (*decided != raw)
+ {
+ if (era_cnt >= 0)
+ {
+ era = _nl_select_era_entry (era_cnt);
+ if (match_string (era->era_name, rp))
+ {
+ *decided = loc;
+ break;
+ }
+ else
+ return NULL;
+ }
+ else
+ {
+ num_eras = _NL_CURRENT_WORD (LC_TIME,
+ _NL_TIME_ERA_NUM_ENTRIES);
+ for (era_cnt = 0; era_cnt < num_eras;
+ ++era_cnt, rp = rp_backup)
+ {
+ era = _nl_select_era_entry (era_cnt);
+ if (match_string (era->era_name, rp))
+ {
+ *decided = loc;
+ break;
+ }
+ }
+ if (era_cnt == num_eras)
+ {
+ era_cnt = -1;
+ if (*decided == loc)
+ return NULL;
+ }
+ else
+ break;
+ }
+
+ *decided = raw;
+ }
+ /* The C locale has no era information, so use the
+ normal representation. */
+ goto match_century;
+ case 'y':
+ if (*decided == raw)
+ goto match_year_in_century;
+
+ get_number(0, 9999, 4);
+ tm->tm_year = val;
+ want_era = 1;
+ want_xday = 1;
+ break;
case 'Y':
- /* Match name of base year in locale's alternate
- representation. */
- /* XXX This is currently not implemented. It should
- use the value _NL_CURRENT (LC_TIME, ERA). */
+ if (*decided != raw)
+ {
+ num_eras = _NL_CURRENT_WORD (LC_TIME,
+ _NL_TIME_ERA_NUM_ENTRIES);
+ for (era_cnt = 0; era_cnt < num_eras;
+ ++era_cnt, rp = rp_backup)
+ {
+ era = _nl_select_era_entry (era_cnt);
+ if (recursive (era->era_format))
+ break;
+ }
+ if (era_cnt == num_eras)
+ {
+ era_cnt = -1;
+ if (*decided == loc)
+ return NULL;
+ else
+ rp = rp_backup;
+ }
+ else
+ {
+ *decided = loc;
+ era_cnt = -1;
+ break;
+ }
+
+ *decided = raw;
+ }
+ get_number (0, 9999, 4);
+ tm->tm_year = val - 1900;
+ want_century = 0;
+ want_xday = 1;
break;
case 'x':
if (*decided != raw)
@@ -707,6 +805,8 @@ strptime_internal (buf, format, tm, decided)
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
@@ -731,6 +831,8 @@ strptime_internal (buf, format, tm, decided)
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
@@ -839,19 +941,38 @@ strptime_internal (buf, format, tm, decided)
tm->tm_year = (century - 19) * 100;
}
- if (want_xday && !have_wday) {
- if ( !(have_mon && have_mday) && have_yday) {
- /* we don't have tm_mon and/or tm_mday, compute them */
+ if (era_cnt != -1)
+ {
+ era = _nl_select_era_entry(era_cnt);
+ if (want_era)
+ tm->tm_year = (era->start_date[0]
+ + ((tm->tm_year - era->offset)
+ * era->absolute_direction));
+ else
+ /* Era start year assumed. */
+ tm->tm_year = era->start_date[0];
+ }
+ else
+ if (want_era)
+ return NULL;
+
+ if (want_xday && !have_wday)
+ {
+ if ( !(have_mon && have_mday) && have_yday)
+ {
+ /* We don't have tm_mon and/or tm_mday, compute them. */
int t_mon = 0;
while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
t_mon++;
if (!have_mon)
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;
- }
+ 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);
@@ -866,10 +987,11 @@ strptime (buf, format, tm)
struct tm *tm;
{
enum locale_status decided;
+
#ifdef _NL_CURRENT
decided = not;
#else
decided = raw;
#endif
- return strptime_internal (buf, format, tm, &decided);
+ return strptime_internal (buf, format, tm, &decided, -1);
}