14297a3b0SGarrett D'Amore /*
2*2d08521bSGarrett D'Amore  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
39d04e500SGarrett D'Amore  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
44297a3b0SGarrett D'Amore  * Copyright (c) 1993
54297a3b0SGarrett D'Amore  *	The Regents of the University of California.  All rights reserved.
64297a3b0SGarrett D'Amore  *
74297a3b0SGarrett D'Amore  * This code is derived from software contributed to Berkeley by
84297a3b0SGarrett D'Amore  * Paul Borman at Krystal Technologies.
94297a3b0SGarrett D'Amore  *
104297a3b0SGarrett D'Amore  * Redistribution and use in source and binary forms, with or without
114297a3b0SGarrett D'Amore  * modification, are permitted provided that the following conditions
124297a3b0SGarrett D'Amore  * are met:
134297a3b0SGarrett D'Amore  * 1. Redistributions of source code must retain the above copyright
144297a3b0SGarrett D'Amore  *    notice, this list of conditions and the following disclaimer.
154297a3b0SGarrett D'Amore  * 2. Redistributions in binary form must reproduce the above copyright
164297a3b0SGarrett D'Amore  *    notice, this list of conditions and the following disclaimer in the
174297a3b0SGarrett D'Amore  *    documentation and/or other materials provided with the distribution.
184297a3b0SGarrett D'Amore  * 4. Neither the name of the University nor the names of its contributors
194297a3b0SGarrett D'Amore  *    may be used to endorse or promote products derived from this software
204297a3b0SGarrett D'Amore  *    without specific prior written permission.
214297a3b0SGarrett D'Amore  *
224297a3b0SGarrett D'Amore  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
234297a3b0SGarrett D'Amore  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
244297a3b0SGarrett D'Amore  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
254297a3b0SGarrett D'Amore  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
264297a3b0SGarrett D'Amore  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
274297a3b0SGarrett D'Amore  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
284297a3b0SGarrett D'Amore  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
294297a3b0SGarrett D'Amore  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
304297a3b0SGarrett D'Amore  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
314297a3b0SGarrett D'Amore  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
324297a3b0SGarrett D'Amore  * SUCH DAMAGE.
334297a3b0SGarrett D'Amore  */
344297a3b0SGarrett D'Amore 
354297a3b0SGarrett D'Amore #include "lint.h"
364297a3b0SGarrett D'Amore #include "file64.h"
374297a3b0SGarrett D'Amore #include <errno.h>
384297a3b0SGarrett D'Amore #include <limits.h>
394297a3b0SGarrett D'Amore #include <string.h>
404297a3b0SGarrett D'Amore #include <stdio.h>
414297a3b0SGarrett D'Amore #include <stdlib.h>
424297a3b0SGarrett D'Amore #include <unistd.h>
434297a3b0SGarrett D'Amore #include <wchar.h>
444297a3b0SGarrett D'Amore #include "runetype.h"
454297a3b0SGarrett D'Amore #include "ldpart.h"
464297a3b0SGarrett D'Amore #include "mblocal.h"
474297a3b0SGarrett D'Amore #include "setlocale.h"
484297a3b0SGarrett D'Amore #include "_ctype.h"
49*2d08521bSGarrett D'Amore #include "lctype.h"
50*2d08521bSGarrett D'Amore #include "localeimpl.h"
51*2d08521bSGarrett D'Amore 
52*2d08521bSGarrett D'Amore extern _RuneLocale	*_Read_RuneMagi(const char *);
53*2d08521bSGarrett D'Amore 
54*2d08521bSGarrett D'Amore struct lc_ctype lc_ctype_posix = {
55*2d08521bSGarrett D'Amore 	.lc_mbrtowc = __mbrtowc_ascii,
56*2d08521bSGarrett D'Amore 	.lc_mbsinit = __mbsinit_ascii,
57*2d08521bSGarrett D'Amore 	.lc_mbsnrtowcs = __mbsnrtowcs_ascii,
58*2d08521bSGarrett D'Amore 	.lc_wcrtomb = __wcrtomb_ascii,
59*2d08521bSGarrett D'Amore 	.lc_wcsnrtombs = __wcsnrtombs_ascii,
60*2d08521bSGarrett D'Amore 	.lc_is_ascii = 1,
61*2d08521bSGarrett D'Amore 	.lc_max_mblen = 1,
62*2d08521bSGarrett D'Amore 	.lc_trans_upper = _DefaultRuneLocale.__mapupper,
63*2d08521bSGarrett D'Amore 	.lc_trans_lower = _DefaultRuneLocale.__maplower,
64*2d08521bSGarrett D'Amore 	.lc_ctype_mask = _DefaultRuneLocale.__runetype,
65*2d08521bSGarrett D'Amore };
66*2d08521bSGarrett D'Amore 
67*2d08521bSGarrett D'Amore struct locdata __posix_ctype_locdata = {
68*2d08521bSGarrett D'Amore 	.l_lname = "C",
69*2d08521bSGarrett D'Amore 	.l_data = { &lc_ctype_posix, &_DefaultRuneLocale }
70*2d08521bSGarrett D'Amore };
714297a3b0SGarrett D'Amore 
724297a3b0SGarrett D'Amore 
73*2d08521bSGarrett D'Amore /*
74*2d08521bSGarrett D'Amore  * Table of initializers for encodings.  When you add a new encoding type,
75*2d08521bSGarrett D'Amore  * this table should be updated.
76*2d08521bSGarrett D'Amore  */
77*2d08521bSGarrett D'Amore static struct {
78*2d08521bSGarrett D'Amore 	const char *e_name;
79*2d08521bSGarrett D'Amore 	void (*e_init)(struct lc_ctype *);
80*2d08521bSGarrett D'Amore } encodings[] = {
81*2d08521bSGarrett D'Amore 	{ "NONE", _none_init },
82*2d08521bSGarrett D'Amore 	{ "UTF-8",	_UTF8_init },
83*2d08521bSGarrett D'Amore 	{ "EUC-CN",	_EUC_CN_init },
84*2d08521bSGarrett D'Amore 	{ "EUC-JP",	_EUC_JP_init },
85*2d08521bSGarrett D'Amore 	{ "EUC-KR",	_EUC_KR_init },
86*2d08521bSGarrett D'Amore 	{ "EUC-TW",	_EUC_TW_init },
87*2d08521bSGarrett D'Amore 	{ "GB18030",	_GB18030_init },
88*2d08521bSGarrett D'Amore 	{ "GB2312",	_GB2312_init },
89*2d08521bSGarrett D'Amore 	{ "GBK",	_GBK_init },
90*2d08521bSGarrett D'Amore 	{ "BIG5",	_BIG5_init },
91*2d08521bSGarrett D'Amore 	{ "MSKanji",	_MSKanji_init },
92*2d08521bSGarrett D'Amore 	{ NULL,		NULL }
93*2d08521bSGarrett D'Amore };
94*2d08521bSGarrett D'Amore 
95*2d08521bSGarrett D'Amore 
96*2d08521bSGarrett D'Amore struct locdata *
__lc_ctype_load(const char * name)97*2d08521bSGarrett D'Amore __lc_ctype_load(const char *name)
984297a3b0SGarrett D'Amore {
99*2d08521bSGarrett D'Amore 	struct locdata *ldata;
100*2d08521bSGarrett D'Amore 	struct lc_ctype *lct;
1014297a3b0SGarrett D'Amore 	_RuneLocale *rl;
102*2d08521bSGarrett D'Amore 	int i;
103*2d08521bSGarrett D'Amore 	char path[PATH_MAX];
1044297a3b0SGarrett D'Amore 
105*2d08521bSGarrett D'Amore 	if ((ldata = __locdata_alloc(name, sizeof (*lct))) == NULL)
106*2d08521bSGarrett D'Amore 		return (NULL);
107*2d08521bSGarrett D'Amore 	lct = ldata->l_data[0];
1084297a3b0SGarrett D'Amore 	/*
1094297a3b0SGarrett D'Amore 	 * Slurp the locale file into the cache.
1104297a3b0SGarrett D'Amore 	 */
1114297a3b0SGarrett D'Amore 
112*2d08521bSGarrett D'Amore 	(void) snprintf(path, sizeof (path), "%s/%s/LC_CTYPE/LCL_DATA",
113*2d08521bSGarrett D'Amore 	    _PathLocale, name);
1144297a3b0SGarrett D'Amore 
115*2d08521bSGarrett D'Amore 	if ((rl = _Read_RuneMagi(path)) == NULL) {
116*2d08521bSGarrett D'Amore 		__locdata_free(ldata);
117*2d08521bSGarrett D'Amore 		errno = EINVAL;
118*2d08521bSGarrett D'Amore 		return (NULL);
1194297a3b0SGarrett D'Amore 	}
120*2d08521bSGarrett D'Amore 	ldata->l_data[1] = rl;
121*2d08521bSGarrett D'Amore 
122*2d08521bSGarrett D'Amore 	lct->lc_mbrtowc = NULL;
123*2d08521bSGarrett D'Amore 	lct->lc_mbsinit = NULL;
124*2d08521bSGarrett D'Amore 	lct->lc_mbsnrtowcs = NULL;
125*2d08521bSGarrett D'Amore 	lct->lc_wcrtomb = NULL;
126*2d08521bSGarrett D'Amore 	lct->lc_wcsnrtombs = NULL;
127*2d08521bSGarrett D'Amore 	lct->lc_ctype_mask = rl->__runetype;
128*2d08521bSGarrett D'Amore 	lct->lc_trans_upper = rl->__mapupper;
129*2d08521bSGarrett D'Amore 	lct->lc_trans_lower = rl->__maplower;
130*2d08521bSGarrett D'Amore 
131*2d08521bSGarrett D'Amore 	/* set up the function pointers */
132*2d08521bSGarrett D'Amore 	for (i = 0; encodings[i].e_name != NULL; i++) {
133*2d08521bSGarrett D'Amore 		int l = strlen(encodings[i].e_name);
134*2d08521bSGarrett D'Amore 		if ((strncmp(rl->__encoding, encodings[i].e_name, l) == 0) &&
135*2d08521bSGarrett D'Amore 		    (rl->__encoding[l] == '\0' || rl->__encoding[l] == '@')) {
136*2d08521bSGarrett D'Amore 			encodings[i].e_init(lct);
137*2d08521bSGarrett D'Amore 			break;
1384297a3b0SGarrett D'Amore 		}
139*2d08521bSGarrett D'Amore 	}
140*2d08521bSGarrett D'Amore 	if (encodings[i].e_name == NULL) {
141*2d08521bSGarrett D'Amore 		__locdata_free(ldata);
142*2d08521bSGarrett D'Amore 		errno = EINVAL;
143*2d08521bSGarrett D'Amore 		return (NULL);
1444297a3b0SGarrett D'Amore 	}
1454297a3b0SGarrett D'Amore 
1464297a3b0SGarrett D'Amore 
147*2d08521bSGarrett D'Amore 	return (ldata);
1484297a3b0SGarrett D'Amore }
149