collate.c.patch   [plain text]


--- 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++)