From 958d68077b3fa1435c010711876a9229e5cd4192 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Tue, 21 Dec 1999 17:50:57 +0000 Subject: Update. 1999-12-21 Shinya Hanataka * 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 * 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 * sysdeps/arm/dl-machine.c (CLEAR_CACHE): Fix a2 value. Patch by Scott Bambrough . --- ChangeLog | 25 +++++++ locale/lc-time.c | 153 ++++++++++++++---------------------------- locale/localeinfo.h | 22 +++--- locale/programs/ld-time.c | 6 ++ localedata/ChangeLog | 5 ++ localedata/locales/ja_JP | 8 +-- sysdeps/arm/dl-machine.h | 2 +- time/strftime.c | 28 ++------ time/strptime.c | 166 ++++++++++++++++++++++++++++++++++++++++------ 9 files changed, 256 insertions(+), 159 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8a35238aba..6ecc3cff0a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +1999-12-21 Shinya Hanataka + + * 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 + + * 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 + + * sysdeps/arm/dl-machine.c (CLEAR_CACHE): Fix a2 value. + Patch by Scott Bambrough . + 1999-12-21 Andreas Schwab * sysdeps/unix/sysv/linux/pread.c: Fix typo. diff --git a/locale/lc-time.c b/locale/lc-time.c index 423adefb2f..c6bf4b10e0 100644 --- a/locale/lc-time.c +++ b/locale/lc-time.c @@ -32,13 +32,9 @@ __libc_lock_define (extern, __libc_setlocale_lock) static int era_initialized; -static struct era_entry **eras; -static const void **eras_nf; -static size_t num_eras; - -#define ERAS_NF(cnt, category) \ - *(eras_nf + ERA_NAME_FORMAT_MEMBERS * (cnt) + (category)) +static struct era_entry *eras; +static size_t num_eras; static int alt_digits_initialized; static const char **alt_digits; @@ -56,17 +52,21 @@ _nl_postload_time (void) walt_digits_initialized = 0; } +#define ERA_DATE_CMP(a, b) \ + (a[0] < b[0] || (a[0] == b[0] && (a[1] < b[1] \ + || (a[1] == b[1] && a[2] <= b[2])))) static void -init_era_entry (void) +_nl_init_era_entries (void) { size_t cnt; + __libc_lock_lock (__libc_setlocale_lock); + if (era_initialized == 0) { size_t new_num_eras = _NL_CURRENT_WORD (LC_TIME, _NL_TIME_ERA_NUM_ENTRIES); - if (new_num_eras == 0) { if (eras != NULL) @@ -74,57 +74,59 @@ init_era_entry (void) free (eras); eras = NULL; } - if (eras_nf != NULL) - { - free (eras_nf); - eras_nf = NULL; - } } else { if (num_eras != new_num_eras) - { - eras = realloc (eras, - new_num_eras * sizeof (struct era_entry *)); - eras_nf = realloc (eras_nf, - new_num_eras * sizeof (void *) - * ERA_NAME_FORMAT_MEMBERS); - } - - if (eras == NULL || eras_nf == NULL) + eras = realloc (eras, + new_num_eras * sizeof (struct era_entry *)); + if (eras == NULL) { num_eras = 0; eras = NULL; - eras_nf = NULL; } - else + else { const char *ptr = _NL_CURRENT (LC_TIME, _NL_TIME_ERA_ENTRIES); num_eras = new_num_eras; for (cnt = 0; cnt < num_eras; ++cnt) { - eras[cnt] = (struct era_entry *) ptr; + const char *base_ptr = ptr; + memcpy((void*)(eras + cnt), (const void *) ptr, + sizeof (uint32_t) * 8); + + if (ERA_DATE_CMP(eras[cnt].start_date, + eras[cnt].stop_date)) + if (eras[cnt].direction == (uint32_t) '+') + eras[cnt].absolute_direction = 1; + else + eras[cnt].absolute_direction = -1; + else + if (eras[cnt].direction == (uint32_t) '+') + eras[cnt].absolute_direction = -1; + else + eras[cnt].absolute_direction = 1; /* Skip numeric values. */ - ptr += sizeof (struct era_entry); + ptr += sizeof (uint32_t) * 8; /* Set and skip era name. */ - ERAS_NF (cnt, ERA_M_NAME) = (void *) ptr; + eras[cnt].era_name = ptr; ptr = strchr (ptr, '\0') + 1; /* Set and skip era format. */ - ERAS_NF (cnt, ERA_M_FORMAT) = (void *) ptr; + eras[cnt].era_format = ptr; ptr = strchr (ptr, '\0') + 1; - ptr += 3 - (((ptr - (const char *) eras[cnt]) + 3) & 3); + ptr += 3 - (((ptr - (const char *) base_ptr) + 3) & 3); /* Set and skip wide era name. */ - ERAS_NF (cnt, ERA_W_NAME) = (void *) ptr; + eras[cnt].era_wname = (wchar_t *) ptr; ptr = (char *) (wcschr ((wchar_t *) ptr, '\0') + 1); /* Set and skip wide era format. */ - ERAS_NF (cnt, ERA_W_FORMAT) = (void *) ptr; + eras[cnt].era_wformat = (wchar_t *) ptr; ptr = (char *) (wcschr ((wchar_t *) ptr, '\0') + 1); } } @@ -132,6 +134,8 @@ init_era_entry (void) era_initialized = 1; } + + __libc_lock_unlock (__libc_setlocale_lock); } @@ -139,92 +143,37 @@ struct era_entry * _nl_get_era_entry (const struct tm *tp) { struct era_entry *result; + int32_t tdate[3]; size_t cnt; - __libc_lock_lock (__libc_setlocale_lock); + tdate[0] = tp->tm_year; + tdate[1] = tp->tm_mon; + tdate[2] = tp->tm_mday; - init_era_entry (); + if (era_initialized == 0) + _nl_init_era_entries (); /* Now compare date with the available eras. */ for (cnt = 0; cnt < num_eras; ++cnt) - if ((eras[cnt]->start_date[0] < tp->tm_year - || (eras[cnt]->start_date[0] == tp->tm_year - && (eras[cnt]->start_date[1] < tp->tm_mon - || (eras[cnt]->start_date[1] == tp->tm_mon - && eras[cnt]->start_date[2] <= tp->tm_mday)))) - && (eras[cnt]->stop_date[0] > tp->tm_year - || (eras[cnt]->stop_date[0] == tp->tm_year - && (eras[cnt]->stop_date[1] > tp->tm_mon - || (eras[cnt]->stop_date[1] == tp->tm_mon - && eras[cnt]->stop_date[2] >= tp->tm_mday))))) + if ((ERA_DATE_CMP(eras[cnt].start_date, tdate) + && ERA_DATE_CMP(tdate, eras[cnt].stop_date)) + || (ERA_DATE_CMP(eras[cnt].stop_date, tdate) + && ERA_DATE_CMP(tdate, eras[cnt].start_date))) break; - result = cnt < num_eras ? eras[cnt] : NULL; - - __libc_lock_unlock (__libc_setlocale_lock); + result = cnt < num_eras ? &eras[cnt] : NULL; return result; } -const void * -_nl_get_era_nf_entry (int cnt, int category) -{ - const void *result; - - __libc_lock_lock (__libc_setlocale_lock); - - init_era_entry (); - - if (eras_nf == NULL) - result = NULL; - else - result = ERAS_NF (cnt, category); - - __libc_lock_unlock (__libc_setlocale_lock); - - return result; -} - - -int -_nl_get_era_year_offset (int cnt, int val) -{ - __libc_lock_lock (__libc_setlocale_lock); - - init_era_entry (); - - if (eras == NULL) - val = -1; - else - { - val -= eras[cnt]->offset; - - if (val < 0 || - val > (eras[cnt]->stop_date[0] - eras[cnt]->start_date[0])) - val = -1; - } - - __libc_lock_unlock (__libc_setlocale_lock); - - return val; -} - - -int -_nl_get_era_year_start (int cnt) +struct era_entry * +_nl_select_era_entry (int cnt) { - int result; - - __libc_lock_lock (__libc_setlocale_lock); - - init_era_entry (); - - result = eras[cnt]->start_date[0]; - - __libc_lock_unlock (__libc_setlocale_lock); + if (era_initialized == 0) + _nl_init_era_entries (); - return result; + return &eras[cnt]; } diff --git a/locale/localeinfo.h b/locale/localeinfo.h index ee402dbf9f..c72ea9d84d 100644 --- a/locale/localeinfo.h +++ b/locale/localeinfo.h @@ -107,7 +107,14 @@ struct era_entry int32_t offset; int32_t start_date[3]; int32_t stop_date[3]; - const char name_fmt[0]; + const char *era_name; + const char *era_format; + const wchar_t *era_wname; + const wchar_t *era_wformat; + int absolute_direction; + /* absolute direction: + +1 indicates that year number is higher in the future. (like A.D.) + -1 indicates that year number is higher in the past. (like B.C.) */ }; @@ -160,17 +167,14 @@ extern void _nl_unload_locale (struct locale_data *locale); extern void _nl_remove_locale (int locale, struct locale_data *data); +/* initialize `era' entries */ +extern void _nl_init_era_entries (void); + /* Return `era' entry which corresponds to TP. Used in strftime. */ extern struct era_entry *_nl_get_era_entry (const struct tm *tp); -/* Return `era' string of the cnt'th `category' entry. */ -extern const void *_nl_get_era_nf_entry (int cnt, int category); - -/* Return a offset of `era' year of the cnt'th entry. */ -extern int _nl_get_era_year_offset (int cnt, int category); - -/* Return a start of `era' year of the cnt'th entry. */ -extern int _nl_get_era_year_start (int cnt); +/* Return `era' cnt'th entry . Used in strptime. */ +extern struct era_entry *_nl_select_era_entry (int cnt); /* Return `alt_digit' which corresponds to NUMBER. Used in strftime. */ extern const char *_nl_get_alt_digit (unsigned int number); diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c index b2c06cca7c..5e12c9ba78 100644 --- a/locale/programs/ld-time.c +++ b/locale/programs/ld-time.c @@ -285,6 +285,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap) else str = endp + 1; time->era_entries[idx].start_date[0] -= 1900; + /* year -1 represent 1 B.C. (not -1 A.D.) */ + if (time->era_entries[idx].start_date[0] < -1900) + ++time->era_entries[idx].start_date[0]; time->era_entries[idx].start_date[1] = strtol (str, &endp, 10); if (endp == str || *endp != '/') @@ -359,6 +362,9 @@ time_finish (struct localedef_t *locale, struct charmap_t *charmap) else str = endp + 1; time->era_entries[idx].stop_date[0] -= 1900; + /* year -1 represent 1 B.C. (not -1 A.D.) */ + if (time->era_entries[idx].stop_date[0] < -1900) + ++time->era_entries[idx].stop_date[0]; time->era_entries[idx].stop_date[1] = strtol (str, &endp, 10); if (endp == str || *endp != '/') diff --git a/localedata/ChangeLog b/localedata/ChangeLog index aea0c7e9b7..b0d7886450 100644 --- a/localedata/ChangeLog +++ b/localedata/ChangeLog @@ -1,3 +1,8 @@ +1999-12-21 Ulrich Drepper + + * locales/ja_JP: Fix cntrl mapping and era definition. + Patch by Shinya Hanataka . + 1999-12-20 Ulrich Drepper * locales/af_ZA: New file. diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP index 6bf6dc11bd..a7dbe82229 100644 --- a/localedata/locales/ja_JP +++ b/localedata/locales/ja_JP @@ -3,8 +3,8 @@ comment_char % repertoiremap mnemonic.ja % Name: localedef for ja_JP -% Version: 0.6 -% Date: 1999-11-28 +% Version: 0.7 +% Date: 1999-12-05 % Write: HANATAKA, Shinya LC_CTYPE @@ -76,7 +76,7 @@ cntrl ;;;;;/ ;;;;;;;;;/ ;;;;;;;;;/ ;;;;;;;;/ - ;;;;;;;;;;/ + ;;;;;;;;;;/ ;;;;;;;;;;/ ;;;;;;;;; @@ -1652,7 +1652,7 @@ era "+:2:1990//01//01:+*::%EC%Ey";/ "+:2:1912//07//30:1912//12//31::%EC";/ "+:6:1873//01//01:1912//07//29::%EC%Ey";/ "+:1:0001//01//01:1872//12//31::%EC%Ey";/ - "-:1:0000//12//31:-*::%EC%Ey" + "+:1:-0001//12//31:-*::%EC%Ey" era_d_fmt "%EY%m%d" diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h index de2d0babf5..ef5584f19f 100644 --- a/sysdeps/arm/dl-machine.h +++ b/sysdeps/arm/dl-machine.h @@ -35,7 +35,7 @@ #define CLEAR_CACHE(BEG,END) \ { \ register unsigned long _beg __asm ("a1") = (unsigned long)(BEG); \ - register unsigned long _end __asm ("a2") = (unsigned long)((END) - (BEG));\ + register unsigned long _end __asm ("a2") = (unsigned long)(END); \ register unsigned long _flg __asm ("a3") = 0; \ __asm __volatile ("swi 0x9f0002"); \ } diff --git a/time/strftime.c b/time/strftime.c index 7de2e84c50..d53fdfe93b 100644 --- a/time/strftime.c +++ b/time/strftime.c @@ -834,19 +834,11 @@ my_strftime (s, maxsize, format, tp ut_argument) if (era) { # ifdef COMPILE_WIDE - /* The wide name is after the multi byte name and - format. */ - wchar_t *ws; - size_t len; - char *tcp = strchr (era->name_fmt, '\0') + 1; - tcp = strchr (tcp, '\0') + 1; - tcp += 3 - (((tcp - era->name_fmt) + 3) & 3); - ws = (wchar_t *) tcp; - len = wcslen (ws); - cpy (len, ws); + size_t len = strlen (era->era_name); + cpy (len, era->era_name); # else - size_t len = strlen (era->name_fmt); - cpy (len, era->name_fmt); + size_t len = strlen (era->era_name); + cpy (len, era->era_name); # endif break; } @@ -1199,15 +1191,9 @@ my_strftime (s, maxsize, format, tp ut_argument) if (era) { # ifdef COMPILE_WIDE - /* The wide name is after the multi byte name and - format. */ - char *tcp = strchr (era->name_fmt, '\0') + 1; - tcp = strchr (tcp, '\0') + 1; - tcp += 3 - (((tcp - era->name_fmt) + 3) & 3); - subfmt = (wchar_t *) tcp; - subfmt = wcschr (subfmt, L'\0') + 1; + subfmt = era->era_wformat; # else - subfmt = strchr (era->name_fmt, '\0') + 1; + subfmt = era->era_format; # endif goto subformat; } @@ -1231,7 +1217,7 @@ my_strftime (s, maxsize, format, tp ut_argument) { int delta = tp->tm_year - era->start_date[0]; DO_NUMBER (1, (era->offset - + (era->direction == '-' ? -delta : delta))); + + delta * era->absolute_direction)); } #else # if HAVE_STRFTIME 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); } -- cgit 1.4.1