summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2002-08-30 20:26:02 +0000
committerache <ache@FreeBSD.org>2002-08-30 20:26:02 +0000
commit1286c989d680b02f88a9c13952bbb57e99e7fbac (patch)
treecc03a67fbc20d6779a68e2600ee8cd1e1703c761
parentac79a8c0ebce44313944033ddef7dd8eb5f9574a (diff)
downloadFreeBSD-src-1286c989d680b02f88a9c13952bbb57e99e7fbac.zip
FreeBSD-src-1286c989d680b02f88a9c13952bbb57e99e7fbac.tar.gz
Prepare for switching to unlimited chains format.
Optimize chains lookup a bit.
-rw-r--r--lib/libc/locale/collate.c63
-rw-r--r--lib/libc/locale/collate.h6
2 files changed, 46 insertions, 23 deletions
diff --git a/lib/libc/locale/collate.c b/lib/libc/locale/collate.c
index 45493d4..614d5d5 100644
--- a/lib/libc/locale/collate.c
+++ b/lib/libc/locale/collate.c
@@ -49,7 +49,7 @@ int __collate_substitute_nontrivial;
u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
-struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
+struct __collate_st_chain_pri *__collate_chain_pri_table;
void __collate_err(int ex, const char *f) __dead2;
@@ -57,9 +57,8 @@ int
__collate_load_tables(const char *encoding)
{
FILE *fp;
- int i, saverr;
- char collate_version[STR_LEN];
- char buf[PATH_MAX];
+ int i, saverr, chains;
+ char strbuf[STR_LEN], buf[PATH_MAX];
void *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table;
static char collate_encoding[ENCODING_LEN + 1];
@@ -90,6 +89,37 @@ __collate_load_tables(const char *encoding)
if ((fp = fopen(buf, "r")) == NULL)
return (_LDP_ERROR);
+ if (fread(strbuf, sizeof(strbuf), 1, fp) != 1) {
+ saverr = errno;
+ (void)fclose(fp);
+ errno = saverr;
+ return (_LDP_ERROR);
+ }
+ chains = -1;
+ if (strcmp(strbuf, COLLATE_VERSION) == 0)
+ chains = 0;
+ else if (strcmp(strbuf, COLLATE_VERSION1_1) == 0)
+ chains = 1;
+ if (chains < 0) {
+ (void)fclose(fp);
+ errno = EFTYPE;
+ return (_LDP_ERROR);
+ }
+ if (chains) {
+ if (fread(strbuf, sizeof(strbuf), 1, fp) != 1) {
+ saverr = errno;
+ (void)fclose(fp);
+ errno = saverr;
+ return (_LDP_ERROR);
+ }
+ if ((chains = atoi(strbuf)) < 1) {
+ (void)fclose(fp);
+ errno = EFTYPE;
+ return (_LDP_ERROR);
+ }
+ } else
+ chains = TABLE_SIZE;
+
if ((TMP_substitute_table =
malloc(sizeof(__collate_substitute_table))) == NULL) {
saverr = errno;
@@ -106,7 +136,7 @@ __collate_load_tables(const char *encoding)
return (_LDP_ERROR);
}
if ((TMP_chain_pri_table =
- malloc(sizeof(__collate_chain_pri_table))) == NULL) {
+ malloc(sizeof(*__collate_chain_pri_table) * chains)) == NULL) {
saverr = errno;
free(TMP_substitute_table);
free(TMP_char_pri_table);
@@ -128,18 +158,10 @@ __collate_load_tables(const char *encoding)
} \
}
- FREAD(collate_version, sizeof(collate_version), 1, fp);
- if (strcmp(collate_version, COLLATE_VERSION) != 0) {
- free(TMP_substitute_table);
- free(TMP_char_pri_table);
- free(TMP_chain_pri_table);
- (void)fclose(fp);
- errno = EFTYPE;
- return (_LDP_ERROR);
- }
FREAD(TMP_substitute_table, sizeof(__collate_substitute_table), 1, fp);
FREAD(TMP_char_pri_table, sizeof(__collate_char_pri_table), 1, fp);
- FREAD(TMP_chain_pri_table, sizeof(__collate_chain_pri_table), 1, fp);
+ FREAD(TMP_chain_pri_table,
+ sizeof(*__collate_chain_pri_table) * chains, 1, fp);
(void)fclose(fp);
(void)strcpy(collate_encoding, encoding);
@@ -149,9 +171,9 @@ __collate_load_tables(const char *encoding)
if (__collate_char_pri_table_ptr != NULL)
free(__collate_char_pri_table_ptr);
__collate_char_pri_table_ptr = TMP_char_pri_table;
- if (__collate_chain_pri_table_ptr != NULL)
- free(__collate_chain_pri_table_ptr);
- __collate_chain_pri_table_ptr = TMP_chain_pri_table;
+ if (__collate_chain_pri_table != NULL)
+ free(__collate_chain_pri_table);
+ __collate_chain_pri_table = TMP_chain_pri_table;
__collate_substitute_nontrivial = 0;
for (i = 0; i < UCHAR_MAX + 1; i++) {
@@ -203,8 +225,9 @@ __collate_lookup(t, len, prim, sec)
*len = 1;
*prim = *sec = 0;
- for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) {
- if (strncmp(t, p2->str, strlen(p2->str)) == 0) {
+ for (p2 = __collate_chain_pri_table; p2->str[0] != '\0'; p2++) {
+ if (*t == p2->str[0] &&
+ strncmp(t, p2->str, strlen(p2->str)) == 0) {
*len = strlen(p2->str);
*prim = p2->prim;
*sec = p2->sec;
diff --git a/lib/libc/locale/collate.h b/lib/libc/locale/collate.h
index 413fdf3..ce03e74 100644
--- a/lib/libc/locale/collate.h
+++ b/lib/libc/locale/collate.h
@@ -36,7 +36,8 @@
#define STR_LEN 10
#define TABLE_SIZE 100
-#define COLLATE_VERSION "1.0\n"
+#define COLLATE_VERSION "1.0\n"
+#define COLLATE_VERSION1_1 "1.1\n"
struct __collate_st_char_pri {
int prim, sec;
@@ -52,8 +53,7 @@ extern int __collate_substitute_nontrivial;
extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
#define __collate_char_pri_table (*__collate_char_pri_table_ptr)
extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
-#define __collate_chain_pri_table (*__collate_chain_pri_table_ptr)
-extern struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
+extern struct __collate_st_chain_pri *__collate_chain_pri_table;
__BEGIN_DECLS
u_char *__collate_strdup(u_char *);
OpenPOWER on IntegriCloud