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:
parent
af8c0bce98
commit
76692b8025
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=101498
@ -40,68 +40,115 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "collate.h"
|
#include "collate.h"
|
||||||
#include "setlocale.h"
|
#include "setlocale.h"
|
||||||
|
#include "ldpart.h"
|
||||||
|
|
||||||
#include "libc_private.h"
|
#include "libc_private.h"
|
||||||
|
|
||||||
int __collate_load_error = 1;
|
int __collate_load_error = 1;
|
||||||
int __collate_substitute_nontrivial;
|
int __collate_substitute_nontrivial;
|
||||||
char __collate_version[STR_LEN];
|
|
||||||
u_char __collate_substitute_table[UCHAR_MAX + 1][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_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[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;
|
void __collate_err(int ex, const char *f) __dead2;
|
||||||
|
|
||||||
int
|
int
|
||||||
__collate_load_tables(encoding)
|
__collate_load_tables(const char *encoding)
|
||||||
char *encoding;
|
|
||||||
{
|
{
|
||||||
char buf[PATH_MAX];
|
|
||||||
FILE *fp;
|
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;
|
/* 'encoding' must be already checked. */
|
||||||
__collate_load_error = 1;
|
if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
|
||||||
if (!encoding) {
|
__collate_load_error = 1;
|
||||||
__collate_load_error = save_load_error;
|
return (_LDP_CACHE);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX"))
|
|
||||||
return 0;
|
/*
|
||||||
if (!_PathLocale) {
|
* If the locale name is the same as our cache, use the cache.
|
||||||
__collate_load_error = save_load_error;
|
*/
|
||||||
return -1;
|
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 */
|
/* Range checking not needed, encoding has fixed size */
|
||||||
(void)strcpy(buf, _PathLocale);
|
(void)strcpy(buf, _PathLocale);
|
||||||
(void)strcat(buf, "/");
|
(void)strcat(buf, "/");
|
||||||
(void)strcat(buf, encoding);
|
(void)strcat(buf, encoding);
|
||||||
(void)strcat(buf, "/LC_COLLATE");
|
(void)strcat(buf, "/LC_COLLATE");
|
||||||
if ((fp = fopen(buf, "r")) == NULL) {
|
if ((fp = fopen(buf, "r")) == NULL)
|
||||||
__collate_load_error = save_load_error;
|
return (_LDP_ERROR);
|
||||||
return -1;
|
|
||||||
}
|
if ((TMP_substitute_table =
|
||||||
FREAD(__collate_version, sizeof(__collate_version), 1, fp);
|
malloc(sizeof(__collate_substitute_table))) == NULL) {
|
||||||
if (strcmp(__collate_version, COLLATE_VERSION) != 0) {
|
|
||||||
(void)fclose(fp);
|
(void)fclose(fp);
|
||||||
return -1;
|
errno = ENOMEM;
|
||||||
|
return (_LDP_ERROR);
|
||||||
}
|
}
|
||||||
FREAD(__collate_substitute_table, sizeof(__collate_substitute_table),
|
if ((TMP_char_pri_table =
|
||||||
1, fp);
|
malloc(sizeof(__collate_char_pri_table))) == NULL) {
|
||||||
FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1,
|
free(TMP_substitute_table);
|
||||||
fp);
|
(void)fclose(fp);
|
||||||
FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1,
|
errno = ENOMEM;
|
||||||
fp);
|
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);
|
(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;
|
__collate_substitute_nontrivial = 0;
|
||||||
for (i = 0; i < UCHAR_MAX + 1; i++) {
|
for (i = 0; i < UCHAR_MAX + 1; i++) {
|
||||||
@ -111,8 +158,9 @@ __collate_load_tables(encoding)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
__collate_load_error = 0;
|
||||||
|
|
||||||
return 0;
|
return (_LDP_LOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
u_char *
|
u_char *
|
||||||
@ -152,8 +200,8 @@ __collate_lookup(t, len, prim, sec)
|
|||||||
|
|
||||||
*len = 1;
|
*len = 1;
|
||||||
*prim = *sec = 0;
|
*prim = *sec = 0;
|
||||||
for(p2 = __collate_chain_pri_table; p2->str[0]; p2++) {
|
for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) {
|
||||||
if(strncmp(t, p2->str, strlen(p2->str)) == 0) {
|
if (strncmp(t, p2->str, strlen(p2->str)) == 0) {
|
||||||
*len = strlen(p2->str);
|
*len = strlen(p2->str);
|
||||||
*prim = p2->prim;
|
*prim = p2->prim;
|
||||||
*sec = p2->sec;
|
*sec = p2->sec;
|
||||||
|
@ -48,7 +48,6 @@ struct __collate_st_chain_pri {
|
|||||||
|
|
||||||
extern int __collate_load_error;
|
extern int __collate_load_error;
|
||||||
extern int __collate_substitute_nontrivial;
|
extern int __collate_substitute_nontrivial;
|
||||||
extern char __collate_version[STR_LEN];
|
|
||||||
extern u_char __collate_substitute_table[UCHAR_MAX + 1][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_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
|
||||||
extern struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
|
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
|
__BEGIN_DECLS
|
||||||
u_char *__collate_strdup(u_char *);
|
u_char *__collate_strdup(u_char *);
|
||||||
u_char *__collate_substitute(const 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 *);
|
void __collate_lookup(const u_char *, int *, int *, int *);
|
||||||
int __collate_range_cmp(int, int);
|
int __collate_range_cmp(int, int);
|
||||||
#ifdef COLLATE_DEBUG
|
#ifdef COLLATE_DEBUG
|
||||||
|
@ -63,40 +63,36 @@ _EUC_init(rl)
|
|||||||
_RuneLocale *rl;
|
_RuneLocale *rl;
|
||||||
{
|
{
|
||||||
_EucInfo *ei;
|
_EucInfo *ei;
|
||||||
int x;
|
int x, new__mb_cur_max;
|
||||||
char *v, *e;
|
char *v, *e;
|
||||||
|
|
||||||
rl->sgetrune = _EUC_sgetrune;
|
rl->sgetrune = _EUC_sgetrune;
|
||||||
rl->sputrune = _EUC_sputrune;
|
rl->sputrune = _EUC_sputrune;
|
||||||
|
|
||||||
if (!rl->variable) {
|
if (rl->variable == NULL)
|
||||||
free(rl);
|
|
||||||
return (EFTYPE);
|
return (EFTYPE);
|
||||||
}
|
|
||||||
v = (char *) rl->variable;
|
v = (char *)rl->variable;
|
||||||
|
|
||||||
while (*v == ' ' || *v == '\t')
|
while (*v == ' ' || *v == '\t')
|
||||||
++v;
|
++v;
|
||||||
|
|
||||||
if ((ei = malloc(sizeof(_EucInfo))) == NULL) {
|
if ((ei = malloc(sizeof(_EucInfo))) == NULL)
|
||||||
free(rl);
|
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
}
|
|
||||||
__mb_cur_max = 0;
|
new__mb_cur_max = 0;
|
||||||
for (x = 0; x < 4; ++x) {
|
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)) {
|
if (v == e || !(v = e)) {
|
||||||
free(rl);
|
|
||||||
free(ei);
|
free(ei);
|
||||||
return (EFTYPE);
|
return (EFTYPE);
|
||||||
}
|
}
|
||||||
if (__mb_cur_max < ei->count[x])
|
if (new__mb_cur_max < ei->count[x])
|
||||||
__mb_cur_max = ei->count[x];
|
new__mb_cur_max = ei->count[x];
|
||||||
while (*v == ' ' || *v == '\t')
|
while (*v == ' ' || *v == '\t')
|
||||||
++v;
|
++v;
|
||||||
ei->bits[x] = (int) strtol(v, &e, 0);
|
ei->bits[x] = (int)strtol(v, &e, 0);
|
||||||
if (v == e || !(v = e)) {
|
if (v == e || !(v = e)) {
|
||||||
free(rl);
|
|
||||||
free(ei);
|
free(ei);
|
||||||
return (EFTYPE);
|
return (EFTYPE);
|
||||||
}
|
}
|
||||||
@ -105,18 +101,13 @@ _EUC_init(rl)
|
|||||||
}
|
}
|
||||||
ei->mask = (int)strtol(v, &e, 0);
|
ei->mask = (int)strtol(v, &e, 0);
|
||||||
if (v == e || !(v = e)) {
|
if (v == e || !(v = e)) {
|
||||||
free(rl);
|
|
||||||
free(ei);
|
free(ei);
|
||||||
return (EFTYPE);
|
return (EFTYPE);
|
||||||
}
|
}
|
||||||
if (sizeof(_EucInfo) <= rl->variable_len) {
|
rl->variable = ei;
|
||||||
memcpy(rl->variable, ei, sizeof(_EucInfo));
|
|
||||||
free(ei);
|
|
||||||
} else {
|
|
||||||
rl->variable = ei;
|
|
||||||
}
|
|
||||||
rl->variable_len = sizeof(_EucInfo);
|
rl->variable_len = sizeof(_EucInfo);
|
||||||
_CurrentRuneLocale = rl;
|
_CurrentRuneLocale = rl;
|
||||||
|
__mb_cur_max = new__mb_cur_max;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include "ldpart.h"
|
#include "ldpart.h"
|
||||||
|
|
||||||
static int split_lines(char *, const char *);
|
static int split_lines(char *, const char *);
|
||||||
static void set_from_buf(const char *, int, const char **);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
__part_load_locale(const char *name,
|
__part_load_locale(const char *name,
|
||||||
@ -53,35 +52,25 @@ __part_load_locale(const char *name,
|
|||||||
int locale_buf_size_min,
|
int locale_buf_size_min,
|
||||||
const char **dst_localebuf)
|
const char **dst_localebuf)
|
||||||
{
|
{
|
||||||
static char locale_buf_C[] = "C";
|
int saverr, fd, i, num_lines;
|
||||||
static int num_lines;
|
char *lbuf, *p;
|
||||||
int saverr;
|
const char *plim;
|
||||||
int fd;
|
char filename[PATH_MAX];
|
||||||
char *lbuf;
|
|
||||||
char *p;
|
|
||||||
const char *plim;
|
|
||||||
char filename[PATH_MAX];
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
size_t namesize;
|
size_t namesize, bufsize;
|
||||||
size_t bufsize;
|
|
||||||
int save_using_locale;
|
|
||||||
|
|
||||||
save_using_locale = *using_locale;
|
|
||||||
*using_locale = 0;
|
|
||||||
|
|
||||||
/* 'name' must be already checked. */
|
/* 'name' must be already checked. */
|
||||||
|
if (strcmp(name, "C") == 0 || strcmp(name, "POSIX") == 0) {
|
||||||
if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
|
*using_locale = 0;
|
||||||
return 0;
|
return (_LDP_CACHE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the locale name is the same as our cache, use the cache.
|
* If the locale name is the same as our cache, use the cache.
|
||||||
*/
|
*/
|
||||||
lbuf = locale_buf;
|
if (locale_buf != NULL && strcmp(name, locale_buf) == 0) {
|
||||||
if (lbuf != NULL && strcmp(name, lbuf) == 0) {
|
|
||||||
set_from_buf(lbuf, num_lines, dst_localebuf);
|
|
||||||
*using_locale = 1;
|
*using_locale = 1;
|
||||||
return 0;
|
return (_LDP_CACHE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -90,16 +79,14 @@ __part_load_locale(const char *name,
|
|||||||
namesize = strlen(name) + 1;
|
namesize = strlen(name) + 1;
|
||||||
|
|
||||||
/* 'PathLocale' must be already set & checked. */
|
/* 'PathLocale' must be already set & checked. */
|
||||||
|
|
||||||
/* Range checking not needed, 'name' size is limited */
|
/* Range checking not needed, 'name' size is limited */
|
||||||
strcpy(filename, _PathLocale);
|
strcpy(filename, _PathLocale);
|
||||||
strcat(filename, "/");
|
strcat(filename, "/");
|
||||||
strcat(filename, name);
|
strcat(filename, name);
|
||||||
strcat(filename, "/");
|
strcat(filename, "/");
|
||||||
strcat(filename, category_filename);
|
strcat(filename, category_filename);
|
||||||
fd = _open(filename, O_RDONLY);
|
if ((fd = _open(filename, O_RDONLY)) < 0)
|
||||||
if (fd < 0)
|
return (_LDP_ERROR);
|
||||||
goto no_locale;
|
|
||||||
if (_fstat(fd, &st) != 0)
|
if (_fstat(fd, &st) != 0)
|
||||||
goto bad_locale;
|
goto bad_locale;
|
||||||
if (st.st_size <= 0) {
|
if (st.st_size <= 0) {
|
||||||
@ -107,18 +94,15 @@ __part_load_locale(const char *name,
|
|||||||
goto bad_locale;
|
goto bad_locale;
|
||||||
}
|
}
|
||||||
bufsize = namesize + st.st_size;
|
bufsize = namesize + st.st_size;
|
||||||
locale_buf = NULL;
|
if ((lbuf = malloc(bufsize)) == NULL) {
|
||||||
lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
|
errno = ENOMEM;
|
||||||
malloc(bufsize) : reallocf(lbuf, bufsize);
|
|
||||||
if (lbuf == NULL)
|
|
||||||
goto bad_locale;
|
goto bad_locale;
|
||||||
|
}
|
||||||
(void)strcpy(lbuf, name);
|
(void)strcpy(lbuf, name);
|
||||||
p = lbuf + namesize;
|
p = lbuf + namesize;
|
||||||
plim = p + st.st_size;
|
plim = p + st.st_size;
|
||||||
if (_read(fd, p, (size_t) st.st_size) != st.st_size)
|
if (_read(fd, p, (size_t) st.st_size) != st.st_size)
|
||||||
goto bad_lbuf;
|
goto bad_lbuf;
|
||||||
if (_close(fd) != 0)
|
|
||||||
goto bad_lbuf;
|
|
||||||
/*
|
/*
|
||||||
* Parse the locale file into localebuf.
|
* Parse the locale file into localebuf.
|
||||||
*/
|
*/
|
||||||
@ -133,37 +117,37 @@ __part_load_locale(const char *name,
|
|||||||
num_lines = locale_buf_size_min;
|
num_lines = locale_buf_size_min;
|
||||||
else {
|
else {
|
||||||
errno = EFTYPE;
|
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.
|
* Record the successful parse in the cache.
|
||||||
*/
|
*/
|
||||||
|
if (locale_buf != NULL)
|
||||||
|
free(locale_buf);
|
||||||
locale_buf = lbuf;
|
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;
|
*using_locale = 1;
|
||||||
|
|
||||||
return 0;
|
return (_LDP_LOADED);
|
||||||
|
|
||||||
reset_locale:
|
|
||||||
locale_buf = locale_buf_C;
|
|
||||||
save_using_locale = 0;
|
|
||||||
bad_lbuf:
|
bad_lbuf:
|
||||||
saverr = errno;
|
saverr = errno;
|
||||||
free(lbuf);
|
free(lbuf);
|
||||||
errno = saverr;
|
errno = saverr;
|
||||||
bad_locale:
|
bad_locale:
|
||||||
saverr = errno;
|
saverr = errno;
|
||||||
(void)_close(fd);
|
(void)_close(fd);
|
||||||
errno = saverr;
|
errno = saverr;
|
||||||
no_locale:
|
|
||||||
*using_locale = save_using_locale;
|
|
||||||
|
|
||||||
return -1;
|
return (_LDP_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
split_lines(char *p, const char *plim)
|
split_lines(char *p, const char *plim)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -174,13 +158,3 @@ split_lines(char *p, const char *plim)
|
|||||||
return (i);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@
|
|||||||
#ifndef _LDPART_H_
|
#ifndef _LDPART_H_
|
||||||
#define _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 __part_load_locale(const char *, int*, char *, const char *,
|
||||||
int, int, const char **);
|
int, int, const char **);
|
||||||
|
|
||||||
|
@ -52,18 +52,19 @@ static char *_messages_locale_buf;
|
|||||||
int
|
int
|
||||||
__messages_load_locale(const char *name)
|
__messages_load_locale(const char *name)
|
||||||
{
|
{
|
||||||
/*
|
int ret;
|
||||||
* 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;
|
|
||||||
|
|
||||||
return __part_load_locale(name, &_messages_using_locale,
|
ret = __part_load_locale(name, &_messages_using_locale,
|
||||||
_messages_locale_buf, "LC_MESSAGES",
|
_messages_locale_buf, "LC_MESSAGES",
|
||||||
LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN,
|
LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN,
|
||||||
(const char **)&_messages_locale);
|
(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 *
|
struct lc_messages_T *
|
||||||
|
@ -63,7 +63,7 @@ static int _monetary_using_locale;
|
|||||||
static char *_monetary_locale_buf;
|
static char *_monetary_locale_buf;
|
||||||
|
|
||||||
static char
|
static char
|
||||||
cnv(const char *str)
|
cnv(const char *str)
|
||||||
{
|
{
|
||||||
int i = strtol(str, NULL, 10);
|
int i = strtol(str, NULL, 10);
|
||||||
|
|
||||||
@ -77,12 +77,13 @@ __monetary_load_locale(const char *name)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
__mlocale_changed = 1;
|
|
||||||
ret = __part_load_locale(name, &_monetary_using_locale,
|
ret = __part_load_locale(name, &_monetary_using_locale,
|
||||||
_monetary_locale_buf, "LC_MONETARY",
|
_monetary_locale_buf, "LC_MONETARY",
|
||||||
LCMONETARY_SIZE, LCMONETARY_SIZE,
|
LCMONETARY_SIZE, LCMONETARY_SIZE,
|
||||||
(const char **)&_monetary_locale);
|
(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 =
|
_monetary_locale.mon_grouping =
|
||||||
__fix_locale_grouping_str(_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 *
|
struct lc_monetary_T *
|
||||||
__get_current_monetary_locale(void)
|
__get_current_monetary_locale(void)
|
||||||
{
|
{
|
||||||
return (_monetary_using_locale
|
return (_monetary_using_locale
|
||||||
? &_monetary_locale
|
? &_monetary_locale
|
||||||
|
@ -53,14 +53,15 @@ __numeric_load_locale(const char *name)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
__nlocale_changed = 1;
|
|
||||||
ret = __part_load_locale(name, &_numeric_using_locale,
|
ret = __part_load_locale(name, &_numeric_using_locale,
|
||||||
_numeric_locale_buf, "LC_NUMERIC",
|
_numeric_locale_buf, "LC_NUMERIC",
|
||||||
LCNUMERIC_SIZE, LCNUMERIC_SIZE,
|
LCNUMERIC_SIZE, LCNUMERIC_SIZE,
|
||||||
(const char **)&_numeric_locale);
|
(const char **)&_numeric_locale);
|
||||||
if (ret == 0 && _numeric_using_locale)
|
if (ret != _LDP_ERROR)
|
||||||
|
__nlocale_changed = 1;
|
||||||
|
if (ret == _LDP_LOADED)
|
||||||
_numeric_locale.grouping =
|
_numeric_locale.grouping =
|
||||||
__fix_locale_grouping_str(_numeric_locale.grouping);
|
__fix_locale_grouping_str(_numeric_locale.grouping);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "namespace.h"
|
#include "namespace.h"
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <rune.h>
|
#include <rune.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -59,22 +60,35 @@ _Read_RuneMagi(fp)
|
|||||||
_RuneLocale *rl;
|
_RuneLocale *rl;
|
||||||
_RuneEntry *rr;
|
_RuneEntry *rr;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
int x;
|
int x, saverr;
|
||||||
|
|
||||||
if (_fstat(fileno(fp), &sb) < 0)
|
if (_fstat(fileno(fp), &sb) < 0)
|
||||||
return(0);
|
return (NULL);
|
||||||
|
|
||||||
if (sb.st_size < sizeof(_RuneLocale))
|
if (sb.st_size < sizeof(_RuneLocale)) {
|
||||||
return(0);
|
errno = EFTYPE;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if ((data = malloc(sb.st_size)) == NULL)
|
if ((data = malloc(sb.st_size)) == NULL) {
|
||||||
return(0);
|
errno = ENOMEM;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
rewind(fp); /* Someone might have read the magic number once already */
|
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) {
|
if (fread(data, sb.st_size, 1, fp) != 1) {
|
||||||
|
saverr = errno;
|
||||||
free(data);
|
free(data);
|
||||||
return(0);
|
errno = saverr;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
rl = (_RuneLocale *)data;
|
rl = (_RuneLocale *)data;
|
||||||
@ -84,7 +98,8 @@ _Read_RuneMagi(fp)
|
|||||||
|
|
||||||
if (memcmp(rl->magic, _RUNE_MAGIC_1, sizeof(rl->magic))) {
|
if (memcmp(rl->magic, _RUNE_MAGIC_1, sizeof(rl->magic))) {
|
||||||
free(data);
|
free(data);
|
||||||
return(0);
|
errno = EFTYPE;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
rl->invalid_rune = ntohl(rl->invalid_rune);
|
rl->invalid_rune = ntohl(rl->invalid_rune);
|
||||||
@ -103,21 +118,24 @@ _Read_RuneMagi(fp)
|
|||||||
rl->variable = rl->runetype_ext.ranges + rl->runetype_ext.nranges;
|
rl->variable = rl->runetype_ext.ranges + rl->runetype_ext.nranges;
|
||||||
if (rl->variable > lastp) {
|
if (rl->variable > lastp) {
|
||||||
free(data);
|
free(data);
|
||||||
return(0);
|
errno = EFTYPE;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
rl->maplower_ext.ranges = (_RuneEntry *)rl->variable;
|
rl->maplower_ext.ranges = (_RuneEntry *)rl->variable;
|
||||||
rl->variable = rl->maplower_ext.ranges + rl->maplower_ext.nranges;
|
rl->variable = rl->maplower_ext.ranges + rl->maplower_ext.nranges;
|
||||||
if (rl->variable > lastp) {
|
if (rl->variable > lastp) {
|
||||||
free(data);
|
free(data);
|
||||||
return(0);
|
errno = EFTYPE;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
rl->mapupper_ext.ranges = (_RuneEntry *)rl->variable;
|
rl->mapupper_ext.ranges = (_RuneEntry *)rl->variable;
|
||||||
rl->variable = rl->mapupper_ext.ranges + rl->mapupper_ext.nranges;
|
rl->variable = rl->mapupper_ext.ranges + rl->mapupper_ext.nranges;
|
||||||
if (rl->variable > lastp) {
|
if (rl->variable > lastp) {
|
||||||
free(data);
|
free(data);
|
||||||
return(0);
|
errno = EFTYPE;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x = 0; x < rl->runetype_ext.nranges; ++x) {
|
for (x = 0; x < rl->runetype_ext.nranges; ++x) {
|
||||||
@ -131,7 +149,8 @@ _Read_RuneMagi(fp)
|
|||||||
rl->variable = rr[x].types + len;
|
rl->variable = rr[x].types + len;
|
||||||
if (rl->variable > lastp) {
|
if (rl->variable > lastp) {
|
||||||
free(data);
|
free(data);
|
||||||
return(0);
|
errno = EFTYPE;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
while (len-- > 0)
|
while (len-- > 0)
|
||||||
rr[x].types[len] = ntohl(rr[x].types[len]);
|
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) {
|
if (((char *)rl->variable) + rl->variable_len > (char *)lastp) {
|
||||||
free(data);
|
free(data);
|
||||||
return(0);
|
errno = EFTYPE;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -174,5 +194,5 @@ _Read_RuneMagi(fp)
|
|||||||
if (!rl->mapupper_ext.nranges)
|
if (!rl->mapupper_ext.nranges)
|
||||||
rl->mapupper_ext.ranges = 0;
|
rl->mapupper_ext.ranges = 0;
|
||||||
|
|
||||||
return(rl);
|
return (rl);
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include "lnumeric.h" /* for __numeric_load_locale() */
|
#include "lnumeric.h" /* for __numeric_load_locale() */
|
||||||
#include "lmessages.h" /* for __messages_load_locale() */
|
#include "lmessages.h" /* for __messages_load_locale() */
|
||||||
#include "setlocale.h"
|
#include "setlocale.h"
|
||||||
|
#include "ldpart.h"
|
||||||
#include "../stdtime/timelocal.h" /* for __time_load_locale() */
|
#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 current_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)];
|
||||||
|
|
||||||
static char *currentlocale(void);
|
static char *currentlocale(void);
|
||||||
static int wrap_setrunelocale(char *);
|
static int wrap_setrunelocale(const char *);
|
||||||
static char *loadlocale(int);
|
static char *loadlocale(int);
|
||||||
|
|
||||||
char *
|
char *
|
||||||
@ -206,7 +207,10 @@ setlocale(category, locale)
|
|||||||
for (j = 1; j < i; j++) {
|
for (j = 1; j < i; j++) {
|
||||||
(void)strcpy(new_categories[j],
|
(void)strcpy(new_categories[j],
|
||||||
saved_categories[j]);
|
saved_categories[j]);
|
||||||
(void)loadlocale(j);
|
if (loadlocale(j) == NULL) {
|
||||||
|
(void)strcpy(new_categories[j], "C");
|
||||||
|
(void)loadlocale(j);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
errno = saverr;
|
errno = saverr;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -235,27 +239,24 @@ currentlocale()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wrap_setrunelocale(locale)
|
wrap_setrunelocale(const char *locale)
|
||||||
char *locale;
|
|
||||||
{
|
{
|
||||||
int ret = setrunelocale(locale);
|
int ret = setrunelocale((char *)locale);
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
errno = ret;
|
errno = ret;
|
||||||
return (-1);
|
return (_LDP_ERROR);
|
||||||
}
|
}
|
||||||
return (0);
|
return (_LDP_LOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
loadlocale(category)
|
loadlocale(category)
|
||||||
int category;
|
int category;
|
||||||
{
|
{
|
||||||
char *ret;
|
|
||||||
char *new = new_categories[category];
|
char *new = new_categories[category];
|
||||||
char *old = current_categories[category];
|
char *old = current_categories[category];
|
||||||
int (*func)();
|
int (*func)(const char *);
|
||||||
int saverr;
|
|
||||||
|
|
||||||
if ((new[0] == '.' &&
|
if ((new[0] == '.' &&
|
||||||
(new[1] == '\0' || (new[1] == '.' && new[2] == '\0'))) ||
|
(new[1] == '\0' || (new[1] == '.' && new[2] == '\0'))) ||
|
||||||
@ -278,8 +279,10 @@ loadlocale(category)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
_PathLocale = strdup(p);
|
_PathLocale = strdup(p);
|
||||||
if (_PathLocale == NULL)
|
if (_PathLocale == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
_PathLocale = _PATH_LOCALE;
|
_PathLocale = _PATH_LOCALE;
|
||||||
}
|
}
|
||||||
@ -311,15 +314,11 @@ loadlocale(category)
|
|||||||
if (strcmp(new, old) == 0)
|
if (strcmp(new, old) == 0)
|
||||||
return (old);
|
return (old);
|
||||||
|
|
||||||
ret = func(new) != 0 ? NULL : new;
|
if (func(new) != _LDP_ERROR) {
|
||||||
if (ret == NULL) {
|
|
||||||
saverr = errno;
|
|
||||||
if (func(old) != 0 && func("C") == 0)
|
|
||||||
(void)strcpy(old, "C");
|
|
||||||
errno = saverr;
|
|
||||||
} else
|
|
||||||
(void)strcpy(old, new);
|
(void)strcpy(old, new);
|
||||||
|
return (old);
|
||||||
|
}
|
||||||
|
|
||||||
return (ret);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,12 +54,15 @@ extern int _MSKanji_init(_RuneLocale *);
|
|||||||
extern _RuneLocale *_Read_RuneMagi(FILE *);
|
extern _RuneLocale *_Read_RuneMagi(FILE *);
|
||||||
|
|
||||||
int
|
int
|
||||||
setrunelocale(encoding)
|
setrunelocale(char *encoding)
|
||||||
char *encoding;
|
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char name[PATH_MAX];
|
char name[PATH_MAX];
|
||||||
_RuneLocale *rl;
|
_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 ||
|
if (!encoding || !*encoding || strlen(encoding) > ENCODING_LEN ||
|
||||||
(encoding[0] == '.' &&
|
(encoding[0] == '.' &&
|
||||||
@ -71,12 +74,25 @@ setrunelocale(encoding)
|
|||||||
/*
|
/*
|
||||||
* The "C" and "POSIX" locale are always here.
|
* 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;
|
_CurrentRuneLocale = &_DefaultRuneLocale;
|
||||||
__mb_cur_max = 1;
|
__mb_cur_max = 1;
|
||||||
return (0);
|
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) {
|
if (_PathLocale == NULL) {
|
||||||
char *p = getenv("PATH_LOCALE");
|
char *p = getenv("PATH_LOCALE");
|
||||||
|
|
||||||
@ -90,7 +106,7 @@ setrunelocale(encoding)
|
|||||||
return (ENAMETOOLONG);
|
return (ENAMETOOLONG);
|
||||||
_PathLocale = strdup(p);
|
_PathLocale = strdup(p);
|
||||||
if (_PathLocale == NULL)
|
if (_PathLocale == NULL)
|
||||||
return (errno);
|
return (ENOMEM);
|
||||||
} else
|
} else
|
||||||
_PathLocale = _PATH_LOCALE;
|
_PathLocale = _PATH_LOCALE;
|
||||||
}
|
}
|
||||||
@ -103,25 +119,38 @@ setrunelocale(encoding)
|
|||||||
if ((fp = fopen(name, "r")) == NULL)
|
if ((fp = fopen(name, "r")) == NULL)
|
||||||
return (errno);
|
return (errno);
|
||||||
|
|
||||||
if ((rl = _Read_RuneMagi(fp)) == 0) {
|
if ((rl = _Read_RuneMagi(fp)) == NULL) {
|
||||||
fclose(fp);
|
saverr = errno;
|
||||||
return (EFTYPE);
|
(void)fclose(fp);
|
||||||
|
return (saverr);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
(void)fclose(fp);
|
||||||
|
|
||||||
if (!rl->encoding[0])
|
if (strcmp(rl->encoding, "NONE") == 0)
|
||||||
return (EFTYPE);
|
ret = _none_init(rl);
|
||||||
else if (!strcmp(rl->encoding, "NONE"))
|
else if (strcmp(rl->encoding, "UTF2") == 0)
|
||||||
return (_none_init(rl));
|
ret = _UTF2_init(rl);
|
||||||
else if (!strcmp(rl->encoding, "UTF2"))
|
else if (strcmp(rl->encoding, "EUC") == 0)
|
||||||
return (_UTF2_init(rl));
|
ret = _EUC_init(rl);
|
||||||
else if (!strcmp(rl->encoding, "EUC"))
|
else if (strcmp(rl->encoding, "BIG5") == 0)
|
||||||
return (_EUC_init(rl));
|
ret = _BIG5_init(rl);
|
||||||
else if (!strcmp(rl->encoding, "BIG5"))
|
else if (strcmp(rl->encoding, "MSKanji") == 0)
|
||||||
return (_BIG5_init(rl));
|
ret = _MSKanji_init(rl);
|
||||||
else if (!strcmp(rl->encoding, "MSKanji"))
|
|
||||||
return (_MSKanji_init(rl));
|
|
||||||
else
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user