免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1324 | 回复: 0
打印 上一主题 下一主题

装载LC_CTYPE初探 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-01-23 14:16 |只看该作者 |倒序浏览
在系统装载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
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP