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).
This commit is contained in:
Andrey A. Chernov 2002-08-08 05:51:54 +00:00
parent af8c0bce98
commit 76692b8025
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=101498
11 changed files with 260 additions and 193 deletions

View File

@ -40,68 +40,115 @@ __FBSDID("$FreeBSD$");
#include "collate.h"
#include "setlocale.h"
#include "ldpart.h"
#include "libc_private.h"
int __collate_load_error = 1;
int __collate_substitute_nontrivial;
char __collate_version[STR_LEN];
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];
#define FREAD(a, b, c, d) \
do { \
if (fread(a, b, c, d) != c) { \
(void)fclose(d); \
return -1; \
} \
} while(0)
void __collate_err(int ex, const char *f) __dead2;
int
__collate_load_tables(encoding)
char *encoding;
__collate_load_tables(const char *encoding)
{
char buf[PATH_MAX];
FILE *fp;
int i, save_load_error;
int i, saverr;
char collate_version[STR_LEN];
char buf[PATH_MAX];
char *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table;
static char collate_encoding[ENCODING_LEN + 1];
save_load_error = __collate_load_error;
__collate_load_error = 1;
if (!encoding) {
__collate_load_error = save_load_error;
return -1;
/* 'encoding' must be already checked. */
if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
__collate_load_error = 1;
return (_LDP_CACHE);
}
if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX"))
return 0;
if (!_PathLocale) {
__collate_load_error = save_load_error;
return -1;
/*
* If the locale name is the same as our cache, use the cache.
*/
if (strcmp(encoding, collate_encoding) == 0) {
__collate_load_error = 0;
return (_LDP_CACHE);
}
/*
* Slurp the locale file into the cache.
*/
/* 'PathLocale' must be already set & checked. */
/* Range checking not needed, encoding has fixed size */
(void)strcpy(buf, _PathLocale);
(void)strcat(buf, "/");
(void)strcat(buf, encoding);
(void)strcat(buf, "/LC_COLLATE");
if ((fp = fopen(buf, "r")) == NULL) {
__collate_load_error = save_load_error;
return -1;
}
FREAD(__collate_version, sizeof(__collate_version), 1, fp);
if (strcmp(__collate_version, COLLATE_VERSION) != 0) {
if ((fp = fopen(buf, "r")) == NULL)
return (_LDP_ERROR);
if ((TMP_substitute_table =
malloc(sizeof(__collate_substitute_table))) == NULL) {
(void)fclose(fp);
return -1;
errno = ENOMEM;
return (_LDP_ERROR);
}
FREAD(__collate_substitute_table, sizeof(__collate_substitute_table),
1, fp);
FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1,
fp);
FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1,
fp);
if ((TMP_char_pri_table =
malloc(sizeof(__collate_char_pri_table))) == NULL) {
free(TMP_substitute_table);
(void)fclose(fp);
errno = ENOMEM;
return (_LDP_ERROR);
}
if ((TMP_chain_pri_table =
malloc(sizeof(__collate_chain_pri_table))) == NULL) {
free(TMP_substitute_table);
free(TMP_char_pri_table);
(void)fclose(fp);
errno = ENOMEM;
return (_LDP_ERROR);
}
#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); \
(void)fclose(d); \
errno = saverr; \
return (_LDP_ERROR); \
} \
}
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);
(void)fclose(fp);
__collate_load_error = 0;
(void)strcpy(collate_encoding, encoding);
(void)memcpy(__collate_substitute_table, TMP_substitute_table,
sizeof(__collate_substitute_table));
(void)memcpy(__collate_char_pri_table, TMP_char_pri_table,
sizeof(__collate_char_pri_table));
(void)memcpy(__collate_chain_pri_table, TMP_chain_pri_table,
sizeof(__collate_chain_pri_table));
free(TMP_substitute_table);
free(TMP_char_pri_table);
free(TMP_chain_pri_table);
__collate_substitute_nontrivial = 0;
for (i = 0; i < UCHAR_MAX + 1; i++) {
@ -111,8 +158,9 @@ __collate_load_tables(encoding)
break;
}
}
__collate_load_error = 0;
return 0;
return (_LDP_LOADED);
}
u_char *
@ -152,8 +200,8 @@ __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]; p2++) {
if (strncmp(t, p2->str, strlen(p2->str)) == 0) {
*len = strlen(p2->str);
*prim = p2->prim;
*sec = p2->sec;

View File

@ -48,7 +48,6 @@ struct __collate_st_chain_pri {
extern int __collate_load_error;
extern int __collate_substitute_nontrivial;
extern char __collate_version[STR_LEN];
extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
extern struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
@ -56,7 +55,7 @@ extern struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
__BEGIN_DECLS
u_char *__collate_strdup(u_char *);
u_char *__collate_substitute(const u_char *);
int __collate_load_tables(char *);
int __collate_load_tables(const char *);
void __collate_lookup(const u_char *, int *, int *, int *);
int __collate_range_cmp(int, int);
#ifdef COLLATE_DEBUG

View File

@ -63,40 +63,36 @@ _EUC_init(rl)
_RuneLocale *rl;
{
_EucInfo *ei;
int x;
int x, new__mb_cur_max;
char *v, *e;
rl->sgetrune = _EUC_sgetrune;
rl->sputrune = _EUC_sputrune;
if (!rl->variable) {
free(rl);
if (rl->variable == NULL)
return (EFTYPE);
}
v = (char *) rl->variable;
v = (char *)rl->variable;
while (*v == ' ' || *v == '\t')
++v;
if ((ei = malloc(sizeof(_EucInfo))) == NULL) {
free(rl);
if ((ei = malloc(sizeof(_EucInfo))) == NULL)
return (ENOMEM);
}
__mb_cur_max = 0;
new__mb_cur_max = 0;
for (x = 0; x < 4; ++x) {
ei->count[x] = (int) strtol(v, &e, 0);
ei->count[x] = (int)strtol(v, &e, 0);
if (v == e || !(v = e)) {
free(rl);
free(ei);
return (EFTYPE);
}
if (__mb_cur_max < ei->count[x])
__mb_cur_max = ei->count[x];
if (new__mb_cur_max < ei->count[x])
new__mb_cur_max = ei->count[x];
while (*v == ' ' || *v == '\t')
++v;
ei->bits[x] = (int) strtol(v, &e, 0);
ei->bits[x] = (int)strtol(v, &e, 0);
if (v == e || !(v = e)) {
free(rl);
free(ei);
return (EFTYPE);
}
@ -105,18 +101,13 @@ _EUC_init(rl)
}
ei->mask = (int)strtol(v, &e, 0);
if (v == e || !(v = e)) {
free(rl);
free(ei);
return (EFTYPE);
}
if (sizeof(_EucInfo) <= rl->variable_len) {
memcpy(rl->variable, ei, sizeof(_EucInfo));
free(ei);
} else {
rl->variable = ei;
}
rl->variable = ei;
rl->variable_len = sizeof(_EucInfo);
_CurrentRuneLocale = rl;
__mb_cur_max = new__mb_cur_max;
return (0);
}

View File

@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include "ldpart.h"
static int split_lines(char *, const char *);
static void set_from_buf(const char *, int, const char **);
int
__part_load_locale(const char *name,
@ -53,35 +52,25 @@ __part_load_locale(const char *name,
int locale_buf_size_min,
const char **dst_localebuf)
{
static char locale_buf_C[] = "C";
static int num_lines;
int saverr;
int fd;
char *lbuf;
char *p;
const char *plim;
char filename[PATH_MAX];
int saverr, fd, i, num_lines;
char *lbuf, *p;
const char *plim;
char filename[PATH_MAX];
struct stat st;
size_t namesize;
size_t bufsize;
int save_using_locale;
save_using_locale = *using_locale;
*using_locale = 0;
size_t namesize, bufsize;
/* 'name' must be already checked. */
if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
return 0;
if (strcmp(name, "C") == 0 || strcmp(name, "POSIX") == 0) {
*using_locale = 0;
return (_LDP_CACHE);
}
/*
* If the locale name is the same as our cache, use the cache.
*/
lbuf = locale_buf;
if (lbuf != NULL && strcmp(name, lbuf) == 0) {
set_from_buf(lbuf, num_lines, dst_localebuf);
if (locale_buf != NULL && strcmp(name, locale_buf) == 0) {
*using_locale = 1;
return 0;
return (_LDP_CACHE);
}
/*
@ -90,16 +79,14 @@ __part_load_locale(const char *name,
namesize = strlen(name) + 1;
/* 'PathLocale' must be already set & checked. */
/* Range checking not needed, 'name' size is limited */
strcpy(filename, _PathLocale);
strcat(filename, "/");
strcat(filename, name);
strcat(filename, "/");
strcat(filename, category_filename);
fd = _open(filename, O_RDONLY);
if (fd < 0)
goto no_locale;
if ((fd = _open(filename, O_RDONLY)) < 0)
return (_LDP_ERROR);
if (_fstat(fd, &st) != 0)
goto bad_locale;
if (st.st_size <= 0) {
@ -107,18 +94,15 @@ __part_load_locale(const char *name,
goto bad_locale;
}
bufsize = namesize + st.st_size;
locale_buf = NULL;
lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
malloc(bufsize) : reallocf(lbuf, bufsize);
if (lbuf == NULL)
if ((lbuf = malloc(bufsize)) == NULL) {
errno = ENOMEM;
goto bad_locale;
}
(void)strcpy(lbuf, name);
p = lbuf + namesize;
plim = p + st.st_size;
if (_read(fd, p, (size_t) st.st_size) != st.st_size)
goto bad_lbuf;
if (_close(fd) != 0)
goto bad_lbuf;
/*
* Parse the locale file into localebuf.
*/
@ -133,37 +117,37 @@ __part_load_locale(const char *name,
num_lines = locale_buf_size_min;
else {
errno = EFTYPE;
goto reset_locale;
goto bad_lbuf;
}
set_from_buf(lbuf, num_lines, dst_localebuf);
(void)_close(fd);
/*
* Record the successful parse in the cache.
*/
if (locale_buf != NULL)
free(locale_buf);
locale_buf = lbuf;
for (p = locale_buf, i = 0; i < num_lines; i++)
dst_localebuf[i] = (p += strlen(p) + 1);
for (i = num_lines; i < locale_buf_size_max; i++)
dst_localebuf[i] = NULL;
*using_locale = 1;
return 0;
return (_LDP_LOADED);
reset_locale:
locale_buf = locale_buf_C;
save_using_locale = 0;
bad_lbuf:
saverr = errno;
free(lbuf);
saverr = errno;
free(lbuf);
errno = saverr;
bad_locale:
saverr = errno;
(void)_close(fd);
saverr = errno;
(void)_close(fd);
errno = saverr;
no_locale:
*using_locale = save_using_locale;
return -1;
return (_LDP_ERROR);
}
static int
split_lines(char *p, const char *plim)
split_lines(char *p, const char *plim)
{
int i;
@ -174,13 +158,3 @@ split_lines(char *p, const char *plim)
return (i);
}
static void
set_from_buf(const char *p, int num_lines, const char **dst_localebuf) {
const char **ap;
int i;
for (ap = dst_localebuf, i = 0; i < num_lines; ++ap, ++i)
*ap = p += strlen(p) + 1;
}

View File

@ -29,6 +29,10 @@
#ifndef _LDPART_H_
#define _LDPART_H_
#define _LDP_LOADED 0
#define _LDP_ERROR (-1)
#define _LDP_CACHE 1
int __part_load_locale(const char *, int*, char *, const char *,
int, int, const char **);

View File

@ -52,18 +52,19 @@ static char *_messages_locale_buf;
int
__messages_load_locale(const char *name)
{
/*
* Propose that we can have incomplete locale file (w/o "{yes,no}str").
* Initialize them before loading. In case of complete locale, they'll
* be initialized to loaded value, otherwise they'll not be touched.
*/
_messages_locale.yesstr = empty;
_messages_locale.nostr = empty;
int ret;
return __part_load_locale(name, &_messages_using_locale,
_messages_locale_buf, "LC_MESSAGES",
LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN,
(const char **)&_messages_locale);
ret = __part_load_locale(name, &_messages_using_locale,
_messages_locale_buf, "LC_MESSAGES",
LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN,
(const char **)&_messages_locale);
if (ret == _LDP_LOADED) {
if (_messages_locale.yesstr == NULL)
_messages_locale.yesstr = empty;
if (_messages_locale.nostr == NULL)
_messages_locale.nostr = empty;
}
return (ret);
}
struct lc_messages_T *

View File

@ -63,7 +63,7 @@ static int _monetary_using_locale;
static char *_monetary_locale_buf;
static char
cnv(const char *str)
cnv(const char *str)
{
int i = strtol(str, NULL, 10);
@ -77,12 +77,13 @@ __monetary_load_locale(const char *name)
{
int ret;
__mlocale_changed = 1;
ret = __part_load_locale(name, &_monetary_using_locale,
_monetary_locale_buf, "LC_MONETARY",
LCMONETARY_SIZE, LCMONETARY_SIZE,
(const char **)&_monetary_locale);
if (ret == 0 && _monetary_using_locale) {
if (ret != _LDP_ERROR)
__mlocale_changed = 1;
if (ret == _LDP_LOADED) {
_monetary_locale.mon_grouping =
__fix_locale_grouping_str(_monetary_locale.mon_grouping);
@ -102,7 +103,7 @@ __monetary_load_locale(const char *name)
}
struct lc_monetary_T *
__get_current_monetary_locale(void)
__get_current_monetary_locale(void)
{
return (_monetary_using_locale
? &_monetary_locale

View File

@ -53,14 +53,15 @@ __numeric_load_locale(const char *name)
{
int ret;
__nlocale_changed = 1;
ret = __part_load_locale(name, &_numeric_using_locale,
_numeric_locale_buf, "LC_NUMERIC",
LCNUMERIC_SIZE, LCNUMERIC_SIZE,
(const char **)&_numeric_locale);
if (ret == 0 && _numeric_using_locale)
if (ret != _LDP_ERROR)
__nlocale_changed = 1;
if (ret == _LDP_LOADED)
_numeric_locale.grouping =
__fix_locale_grouping_str(_numeric_locale.grouping);
__fix_locale_grouping_str(_numeric_locale.grouping);
return (ret);
}

View File

@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include "namespace.h"
#include <arpa/inet.h>
#include <errno.h>
#include <rune.h>
#include <stdio.h>
#include <string.h>
@ -59,22 +60,35 @@ _Read_RuneMagi(fp)
_RuneLocale *rl;
_RuneEntry *rr;
struct stat sb;
int x;
int x, saverr;
if (_fstat(fileno(fp), &sb) < 0)
return(0);
return (NULL);
if (sb.st_size < sizeof(_RuneLocale))
return(0);
if (sb.st_size < sizeof(_RuneLocale)) {
errno = EFTYPE;
return (NULL);
}
if ((data = malloc(sb.st_size)) == NULL)
return(0);
if ((data = malloc(sb.st_size)) == NULL) {
errno = ENOMEM;
return (NULL);
}
errno = 0;
rewind(fp); /* Someone might have read the magic number once already */
if (errno) {
saverr = errno;
free(data);
errno = saverr;
return (NULL);
}
if (fread(data, sb.st_size, 1, fp) != 1) {
saverr = errno;
free(data);
return(0);
errno = saverr;
return (NULL);
}
rl = (_RuneLocale *)data;
@ -84,7 +98,8 @@ _Read_RuneMagi(fp)
if (memcmp(rl->magic, _RUNE_MAGIC_1, sizeof(rl->magic))) {
free(data);
return(0);
errno = EFTYPE;
return (NULL);
}
rl->invalid_rune = ntohl(rl->invalid_rune);
@ -103,21 +118,24 @@ _Read_RuneMagi(fp)
rl->variable = rl->runetype_ext.ranges + rl->runetype_ext.nranges;
if (rl->variable > lastp) {
free(data);
return(0);
errno = EFTYPE;
return (NULL);
}
rl->maplower_ext.ranges = (_RuneEntry *)rl->variable;
rl->variable = rl->maplower_ext.ranges + rl->maplower_ext.nranges;
if (rl->variable > lastp) {
free(data);
return(0);
errno = EFTYPE;
return (NULL);
}
rl->mapupper_ext.ranges = (_RuneEntry *)rl->variable;
rl->variable = rl->mapupper_ext.ranges + rl->mapupper_ext.nranges;
if (rl->variable > lastp) {
free(data);
return(0);
errno = EFTYPE;
return (NULL);
}
for (x = 0; x < rl->runetype_ext.nranges; ++x) {
@ -131,7 +149,8 @@ _Read_RuneMagi(fp)
rl->variable = rr[x].types + len;
if (rl->variable > lastp) {
free(data);
return(0);
errno = EFTYPE;
return (NULL);
}
while (len-- > 0)
rr[x].types[len] = ntohl(rr[x].types[len]);
@ -156,7 +175,8 @@ _Read_RuneMagi(fp)
}
if (((char *)rl->variable) + rl->variable_len > (char *)lastp) {
free(data);
return(0);
errno = EFTYPE;
return (NULL);
}
/*
@ -174,5 +194,5 @@ _Read_RuneMagi(fp)
if (!rl->mapupper_ext.nranges)
rl->mapupper_ext.ranges = 0;
return(rl);
return (rl);
}

View File

@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include "lnumeric.h" /* for __numeric_load_locale() */
#include "lmessages.h" /* for __messages_load_locale() */
#include "setlocale.h"
#include "ldpart.h"
#include "../stdtime/timelocal.h" /* for __time_load_locale() */
/*
@ -92,7 +93,7 @@ static char saved_categories[_LC_LAST][ENCODING_LEN + 1];
static char current_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)];
static char *currentlocale(void);
static int wrap_setrunelocale(char *);
static int wrap_setrunelocale(const char *);
static char *loadlocale(int);
char *
@ -206,7 +207,10 @@ setlocale(category, locale)
for (j = 1; j < i; j++) {
(void)strcpy(new_categories[j],
saved_categories[j]);
(void)loadlocale(j);
if (loadlocale(j) == NULL) {
(void)strcpy(new_categories[j], "C");
(void)loadlocale(j);
}
}
errno = saverr;
return (NULL);
@ -235,27 +239,24 @@ currentlocale()
}
static int
wrap_setrunelocale(locale)
char *locale;
wrap_setrunelocale(const char *locale)
{
int ret = setrunelocale(locale);
int ret = setrunelocale((char *)locale);
if (ret != 0) {
errno = ret;
return (-1);
return (_LDP_ERROR);
}
return (0);
return (_LDP_LOADED);
}
static char *
loadlocale(category)
int category;
{
char *ret;
char *new = new_categories[category];
char *old = current_categories[category];
int (*func)();
int saverr;
int (*func)(const char *);
if ((new[0] == '.' &&
(new[1] == '\0' || (new[1] == '.' && new[2] == '\0'))) ||
@ -278,8 +279,10 @@ loadlocale(category)
return (NULL);
}
_PathLocale = strdup(p);
if (_PathLocale == NULL)
if (_PathLocale == NULL) {
errno = ENOMEM;
return (NULL);
}
} else
_PathLocale = _PATH_LOCALE;
}
@ -311,15 +314,11 @@ loadlocale(category)
if (strcmp(new, old) == 0)
return (old);
ret = func(new) != 0 ? NULL : new;
if (ret == NULL) {
saverr = errno;
if (func(old) != 0 && func("C") == 0)
(void)strcpy(old, "C");
errno = saverr;
} else
if (func(new) != _LDP_ERROR) {
(void)strcpy(old, new);
return (old);
}
return (ret);
return (NULL);
}

View File

@ -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);
}