1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
19*b30d1939SAndy Fiddaman *                   Phong Vo <kpv@research.att.com>                    *
20*b30d1939SAndy Fiddaman *                                                                      *
21*b30d1939SAndy Fiddaman ***********************************************************************/
22*b30d1939SAndy Fiddaman /*
23*b30d1939SAndy Fiddaman  * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
24*b30d1939SAndy Fiddaman  */
25*b30d1939SAndy Fiddaman #pragma prototyped
26*b30d1939SAndy Fiddaman 
27*b30d1939SAndy Fiddaman /*
28*b30d1939SAndy Fiddaman  * setlocale() intercept
29*b30d1939SAndy Fiddaman  * maintains a bitmask of non-default categories
30*b30d1939SAndy Fiddaman  * and a permanent locale namespace for pointer comparison
31*b30d1939SAndy Fiddaman  * and persistent private data for locale related functions
32*b30d1939SAndy Fiddaman  */
33*b30d1939SAndy Fiddaman 
34*b30d1939SAndy Fiddaman #include <ast_standards.h>
35*b30d1939SAndy Fiddaman 
36*b30d1939SAndy Fiddaman #include "lclib.h"
37*b30d1939SAndy Fiddaman 
38*b30d1939SAndy Fiddaman #include <ast_wchar.h>
39*b30d1939SAndy Fiddaman #include <ctype.h>
40*b30d1939SAndy Fiddaman #include <mc.h>
41*b30d1939SAndy Fiddaman #include <namval.h>
42*b30d1939SAndy Fiddaman 
43*b30d1939SAndy Fiddaman #if ( _lib_wcwidth || _lib_wctomb ) && _hdr_wctype
44*b30d1939SAndy Fiddaman #include <wctype.h>
45*b30d1939SAndy Fiddaman #endif
46*b30d1939SAndy Fiddaman 
47*b30d1939SAndy Fiddaman #if _lib_wcwidth
48*b30d1939SAndy Fiddaman #undef	wcwidth
49*b30d1939SAndy Fiddaman #else
50*b30d1939SAndy Fiddaman #define wcwidth			0
51*b30d1939SAndy Fiddaman #endif
52*b30d1939SAndy Fiddaman 
53*b30d1939SAndy Fiddaman #if _lib_wctomb
54*b30d1939SAndy Fiddaman #undef	wctomb
55*b30d1939SAndy Fiddaman #else
56*b30d1939SAndy Fiddaman #define wctomb			0
57*b30d1939SAndy Fiddaman #endif
58*b30d1939SAndy Fiddaman 
59*b30d1939SAndy Fiddaman #ifdef mblen
60*b30d1939SAndy Fiddaman #undef	mblen
61*b30d1939SAndy Fiddaman extern int		mblen(const char*, size_t);
62*b30d1939SAndy Fiddaman #endif
63*b30d1939SAndy Fiddaman 
64*b30d1939SAndy Fiddaman #undef	mbtowc
65*b30d1939SAndy Fiddaman #undef	setlocale
66*b30d1939SAndy Fiddaman #undef	strcmp
67*b30d1939SAndy Fiddaman #undef	strcoll
68*b30d1939SAndy Fiddaman #undef	strxfrm
69*b30d1939SAndy Fiddaman #undef	valid
70*b30d1939SAndy Fiddaman 
71*b30d1939SAndy Fiddaman #ifndef AST_LC_CANONICAL
72*b30d1939SAndy Fiddaman #define AST_LC_CANONICAL	LC_abbreviated
73*b30d1939SAndy Fiddaman #endif
74*b30d1939SAndy Fiddaman 
75*b30d1939SAndy Fiddaman static void
header(void)76*b30d1939SAndy Fiddaman header(void)
77*b30d1939SAndy Fiddaman {
78*b30d1939SAndy Fiddaman 	static int	done = 0;
79*b30d1939SAndy Fiddaman 
80*b30d1939SAndy Fiddaman 	if (!done)
81*b30d1939SAndy Fiddaman 	{
82*b30d1939SAndy Fiddaman 		done = 1;
83*b30d1939SAndy Fiddaman 		sfprintf(sfstderr, "locale      %17s %16s %16s %16s %s\n", "CATEGORY", "AST", "SYSTEM", "PREVIOUS", "ATTRIBUTES");
84*b30d1939SAndy Fiddaman 	}
85*b30d1939SAndy Fiddaman }
86*b30d1939SAndy Fiddaman 
87*b30d1939SAndy Fiddaman #if _UWIN
88*b30d1939SAndy Fiddaman 
89*b30d1939SAndy Fiddaman #include <ast_windows.h>
90*b30d1939SAndy Fiddaman 
91*b30d1939SAndy Fiddaman #undef	_lib_setlocale
92*b30d1939SAndy Fiddaman #define _lib_setlocale		1
93*b30d1939SAndy Fiddaman 
94*b30d1939SAndy Fiddaman #define setlocale(c,l)		native_setlocale(c,l)
95*b30d1939SAndy Fiddaman 
96*b30d1939SAndy Fiddaman extern char*			uwin_setlocale(int, const char*);
97*b30d1939SAndy Fiddaman 
98*b30d1939SAndy Fiddaman /*
99*b30d1939SAndy Fiddaman  * convert locale to native locale name in buf
100*b30d1939SAndy Fiddaman  */
101*b30d1939SAndy Fiddaman 
102*b30d1939SAndy Fiddaman static char*
native_locale(const char * locale,char * buf,size_t siz)103*b30d1939SAndy Fiddaman native_locale(const char* locale, char* buf, size_t siz)
104*b30d1939SAndy Fiddaman {
105*b30d1939SAndy Fiddaman 	Lc_t*				lc;
106*b30d1939SAndy Fiddaman 	const Lc_attribute_list_t*	ap;
107*b30d1939SAndy Fiddaman 	int				i;
108*b30d1939SAndy Fiddaman 	unsigned long			lcid;
109*b30d1939SAndy Fiddaman 	unsigned long			lang;
110*b30d1939SAndy Fiddaman 	unsigned long			ctry;
111*b30d1939SAndy Fiddaman 	char				lbuf[128];
112*b30d1939SAndy Fiddaman 	char				cbuf[128];
113*b30d1939SAndy Fiddaman 
114*b30d1939SAndy Fiddaman 	if (locale && *locale)
115*b30d1939SAndy Fiddaman 	{
116*b30d1939SAndy Fiddaman 		if (!(lc = lcmake(locale)))
117*b30d1939SAndy Fiddaman 			return 0;
118*b30d1939SAndy Fiddaman 		lang = lc->language->index;
119*b30d1939SAndy Fiddaman 		ctry = 0;
120*b30d1939SAndy Fiddaman 		for (ap = lc->attributes; ap; ap = ap->next)
121*b30d1939SAndy Fiddaman 			if (ctry = ap->attribute->index)
122*b30d1939SAndy Fiddaman 				break;
123*b30d1939SAndy Fiddaman 		if (!ctry)
124*b30d1939SAndy Fiddaman 		{
125*b30d1939SAndy Fiddaman 			for (i = 0; i < elementsof(lc->territory->languages); i++)
126*b30d1939SAndy Fiddaman 				if (lc->territory->languages[i] == lc->language)
127*b30d1939SAndy Fiddaman 				{
128*b30d1939SAndy Fiddaman 					ctry = lc->territory->indices[i];
129*b30d1939SAndy Fiddaman 					break;
130*b30d1939SAndy Fiddaman 				}
131*b30d1939SAndy Fiddaman 			if (!ctry)
132*b30d1939SAndy Fiddaman 			{
133*b30d1939SAndy Fiddaman 				if (!lang)
134*b30d1939SAndy Fiddaman 					return 0;
135*b30d1939SAndy Fiddaman 				ctry = SUBLANG_DEFAULT;
136*b30d1939SAndy Fiddaman 			}
137*b30d1939SAndy Fiddaman 		}
138*b30d1939SAndy Fiddaman 		lcid = MAKELCID(MAKELANGID(lang, ctry), SORT_DEFAULT);
139*b30d1939SAndy Fiddaman 	}
140*b30d1939SAndy Fiddaman 	else
141*b30d1939SAndy Fiddaman 		lcid = GetUserDefaultLCID();
142*b30d1939SAndy Fiddaman 	if (GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, lbuf, sizeof(lbuf)) <= 0 ||
143*b30d1939SAndy Fiddaman 	    GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY, cbuf, sizeof(cbuf)) <= 0)
144*b30d1939SAndy Fiddaman 		return 0;
145*b30d1939SAndy Fiddaman 	if (lc->charset->ms)
146*b30d1939SAndy Fiddaman 		sfsprintf(buf, siz, "%s_%s.%s", lbuf, cbuf, lc->charset->ms);
147*b30d1939SAndy Fiddaman 	else
148*b30d1939SAndy Fiddaman 		sfsprintf(buf, siz, "%s_%s", lbuf, cbuf);
149*b30d1939SAndy Fiddaman 	return buf;
150*b30d1939SAndy Fiddaman }
151*b30d1939SAndy Fiddaman 
152*b30d1939SAndy Fiddaman /*
153*b30d1939SAndy Fiddaman  * locale!=0 here
154*b30d1939SAndy Fiddaman  */
155*b30d1939SAndy Fiddaman 
156*b30d1939SAndy Fiddaman static char*
native_setlocale(int category,const char * locale)157*b30d1939SAndy Fiddaman native_setlocale(int category, const char* locale)
158*b30d1939SAndy Fiddaman {
159*b30d1939SAndy Fiddaman 	char*		usr;
160*b30d1939SAndy Fiddaman 	char*		sys;
161*b30d1939SAndy Fiddaman 	char		buf[256];
162*b30d1939SAndy Fiddaman 
163*b30d1939SAndy Fiddaman 	if (!(usr = native_locale(locale, buf, sizeof(buf))))
164*b30d1939SAndy Fiddaman 		return 0;
165*b30d1939SAndy Fiddaman 
166*b30d1939SAndy Fiddaman 	/*
167*b30d1939SAndy Fiddaman 	 * win32 doesn't have LC_MESSAGES
168*b30d1939SAndy Fiddaman 	 */
169*b30d1939SAndy Fiddaman 
170*b30d1939SAndy Fiddaman 	if (category == LC_MESSAGES)
171*b30d1939SAndy Fiddaman 		return (char*)locale;
172*b30d1939SAndy Fiddaman 	sys = uwin_setlocale(category, usr);
173*b30d1939SAndy Fiddaman 	if (ast.locale.set & AST_LC_debug)
174*b30d1939SAndy Fiddaman 		sfprintf(sfstderr, "locale uwin %17s %-24s %-24s\n", lc_categories[lcindex(category, 0)].name, usr, sys);
175*b30d1939SAndy Fiddaman 	return sys;
176*b30d1939SAndy Fiddaman }
177*b30d1939SAndy Fiddaman 
178*b30d1939SAndy Fiddaman #else
179*b30d1939SAndy Fiddaman 
180*b30d1939SAndy Fiddaman #define native_locale(a,b,c)	((char*)0)
181*b30d1939SAndy Fiddaman 
182*b30d1939SAndy Fiddaman #endif
183*b30d1939SAndy Fiddaman 
184*b30d1939SAndy Fiddaman /*
185*b30d1939SAndy Fiddaman  * LC_COLLATE and LC_CTYPE native support
186*b30d1939SAndy Fiddaman  */
187*b30d1939SAndy Fiddaman 
188*b30d1939SAndy Fiddaman #if !_lib_mbtowc || MB_LEN_MAX <= 1
189*b30d1939SAndy Fiddaman #define mblen		0
190*b30d1939SAndy Fiddaman #define mbtowc		0
191*b30d1939SAndy Fiddaman #endif
192*b30d1939SAndy Fiddaman 
193*b30d1939SAndy Fiddaman #if !_lib_strcoll
194*b30d1939SAndy Fiddaman #define	strcoll		0
195*b30d1939SAndy Fiddaman #endif
196*b30d1939SAndy Fiddaman 
197*b30d1939SAndy Fiddaman #if !_lib_strxfrm
198*b30d1939SAndy Fiddaman #define	strxfrm		0
199*b30d1939SAndy Fiddaman #endif
200*b30d1939SAndy Fiddaman 
201*b30d1939SAndy Fiddaman /*
202*b30d1939SAndy Fiddaman  * LC_COLLATE and LC_CTYPE debug support
203*b30d1939SAndy Fiddaman  *
204*b30d1939SAndy Fiddaman  * mutibyte debug encoding
205*b30d1939SAndy Fiddaman  *
206*b30d1939SAndy Fiddaman  *	DL0 [ '0' .. '4' ] c1 ... c4 DR0
207*b30d1939SAndy Fiddaman  *	DL1 [ '0' .. '4' ] c1 ... c4 DR1
208*b30d1939SAndy Fiddaman  *
209*b30d1939SAndy Fiddaman  * with these ligatures
210*b30d1939SAndy Fiddaman  *
211*b30d1939SAndy Fiddaman  *	ch CH sst SST
212*b30d1939SAndy Fiddaman  *
213*b30d1939SAndy Fiddaman  * and private collation order
214*b30d1939SAndy Fiddaman  *
215*b30d1939SAndy Fiddaman  * wide character display width is the low order 3 bits
216*b30d1939SAndy Fiddaman  * wctomb() uses DL1...DR1
217*b30d1939SAndy Fiddaman  */
218*b30d1939SAndy Fiddaman 
219*b30d1939SAndy Fiddaman #define DEBUG_MB_CUR_MAX	7
220*b30d1939SAndy Fiddaman 
221*b30d1939SAndy Fiddaman #if DEBUG_MB_CUR_MAX < MB_LEN_MAX
222*b30d1939SAndy Fiddaman #undef	DEBUG_MB_CUR_MAX
223*b30d1939SAndy Fiddaman #define DEBUG_MB_CUR_MAX	MB_LEN_MAX
224*b30d1939SAndy Fiddaman #endif
225*b30d1939SAndy Fiddaman 
226*b30d1939SAndy Fiddaman #define DL0	'<'
227*b30d1939SAndy Fiddaman #define DL1	0xab		/* 8-bit mini << on xterm	*/
228*b30d1939SAndy Fiddaman #define DR0	'>'
229*b30d1939SAndy Fiddaman #define DR1	0xbb		/* 8-bit mini >> on xterm	*/
230*b30d1939SAndy Fiddaman 
231*b30d1939SAndy Fiddaman #define DB	((int)sizeof(wchar_t)*8-1)
232*b30d1939SAndy Fiddaman #define DC	7		/* wchar_t embedded char bits	*/
233*b30d1939SAndy Fiddaman #define DX	(DB/DC)		/* wchar_t max embedded chars	*/
234*b30d1939SAndy Fiddaman #define DZ	(DB-DX*DC+1)	/* wchar_t embedded size bits	*/
235*b30d1939SAndy Fiddaman #define DD	3		/* # mb delimiter chars <n...>	*/
236*b30d1939SAndy Fiddaman 
237*b30d1939SAndy Fiddaman static unsigned char debug_order[] =
238*b30d1939SAndy Fiddaman {
239*b30d1939SAndy Fiddaman 	  0,   1,   2,   3,   4,   5,   6,   7,
240*b30d1939SAndy Fiddaman 	  8,   9,  10,  11,  12,  13,  14,  15,
241*b30d1939SAndy Fiddaman 	 16,  17,  18,  19,  20,  21,  22,  23,
242*b30d1939SAndy Fiddaman 	 24,  25,  26,  27,  28,  29,  30,  31,
243*b30d1939SAndy Fiddaman 	 99, 100, 101, 102,  98, 103, 104, 105,
244*b30d1939SAndy Fiddaman 	106, 107, 108,  43, 109,  44,  42, 110,
245*b30d1939SAndy Fiddaman 	 32,  33,  34,  35,  36,  37,  38,  39,
246*b30d1939SAndy Fiddaman 	 40,  41, 111, 112, 113, 114, 115, 116,
247*b30d1939SAndy Fiddaman 	117,  71,  72,  73,  74,  75,  76,  77,
248*b30d1939SAndy Fiddaman 	 78,  79,  80,  81,  82,  83,  84,  85,
249*b30d1939SAndy Fiddaman 	 86,  87,  88,  89,  90,  91,  92,  93,
250*b30d1939SAndy Fiddaman 	 94,  95,  96, 118, 119, 120, 121,  97,
251*b30d1939SAndy Fiddaman 	122,  45,  46,  47,  48,  49,  50,  51,
252*b30d1939SAndy Fiddaman 	 52,  53,  54,  55,  56,  57,  58,  59,
253*b30d1939SAndy Fiddaman 	 60,  61,  62,  63,  64,  65,  66,  67,
254*b30d1939SAndy Fiddaman 	 68,  69,  70, 123, 124, 125, 126, 127,
255*b30d1939SAndy Fiddaman 	128, 129, 130, 131, 132, 133, 134, 135,
256*b30d1939SAndy Fiddaman 	136, 137, 138, 139, 140, 141, 142, 143,
257*b30d1939SAndy Fiddaman 	144, 145, 146, 147, 148, 149, 150, 151,
258*b30d1939SAndy Fiddaman 	152, 153, 154, 155, 156, 157, 158, 159,
259*b30d1939SAndy Fiddaman 	160, 161, 162, 163, 164, 165, 166, 167,
260*b30d1939SAndy Fiddaman 	168, 169, 170, 171, 172, 173, 174, 175,
261*b30d1939SAndy Fiddaman 	176, 177, 178, 179, 180, 181, 182, 183,
262*b30d1939SAndy Fiddaman 	184, 185, 186, 187, 188, 189, 190, 191,
263*b30d1939SAndy Fiddaman 	192, 193, 194, 195, 196, 197, 198, 199,
264*b30d1939SAndy Fiddaman 	200, 201, 202, 203, 204, 205, 206, 207,
265*b30d1939SAndy Fiddaman 	208, 209, 210, 211, 212, 213, 214, 215,
266*b30d1939SAndy Fiddaman 	216, 217, 218, 219, 220, 221, 222, 223,
267*b30d1939SAndy Fiddaman 	224, 225, 226, 227, 228, 229, 230, 231,
268*b30d1939SAndy Fiddaman 	232, 233, 234, 235, 236, 237, 238, 239,
269*b30d1939SAndy Fiddaman 	240, 241, 242, 243, 244, 245, 246, 247,
270*b30d1939SAndy Fiddaman 	248, 249, 250, 251, 252, 253, 254, 255,
271*b30d1939SAndy Fiddaman };
272*b30d1939SAndy Fiddaman 
273*b30d1939SAndy Fiddaman static int
debug_mbtowc(register wchar_t * p,register const char * s,size_t n)274*b30d1939SAndy Fiddaman debug_mbtowc(register wchar_t* p, register const char* s, size_t n)
275*b30d1939SAndy Fiddaman {
276*b30d1939SAndy Fiddaman 	register const char*	q;
277*b30d1939SAndy Fiddaman 	register const char*	r;
278*b30d1939SAndy Fiddaman 	register int		w;
279*b30d1939SAndy Fiddaman 	register int		dr;
280*b30d1939SAndy Fiddaman 	wchar_t			c;
281*b30d1939SAndy Fiddaman 
282*b30d1939SAndy Fiddaman 	if (n < 1)
283*b30d1939SAndy Fiddaman 		return -1;
284*b30d1939SAndy Fiddaman 	if (!s || !*s)
285*b30d1939SAndy Fiddaman 		return 0;
286*b30d1939SAndy Fiddaman 	switch (((unsigned char*)s)[0])
287*b30d1939SAndy Fiddaman 	{
288*b30d1939SAndy Fiddaman 	case DL0:
289*b30d1939SAndy Fiddaman 		dr = DR0;
290*b30d1939SAndy Fiddaman 		break;
291*b30d1939SAndy Fiddaman 	case DL1:
292*b30d1939SAndy Fiddaman 		dr = DR1;
293*b30d1939SAndy Fiddaman 		break;
294*b30d1939SAndy Fiddaman 	default:
295*b30d1939SAndy Fiddaman 	single:
296*b30d1939SAndy Fiddaman 		if (p)
297*b30d1939SAndy Fiddaman 			*p = ((unsigned char*)s)[0] & ((1<<DC)-1);
298*b30d1939SAndy Fiddaman 		return 1;
299*b30d1939SAndy Fiddaman 	}
300*b30d1939SAndy Fiddaman 	if (n < 2)
301*b30d1939SAndy Fiddaman 		return -1;
302*b30d1939SAndy Fiddaman 	if ((w = ((unsigned char*)s)[1]) < '0' || w > ('0' + DX))
303*b30d1939SAndy Fiddaman 		goto single;
304*b30d1939SAndy Fiddaman 	if ((w -= '0' - DD) > n)
305*b30d1939SAndy Fiddaman 		return -1;
306*b30d1939SAndy Fiddaman 	r = s + w - 1;
307*b30d1939SAndy Fiddaman 	q = s += 2;
308*b30d1939SAndy Fiddaman 	while (q < r && *q)
309*b30d1939SAndy Fiddaman 		q++;
310*b30d1939SAndy Fiddaman 	if (q != r || *((unsigned char*)q) != dr)
311*b30d1939SAndy Fiddaman 		return -1;
312*b30d1939SAndy Fiddaman 	if (p)
313*b30d1939SAndy Fiddaman 	{
314*b30d1939SAndy Fiddaman 		c = 1;
315*b30d1939SAndy Fiddaman 		while (--q >= s)
316*b30d1939SAndy Fiddaman 		{
317*b30d1939SAndy Fiddaman 			c <<= DC;
318*b30d1939SAndy Fiddaman 			c |= *((unsigned char*)q);
319*b30d1939SAndy Fiddaman 		}
320*b30d1939SAndy Fiddaman 		c <<= DZ;
321*b30d1939SAndy Fiddaman 		c |= (w - DD);
322*b30d1939SAndy Fiddaman 		*p = c;
323*b30d1939SAndy Fiddaman 	}
324*b30d1939SAndy Fiddaman 	return w;
325*b30d1939SAndy Fiddaman }
326*b30d1939SAndy Fiddaman 
327*b30d1939SAndy Fiddaman static int
debug_wctomb(char * s,wchar_t c)328*b30d1939SAndy Fiddaman debug_wctomb(char* s, wchar_t c)
329*b30d1939SAndy Fiddaman {
330*b30d1939SAndy Fiddaman 	int	w;
331*b30d1939SAndy Fiddaman 	int	i;
332*b30d1939SAndy Fiddaman 	int	k;
333*b30d1939SAndy Fiddaman 
334*b30d1939SAndy Fiddaman 	w = 0;
335*b30d1939SAndy Fiddaman 	if (c >= 0 && c <= UCHAR_MAX)
336*b30d1939SAndy Fiddaman 	{
337*b30d1939SAndy Fiddaman 		w++;
338*b30d1939SAndy Fiddaman 		if (s)
339*b30d1939SAndy Fiddaman 			*s = c;
340*b30d1939SAndy Fiddaman 	}
341*b30d1939SAndy Fiddaman 	else if ((i = c & ((1<<DZ)-1)) > DX)
342*b30d1939SAndy Fiddaman 		return -1;
343*b30d1939SAndy Fiddaman 	else
344*b30d1939SAndy Fiddaman 	{
345*b30d1939SAndy Fiddaman 		w++;
346*b30d1939SAndy Fiddaman 		if (s)
347*b30d1939SAndy Fiddaman 			*s++ = DL0;
348*b30d1939SAndy Fiddaman 		c >>= DZ;
349*b30d1939SAndy Fiddaman 		w++;
350*b30d1939SAndy Fiddaman 		if (s)
351*b30d1939SAndy Fiddaman 			*s++ = i + '0';
352*b30d1939SAndy Fiddaman 		while (i--)
353*b30d1939SAndy Fiddaman 		{
354*b30d1939SAndy Fiddaman 			w++;
355*b30d1939SAndy Fiddaman 			if (s)
356*b30d1939SAndy Fiddaman 				*s++ = (k = c & ((1<<DC)-1)) ? k : '?';
357*b30d1939SAndy Fiddaman 			c >>= DC;
358*b30d1939SAndy Fiddaman 		}
359*b30d1939SAndy Fiddaman 		w++;
360*b30d1939SAndy Fiddaman 		if (s)
361*b30d1939SAndy Fiddaman 			*s++ = DR0;
362*b30d1939SAndy Fiddaman 	}
363*b30d1939SAndy Fiddaman 	return w;
364*b30d1939SAndy Fiddaman }
365*b30d1939SAndy Fiddaman 
366*b30d1939SAndy Fiddaman static int
debug_mblen(const char * s,size_t n)367*b30d1939SAndy Fiddaman debug_mblen(const char* s, size_t n)
368*b30d1939SAndy Fiddaman {
369*b30d1939SAndy Fiddaman 	return debug_mbtowc(NiL, s, n);
370*b30d1939SAndy Fiddaman }
371*b30d1939SAndy Fiddaman 
372*b30d1939SAndy Fiddaman static int
debug_wcwidth(wchar_t c)373*b30d1939SAndy Fiddaman debug_wcwidth(wchar_t c)
374*b30d1939SAndy Fiddaman {
375*b30d1939SAndy Fiddaman 	if (c >= 0 && c <= UCHAR_MAX)
376*b30d1939SAndy Fiddaman 		return 1;
377*b30d1939SAndy Fiddaman 	if ((c &= ((1<<DZ)-1)) > DX)
378*b30d1939SAndy Fiddaman 		return -1;
379*b30d1939SAndy Fiddaman 	return c + DD;
380*b30d1939SAndy Fiddaman }
381*b30d1939SAndy Fiddaman 
382*b30d1939SAndy Fiddaman static int
debug_alpha(wchar_t c)383*b30d1939SAndy Fiddaman debug_alpha(wchar_t c)
384*b30d1939SAndy Fiddaman {
385*b30d1939SAndy Fiddaman 	return isalpha((c >> DZ) & ((1<<DC)-1));
386*b30d1939SAndy Fiddaman }
387*b30d1939SAndy Fiddaman 
388*b30d1939SAndy Fiddaman static size_t
debug_strxfrm(register char * t,register const char * s,size_t n)389*b30d1939SAndy Fiddaman debug_strxfrm(register char* t, register const char* s, size_t n)
390*b30d1939SAndy Fiddaman {
391*b30d1939SAndy Fiddaman 	register const char*	q;
392