summaryrefslogtreecommitdiffstats
path: root/lib/libc/locale/setrunelocale.c
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2002-08-08 05:51:54 +0000
committerache <ache@FreeBSD.org>2002-08-08 05:51:54 +0000
commit3b0ddae36e14f345ddbfb571d2838b236c78d073 (patch)
tree92e69228cb60dc54efe523b4a60905762797b926 /lib/libc/locale/setrunelocale.c
parenta72d8585b7d6c0e0b3cd0824b229a07724c33288 (diff)
downloadFreeBSD-src-3b0ddae36e14f345ddbfb571d2838b236c78d073.zip
FreeBSD-src-3b0ddae36e14f345ddbfb571d2838b236c78d073.tar.gz
Rewrite locale loading procedures, so any load failure will not affect
currently cached data. It allows a number of nice things, like: removing fallback code from single locale loading, remove memory leak when LC_CTYPE data loaded again and again, efficient cache use, not only for setlocale(locale1); setlocale(locale1), but for setlocale(locale1); setlocale("C"); setlocale(locale1) too (i.e. data file loaded only once).
Diffstat (limited to 'lib/libc/locale/setrunelocale.c')
-rw-r--r--lib/libc/locale/setrunelocale.c71
1 files changed, 50 insertions, 21 deletions
diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c
index 11d97bd..f1a01fc 100644
--- a/lib/libc/locale/setrunelocale.c
+++ b/lib/libc/locale/setrunelocale.c
@@ -54,12 +54,15 @@ extern int _MSKanji_init(_RuneLocale *);
extern _RuneLocale *_Read_RuneMagi(FILE *);
int
-setrunelocale(encoding)
- char *encoding;
+setrunelocale(char *encoding)
{
FILE *fp;
char name[PATH_MAX];
_RuneLocale *rl;
+ int saverr, ret;
+ static char ctype_encoding[ENCODING_LEN + 1];
+ static _RuneLocale *CachedRuneLocale;
+ static int Cached__mb_cur_max;
if (!encoding || !*encoding || strlen(encoding) > ENCODING_LEN ||
(encoding[0] == '.' &&
@@ -71,12 +74,25 @@ setrunelocale(encoding)
/*
* The "C" and "POSIX" locale are always here.
*/
- if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) {
+ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
_CurrentRuneLocale = &_DefaultRuneLocale;
__mb_cur_max = 1;
return (0);
}
+ /*
+ * If the locale name is the same as our cache, use the cache.
+ */
+ if (CachedRuneLocale != NULL &&
+ strcmp(encoding, ctype_encoding) == 0) {
+ _CurrentRuneLocale = CachedRuneLocale;
+ __mb_cur_max = Cached__mb_cur_max;
+ return (0);
+ }
+
+ /*
+ * Slurp the locale file into the cache.
+ */
if (_PathLocale == NULL) {
char *p = getenv("PATH_LOCALE");
@@ -90,7 +106,7 @@ setrunelocale(encoding)
return (ENAMETOOLONG);
_PathLocale = strdup(p);
if (_PathLocale == NULL)
- return (errno);
+ return (ENOMEM);
} else
_PathLocale = _PATH_LOCALE;
}
@@ -103,25 +119,38 @@ setrunelocale(encoding)
if ((fp = fopen(name, "r")) == NULL)
return (errno);
- if ((rl = _Read_RuneMagi(fp)) == 0) {
- fclose(fp);
- return (EFTYPE);
+ if ((rl = _Read_RuneMagi(fp)) == NULL) {
+ saverr = errno;
+ (void)fclose(fp);
+ return (saverr);
}
- fclose(fp);
+ (void)fclose(fp);
- if (!rl->encoding[0])
- return (EFTYPE);
- else if (!strcmp(rl->encoding, "NONE"))
- return (_none_init(rl));
- else if (!strcmp(rl->encoding, "UTF2"))
- return (_UTF2_init(rl));
- else if (!strcmp(rl->encoding, "EUC"))
- return (_EUC_init(rl));
- else if (!strcmp(rl->encoding, "BIG5"))
- return (_BIG5_init(rl));
- else if (!strcmp(rl->encoding, "MSKanji"))
- return (_MSKanji_init(rl));
+ if (strcmp(rl->encoding, "NONE") == 0)
+ ret = _none_init(rl);
+ else if (strcmp(rl->encoding, "UTF2") == 0)
+ ret = _UTF2_init(rl);
+ else if (strcmp(rl->encoding, "EUC") == 0)
+ ret = _EUC_init(rl);
+ else if (strcmp(rl->encoding, "BIG5") == 0)
+ ret = _BIG5_init(rl);
+ else if (strcmp(rl->encoding, "MSKanji") == 0)
+ ret = _MSKanji_init(rl);
else
- return (EFTYPE);
+ ret = EFTYPE;
+ if (ret == 0) {
+ if (CachedRuneLocale != NULL) {
+ /* See euc.c */
+ if (strcmp(CachedRuneLocale->encoding, "EUC") == 0)
+ free(CachedRuneLocale->variable);
+ free(CachedRuneLocale);
+ }
+ CachedRuneLocale = _CurrentRuneLocale;
+ Cached__mb_cur_max = __mb_cur_max;
+ (void)strcpy(ctype_encoding, encoding);
+ } else
+ free(rl);
+
+ return (ret);
}
OpenPOWER on IntegriCloud