+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>.
+
1999-12-21 Andreas Schwab <schwab@suse.de>
* sysdeps/unix/sysv/linux/pread.c: Fix typo.
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;
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)
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);
}
}
era_initialized = 1;
}
+
+ __libc_lock_unlock (__libc_setlocale_lock);
}
_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];
}
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.) */
};
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);
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 != '/')
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 != '/')
+1999-12-21 Ulrich Drepper <drepper@cygnus.com>
+
+ * locales/ja_JP: Fix cntrl mapping and era definition.
+ Patch by Shinya Hanataka <hanataka@abyss.rim.or.jp>.
+
1999-12-20 Ulrich Drepper <drepper@cygnus.com>
* locales/af_ZA: New file.
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 <hanataka@abyss.rim.or.jp>
LC_CTYPE
<NUL>;<SOH>;<STX>;<ETX>;<EOT>;<ENQ>;<ACK>;<SO>;<SI>;/
<DLE>;<DC1>;<DC2>;<DC3>;<DC4>;<NAK>;<SYN>;<ETB>;<CAN>;/
<EM>;<SUB>;<ESC>;<IS4>;<IS3>;<IS2>;<IS1>;<DEL>;/
- <PBH>;<HOP>;<BPH>;<NBH>;<IND>;<NEL>;<SSA>;<ESA>;<HTS>;<HTJ>;/
+ <PAD>;<HOP>;<BPH>;<NBH>;<IND>;<NEL>;<SSA>;<ESA>;<HTS>;<HTJ>;/
<VTS>;<PLD>;<PLU>;<RI>;<DCS>;<PU1>;<PU2>;<STS>;<CCH>;<MW>;/
<SPA>;<EPA>;<SOS>;<SGCI>;<SCI>;<CSI>;<ST>;<OSC>;<PM>;<APC>
"+:2:1912//07//30:1912//12//31:<j3471><j3221>:%EC<j2421><j3915>";/
"+:6:1873//01//01:1912//07//29:<j4432><j2803>:%EC%Ey<j3915>";/
"+:1:0001//01//01:1872//12//31:<j3230><j4681>:%EC%Ey<j3915>";/
- "-:1:0000//12//31:-*:<j2110><j2421><j3316>:%EC%Ey<j3915>"
+ "+:1:-0001//12//31:-*:<j2110><j2421><j3316>:%EC%Ey<j3915>"
era_d_fmt "%EY%m<j2378>%d<j3892>"
#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"); \
}
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;
}
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;
}
{
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
#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
#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')
/* We need this for handling the `E' modifier. */
start_over:
#endif
+
+ /* Make back up of current processing pointer. */
+ rp_backup = rp;
+
switch (*fmt++)
{
case '%':
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
break;
case 'C':
/* Match century number. */
+ match_century:
get_number (0, 99, 2);
century = val;
want_xday = 1;
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
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
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
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)
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
{
if (*decided == loc)
return NULL;
+ else
+ rp = rp_backup;
}
else
{
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);
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);
}