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