- 论坛徽章:
- 0
|
在系统装载locale的时候,通过阅读源代码,得知mbwc的转换初始化大都在装载LC_CTYPE上,总结流程:
系统装载locale设置的时候,首先会找locale的目录,然后对系统locale环境设置进行检测,之后设置系统地locale,对每个种类的locale进行装载,在装载LC_CTYPE的时候,根据LC_CTYPE的值来进行mbwc的初始化配置:-)
主要的代码实现在 /usr/src/lib/libc/locale/setrunelocale.c 中的setrunelocale()函数中:
static int __setrunelocale(const char *encoding)
{
FILE *fp; //用于打开LC_CTYPE文件
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;
static size_t (*Cached__mbrtowc)(wchar_t * __restrict,
const char * __restrict, size_t, mbstate_t * __restrict);
static size_t (*Cached__wcrtomb)(char * __restrict, wchar_t,
mbstate_t * __restrict);
static int (*Cached__mbsinit)(const mbstate_t *);
static size_t (*Cached__mbsnrtowcs)(wchar_t * __restrict,
const char ** __restrict, size_t, size_t, mbstate_t * __restrict);
static size_t (*Cached__wcsnrtombs)(char * __restrict,
const wchar_t ** __restrict, size_t, size_t,
mbstate_t * __restrict);
/*
* The "C" and "POSIX" locale are always here.
*/
if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
_none_init(&_DefaultRuneLocale);
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;
__mbrtowc = Cached__mbrtowc;
__mbsinit = Cached__mbsinit;
__mbsnrtowcs = Cached__mbsnrtowcs;
__wcrtomb = Cached__wcrtomb;
__wcsnrtombs = Cached__wcsnrtombs;
return (0);
}
__mbrtowc,__mbsinit,__mbsnrtowcs,__wcrtomb,__wcsnrtombs都是函数指针,可以根据locale的不同,指向不同语言区域的处理函数
/*
* Slurp the locale file into the cache.
*/
/* Range checking not needed, encoding length already checked before */
(void) strcpy(name, _PathLocale);
(void) strcat(name, "/");
(void) strcat(name, encoding);
(void) strcat(name, "/LC_CTYPE");
加工name,保存LC_CTYPE文件的具体路径
if ((fp = fopen(name, "r")) == NULL)
return (errno == 0 ? ENOENT : errno);
文件打不开,报错!
if ((rl = _Read_RuneMagi(fp)) == NULL) {
saverr = (errno == 0 ? EFTYPE : errno);
(void)fclose(fp);
return (saverr);
}
(void)fclose(fp);
__mbrtowc = NULL;
__mbsinit = NULL;
__mbsnrtowcs = __mbsnrtowcs_std;
__wcrtomb = NULL;
__wcsnrtombs = __wcsnrtombs_std;
rl->__sputrune = NULL;
rl->__sgetrune = NULL;
以上是一些初始化的处理,主要的作用就是检测LC_CTYPE,如果没有发现需要的信息,或者是Null,进行默认的处理
if (strcmp(rl->__encoding, "NONE") == 0)
ret = _none_init(rl);
else if (strcmp(rl->__encoding, "UTF-8") == 0)
ret = _UTF8_init(rl);
else if (strcmp(rl->__encoding, "EUC") == 0)
ret = _EUC_init(rl);
else if (strcmp(rl->__encoding, "GB18030") == 0)
ret = _GB18030_init(rl);
else if (strcmp(rl->__encoding, "GB2312") == 0)
ret = _GB2312_init(rl);
else if (strcmp(rl->__encoding, "GBK") == 0)
ret = _GBK_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
ret = EFTYPE;
以上代码就是相关的入口!以_GB18030_init(rl)为例,进入同目录下的GB18030.c文件中,有如下代码:
int _GB18030_init(_RuneLocale *rl)
{
__mbrtowc = _GB18030_mbrtowc;
__wcrtomb = _GB18030_wcrtomb;
__mbsinit = _GB18030_mbsinit;
_CurrentRuneLocale = rl;
__mb_cur_max = 4;
return (0);
}
接下来,分别定义了函数中出现的几个GB18030的处理函数,以提供相应的处理!
由此可见,nls中的判断代码集,切换不同的处理函数就是由以上机制实现的!
在装载LC_CTYPE中,读取对应locale的LC_CTYPE文件中的代码集成员,然后根据代码集给相应的函数指针指向相应的转换函数啊,以实现系统中宽字节和多字节的转换,而实现本地化!
下面代码略!
在上面的代码中涉及到一个数据结构,在 /usr/src/lib/libc/locale/runetype.h中
typedef struct {
char __magic[8]; /* Magic saying what version we are */
char __encoding[32]; /* ASCII name of this encoding */
__rune_t (*__sgetrune)(const char *, __size_t, char const **);
int (*__sputrune)(__rune_t, char *, __size_t, char **);
__rune_t __invalid_rune;
unsigned long __runetype[_CACHED_RUNES];
__rune_t __maplower[_CACHED_RUNES];
__rune_t __mapupper[_CACHED_RUNES];
/*
* The following are to deal with Runes larger than _CACHED_RUNES - 1.
* Their data is actually contiguous with this structure so as to make
* it easier to read/write from/to disk.
*/
_RuneRange __runetype_ext;
_RuneRange __maplower_ext;
_RuneRange __mapupper_ext;
void *__variable; /* Data which depends on the encoding */
int __variable_len; /* how long that data is */
} _RuneLocale;
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/12258/showart_70052.html |
|