--- collate.c.orig 2004-11-25 11:38:16.000000000 -0800 +++ collate.c 2005-02-17 10:35:00.000000000 -0800 @@ -28,6 +28,11 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD: src/lib/libc/locale/collate.c,v 1.33 2004/09/22 16:56:48 stefanf Exp $"); +#include "xlocale_private.h" +/* assumes the locale_t variable is named loc */ +#define __collate_substitute_table (loc->__lc_collate->__substitute_table) +#define __collate_char_pri_table (loc->__lc_collate->__char_pri_table) + #include "namespace.h" #include <arpa/inet.h> #include <stdio.h> @@ -44,36 +49,46 @@ #include "libc_private.h" -int __collate_load_error = 1; -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; - void __collate_err(int ex, const char *f) __dead2; -int -__collate_load_tables(const char *encoding) +/* + * Normally, the __collate_* routines should all be __private_extern__, + * but grep is using them (3715846). Until we can provide an alternative, + * we leave them public, and provide a read-only __collate_load_error variable + */ +#undef __collate_load_error +int __collate_load_error = 1; + +__private_extern__ int +__collate_load_tables(const char *encoding, locale_t loc) { FILE *fp; int i, saverr, chains; uint32_t u32; 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]; + struct __xlocale_st_collate *TMP; + static struct __xlocale_st_collate *cache = NULL; /* 'encoding' must be already checked. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { - __collate_load_error = 1; + loc->__collate_load_error = 1; + if (loc == &__global_locale) + __collate_load_error = 1; + XL_RELEASE(loc->__lc_collate); + loc->__lc_collate = NULL; return (_LDP_CACHE); } /* * If the locale name is the same as our cache, use the cache. */ - if (strcmp(encoding, collate_encoding) == 0) { - __collate_load_error = 0; + if (cache && strcmp(encoding, cache->__encoding) == 0) { + loc->__collate_load_error = 0; + if (loc == &__global_locale) + __collate_load_error = 0; + XL_RELEASE(loc->__lc_collate); + loc->__lc_collate = cache; + XL_RETAIN(loc->__lc_collate); return (_LDP_CACHE); } @@ -121,115 +136,106 @@ } else chains = TABLE_SIZE; - if ((TMP_substitute_table = - malloc(sizeof(__collate_substitute_table))) == NULL) { - saverr = errno; - (void)fclose(fp); - errno = saverr; - return (_LDP_ERROR); - } - if ((TMP_char_pri_table = - malloc(sizeof(__collate_char_pri_table))) == NULL) { + if ((TMP = + malloc(sizeof(struct __xlocale_st_collate) + sizeof(struct __collate_st_chain_pri) * chains)) == NULL) { saverr = errno; - free(TMP_substitute_table); - (void)fclose(fp); - errno = saverr; - return (_LDP_ERROR); - } - if ((TMP_chain_pri_table = - malloc(sizeof(*__collate_chain_pri_table) * chains)) == NULL) { - saverr = errno; - free(TMP_substitute_table); - free(TMP_char_pri_table); (void)fclose(fp); errno = saverr; return (_LDP_ERROR); } + TMP->__refcount = 2; /* one for the locale, one for the cache */ + TMP->__free_extra = NULL; + TMP->__chain_pri_table = (struct __collate_st_chain_pri *)(TMP + 1); #define FREAD(a, b, c, d) \ { \ if (fread(a, b, c, d) != c) { \ saverr = errno; \ - free(TMP_substitute_table); \ - free(TMP_char_pri_table); \ - free(TMP_chain_pri_table); \ + free(TMP); \ (void)fclose(d); \ errno = saverr; \ 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), chains, fp); + FREAD(TMP->__substitute_table, sizeof(TMP->__substitute_table), 1, fp); + FREAD(TMP->__char_pri_table, sizeof(TMP->__char_pri_table), 1, fp); + FREAD(TMP->__chain_pri_table, + sizeof(struct __collate_st_chain_pri), chains, fp); (void)fclose(fp); - (void)strcpy(collate_encoding, encoding); - if (__collate_substitute_table_ptr != NULL) - free(__collate_substitute_table_ptr); - __collate_substitute_table_ptr = TMP_substitute_table; - 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 != NULL) - free(__collate_chain_pri_table); - __collate_chain_pri_table = TMP_chain_pri_table; + (void)strcpy(TMP->__encoding, encoding); + XL_RELEASE(cache); + cache = TMP; + XL_RELEASE(loc->__lc_collate); + loc->__lc_collate = cache; + /* no need to retain, since we set __refcount to 2 above */ - __collate_substitute_nontrivial = 0; + loc->__collate_substitute_nontrivial = 0; for (i = 0; i < UCHAR_MAX + 1; i++) { if (__collate_substitute_table[i][0] != i || __collate_substitute_table[i][1] != 0) { - __collate_substitute_nontrivial = 1; + loc->__collate_substitute_nontrivial = 1; break; } } - __collate_load_error = 0; + loc->__collate_load_error = 0; + if (loc == &__global_locale) + __collate_load_error = 0; return (_LDP_LOADED); } -u_char * -__collate_substitute(s) +__private_extern__ u_char * +__collate_substitute_l(s, loc) const u_char *s; + locale_t loc; { int dest_len, len, nlen; - int delta = strlen(s); + int delta = strlen((const char *)s); u_char *dest_str = NULL; if (s == NULL || *s == '\0') - return (__collate_strdup("")); + return (__collate_strdup((u_char *)"")); delta += delta / 8; dest_str = malloc(dest_len = delta); if (dest_str == NULL) __collate_err(EX_OSERR, __func__); len = 0; while (*s) { - nlen = len + strlen(__collate_substitute_table[*s]); + nlen = len + strlen((const char *)__collate_substitute_table[*s]); if (dest_len <= nlen) { dest_str = reallocf(dest_str, dest_len = nlen + delta); if (dest_str == NULL) __collate_err(EX_OSERR, __func__); } - (void)strcpy(dest_str + len, __collate_substitute_table[*s++]); + (void)strcpy((char *)(dest_str + len), (const char *)__collate_substitute_table[*s++]); len = nlen; } return (dest_str); } -void -__collate_lookup(t, len, prim, sec) +u_char * +__collate_substitute(s) + const u_char *s; +{ + return __collate_substitute_l(s, __current_locale()); +} + +__private_extern__ void +__collate_lookup_l(t, len, prim, sec, loc) const u_char *t; int *len, *prim, *sec; + locale_t loc; { struct __collate_st_chain_pri *p2; *len = 1; *prim = *sec = 0; - for (p2 = __collate_chain_pri_table; p2->str[0] != '\0'; p2++) { + for (p2 = loc->__lc_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); + strncmp((const char *)t, (const char *)p2->str, strlen((const char *)p2->str)) == 0) { + *len = strlen((const char *)p2->str); *prim = p2->prim; *sec = p2->sec; return; @@ -239,11 +245,19 @@ *sec = __collate_char_pri_table[*t].sec; } +void +__collate_lookup(t, len, prim, sec) + const u_char *t; + int *len, *prim, *sec; +{ + return __collate_lookup_l(t, len, prim, sec, __current_locale()); +} + u_char * __collate_strdup(s) u_char *s; { - u_char *t = strdup(s); + u_char *t = (u_char *)strdup((const char *)s); if (t == NULL) __collate_err(EX_OSERR, __func__); @@ -274,6 +288,7 @@ { int i; struct __collate_st_chain_pri *p2; + locale_t loc = __current_locale(); printf("Substitute table:\n"); for (i = 0; i < UCHAR_MAX + 1; i++) @@ -281,7 +296,7 @@ printf("\t'%c' --> \"%s\"\n", i, __collate_substitute_table[i]); printf("Chain priority table:\n"); - for (p2 = __collate_chain_pri_table; p2->str[0] != '\0'; p2++) + for (p2 = loc->__lc_collate->__chain_pri_table; p2->str[0] != '\0'; p2++) printf("\t\"%s\" : %d %d\n", p2->str, p2->prim, p2->sec); printf("Char priority table:\n"); for (i = 0; i < UCHAR_MAX + 1; i++)