xref: /csrg-svn/lib/libc/locale/euc.c (revision 60471)
1*60471Sbostic /*-
2*60471Sbostic  * Copyright (c) 1993 The Regents of the University of California.
3*60471Sbostic  * All rights reserved.
4*60471Sbostic  *
5*60471Sbostic  * This code is derived from software contributed to Berkeley by
6*60471Sbostic  * Paul Borman at Krystal Technologies.
7*60471Sbostic  *
8*60471Sbostic  * %sccs.include.redist.c%
9*60471Sbostic  */
10*60471Sbostic 
11*60471Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*60471Sbostic static char sccsid[] = "@(#)euc.c	5.1 (Berkeley) 05/26/93";
13*60471Sbostic #endif /* LIBC_SCCS and not lint */
14*60471Sbostic 
15*60471Sbostic #include <sys/types.h>
16*60471Sbostic 
17*60471Sbostic #include <errno.h>
18*60471Sbostic #include <rune.h>
19*60471Sbostic #include <stddef.h>
20*60471Sbostic #include <stdio.h>
21*60471Sbostic #include <stdlib.h>
22*60471Sbostic 
23*60471Sbostic rune_t	_EUC_sgetrune __P((const char *, size_t, char const **));
24*60471Sbostic int	_EUC_sputrune __P((rune_t, char *, size_t, char **));
25*60471Sbostic 
26*60471Sbostic typedef struct {
27*60471Sbostic 	int	count[4];
28*60471Sbostic 	rune_t	bits[4];
29*60471Sbostic 	rune_t	mask;
30*60471Sbostic } _EucInfo;
31*60471Sbostic 
32*60471Sbostic int
33*60471Sbostic _EUC_init(rl)
34*60471Sbostic 	_RuneLocale *rl;
35*60471Sbostic {
36*60471Sbostic 	_EucInfo *ei;
37*60471Sbostic 	int x;
38*60471Sbostic 	char *v, *e;
39*60471Sbostic 
40*60471Sbostic 	rl->sgetrune = _EUC_sgetrune;
41*60471Sbostic 	rl->sputrune = _EUC_sputrune;
42*60471Sbostic 
43*60471Sbostic 	if (!rl->variable) {
44*60471Sbostic 		free(rl);
45*60471Sbostic 		return (EFTYPE);
46*60471Sbostic 	}
47*60471Sbostic 	v = (char *) rl->variable;
48*60471Sbostic 
49*60471Sbostic 	while (*v == ' ' || *v == '\t')
50*60471Sbostic 		++v;
51*60471Sbostic 
52*60471Sbostic 	if ((ei = malloc(sizeof(_EucInfo))) == NULL) {
53*60471Sbostic 		free(rl);
54*60471Sbostic 		return (ENOMEM);
55*60471Sbostic 	}
56*60471Sbostic 	for (x = 0; x < 4; ++x) {
57*60471Sbostic 		ei->count[x] = (int) strtol(v, &e, 0);
58*60471Sbostic 		if (v == e || !(v = e)) {
59*60471Sbostic 			free(rl);
60*60471Sbostic 			free(ei);
61*60471Sbostic 			return (EFTYPE);
62*60471Sbostic 		}
63*60471Sbostic 		while (*v == ' ' || *v == '\t')
64*60471Sbostic 			++v;
65*60471Sbostic 		ei->bits[x] = (int) strtol(v, &e, 0);
66*60471Sbostic 		if (v == e || !(v = e)) {
67*60471Sbostic 			free(rl);
68*60471Sbostic 			free(ei);
69*60471Sbostic 			return (EFTYPE);
70*60471Sbostic 		}
71*60471Sbostic 		while (*v == ' ' || *v == '\t')
72*60471Sbostic 			++v;
73*60471Sbostic 	}
74*60471Sbostic 	ei->mask = (int)strtol(v, &e, 0);
75*60471Sbostic 	if (v == e || !(v = e)) {
76*60471Sbostic 		free(rl);
77*60471Sbostic 		free(ei);
78*60471Sbostic 		return (EFTYPE);
79*60471Sbostic 	}
80*60471Sbostic 	if (sizeof(_EucInfo) <= rl->variable_len) {
81*60471Sbostic 		memcpy(rl->variable, ei, sizeof(_EucInfo));
82*60471Sbostic 		free(ei);
83*60471Sbostic 	} else {
84*60471Sbostic 		rl->variable = &ei;
85*60471Sbostic 	}
86*60471Sbostic 	rl->variable_len = sizeof(_EucInfo);
87*60471Sbostic 	_CurrentRuneLocale = rl;
88*60471Sbostic 	__mb_cur_max = 3;
89*60471Sbostic 	return (0);
90*60471Sbostic }
91*60471Sbostic 
92*60471Sbostic #define	CEI	((_EucInfo *)(_CurrentRuneLocale->variable))
93*60471Sbostic 
94*60471Sbostic #define	_SS2	0x008e
95*60471Sbostic #define	_SS3	0x008f
96*60471Sbostic 
97*60471Sbostic static inline int
98*60471Sbostic _euc_set(c)
99*60471Sbostic 	u_int c;
100*60471Sbostic {
101*60471Sbostic 	c &= 0xff;
102*60471Sbostic 
103*60471Sbostic 	return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
104*60471Sbostic }
105*60471Sbostic rune_t
106*60471Sbostic _EUC_sgetrune(string, n, result)
107*60471Sbostic 	const char *string;
108*60471Sbostic 	size_t n;
109*60471Sbostic 	char const **result;
110*60471Sbostic {
111*60471Sbostic 	rune_t rune = 0;
112*60471Sbostic 	int len, set;
113*60471Sbostic 
114*60471Sbostic 	if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) {
115*60471Sbostic 		if (result)
116*60471Sbostic 			*result = string;
117*60471Sbostic 		return (_INVALID_RUNE);
118*60471Sbostic 	}
119*60471Sbostic 	switch (set) {
120*60471Sbostic 	case 3:
121*60471Sbostic 	case 2:
122*60471Sbostic 		--len;
123*60471Sbostic 		++string;
124*60471Sbostic 		/* FALLTHROUGH */
125*60471Sbostic 	case 1:
126*60471Sbostic 	case 0:
127*60471Sbostic 		while (len-- > 0)
128*60471Sbostic 			rune = (rune << 8) | ((u_int)(*string++) & 0xff);
129*60471Sbostic 		break;
130*60471Sbostic 	}
131*60471Sbostic 	if (result)
132*60471Sbostic 		*result = string;
133*60471Sbostic 	return ((rune & ~CEI->mask) | CEI->bits[set]);
134*60471Sbostic }
135*60471Sbostic 
136*60471Sbostic int
137*60471Sbostic _EUC_sputrune(c, string, n, result)
138*60471Sbostic 	rune_t c;
139*60471Sbostic 	char *string, **result;
140*60471Sbostic 	size_t n;
141*60471Sbostic {
142*60471Sbostic 	rune_t m = c & CEI->mask;
143*60471Sbostic 	rune_t nm = c & ~m;
144*60471Sbostic 	int i, len;
145*60471Sbostic 
146*60471Sbostic 	if (m == CEI->bits[1]) {
147*60471Sbostic CodeSet1:
148*60471Sbostic 		/* Codeset 1: The first byte must have 0x80 in it. */
149*60471Sbostic 		i = len = CEI->count[1];
150*60471Sbostic 		if (n >= len) {
151*60471Sbostic 			if (result)
152*60471Sbostic 				*result = string + len;
153*60471Sbostic 			while (i-- > 0)
154*60471Sbostic 				*string++ = (nm >> (i << 3)) | 0x80;
155*60471Sbostic 		} else
156*60471Sbostic 			if (result)
157*60471Sbostic 				*result = (char *) 0;
158*60471Sbostic 	} else {
159*60471Sbostic 		if (m == CEI->bits[0]) {
160*60471Sbostic 			i = len = CEI->count[0];
161*60471Sbostic 			if (n < len) {
162*60471Sbostic 				if (result)
163*60471Sbostic 					*result = NULL;
164*60471Sbostic 				return (len);
165*60471Sbostic 			}
166*60471Sbostic 		} else
167*60471Sbostic 			if (m == CEI->bits[2]) {
168*60471Sbostic 				i = len = CEI->count[2];
169*60471Sbostic 				if (n < len) {
170*60471Sbostic 					if (result)
171*60471Sbostic 						*result = NULL;
172*60471Sbostic 					return (len);
173*60471Sbostic 				}
174*60471Sbostic 				*string++ = _SS2;
175*60471Sbostic 				--i;
176*60471Sbostic 			} else
177*60471Sbostic 				if (m == CEI->bits[3]) {
178*60471Sbostic 					i = len = CEI->count[3];
179*60471Sbostic 					if (n < len) {
180*60471Sbostic 						if (result)
181*60471Sbostic 							*result = NULL;
182*60471Sbostic 						return (len);
183*60471Sbostic 					}
184*60471Sbostic 					*string++ = _SS3;
185*60471Sbostic 					--i;
186*60471Sbostic 				} else
187*60471Sbostic 					goto CodeSet1;	/* Bletch */
188*60471Sbostic 		while (i-- > 0)
189*60471Sbostic 			*string++ = (nm >> (i << 3)) & 0xff;
190*60471Sbostic 		if (result)
191*60471Sbostic 			*result = string;
192*60471Sbostic 	}
193*60471Sbostic 	return (len);
194*60471Sbostic }
195