euc.c revision 92905
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 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $FreeBSD: head/lib/libc/locale/euc.c 92905 2002-03-21 22:49:10Z obrien $
37 */
38
39#if defined(LIBC_SCCS) && !defined(lint)
40static char sccsid[] = "@(#)euc.c	8.1 (Berkeley) 6/4/93";
41#endif /* LIBC_SCCS and not lint */
42
43#include <sys/types.h>
44
45#include <errno.h>
46#include <rune.h>
47#include <stddef.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51
52rune_t	_EUC_sgetrune(const char *, size_t, char const **);
53int	_EUC_sputrune(rune_t, char *, size_t, char **);
54
55typedef struct {
56	int	count[4];
57	rune_t	bits[4];
58	rune_t	mask;
59} _EucInfo;
60
61int
62_EUC_init(rl)
63	_RuneLocale *rl;
64{
65	_EucInfo *ei;
66	int x;
67	char *v, *e;
68
69	rl->sgetrune = _EUC_sgetrune;
70	rl->sputrune = _EUC_sputrune;
71
72	if (!rl->variable) {
73		free(rl);
74		return (EFTYPE);
75	}
76	v = (char *) rl->variable;
77
78	while (*v == ' ' || *v == '\t')
79		++v;
80
81	if ((ei = malloc(sizeof(_EucInfo))) == NULL) {
82		free(rl);
83		return (ENOMEM);
84	}
85	for (x = 0; x < 4; ++x) {
86		ei->count[x] = (int) strtol(v, &e, 0);
87		if (v == e || !(v = e)) {
88			free(rl);
89			free(ei);
90			return (EFTYPE);
91		}
92		while (*v == ' ' || *v == '\t')
93			++v;
94		ei->bits[x] = (int) strtol(v, &e, 0);
95		if (v == e || !(v = e)) {
96			free(rl);
97			free(ei);
98			return (EFTYPE);
99		}
100		while (*v == ' ' || *v == '\t')
101			++v;
102	}
103	ei->mask = (int)strtol(v, &e, 0);
104	if (v == e || !(v = e)) {
105		free(rl);
106		free(ei);
107		return (EFTYPE);
108	}
109	if (sizeof(_EucInfo) <= rl->variable_len) {
110		memcpy(rl->variable, ei, sizeof(_EucInfo));
111		free(ei);
112	} else {
113		rl->variable = &ei;
114	}
115	rl->variable_len = sizeof(_EucInfo);
116	_CurrentRuneLocale = rl;
117	__mb_cur_max = 3;
118	return (0);
119}
120
121#define	CEI	((_EucInfo *)(_CurrentRuneLocale->variable))
122
123#define	_SS2	0x008e
124#define	_SS3	0x008f
125
126static inline int
127_euc_set(c)
128	u_int c;
129{
130	c &= 0xff;
131
132	return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
133}
134rune_t
135_EUC_sgetrune(string, n, result)
136	const char *string;
137	size_t n;
138	char const **result;
139{
140	rune_t rune = 0;
141	int len, set;
142
143	if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) {
144		if (result)
145			*result = string;
146		return (_INVALID_RUNE);
147	}
148	switch (set) {
149	case 3:
150	case 2:
151		--len;
152		++string;
153		/* FALLTHROUGH */
154	case 1:
155	case 0:
156		while (len-- > 0)
157			rune = (rune << 8) | ((u_int)(*string++) & 0xff);
158		break;
159	}
160	if (result)
161		*result = string;
162	return ((rune & ~CEI->mask) | CEI->bits[set]);
163}
164
165int
166_EUC_sputrune(c, string, n, result)
167	rune_t c;
168	char *string, **result;
169	size_t n;
170{
171	rune_t m = c & CEI->mask;
172	rune_t nm = c & ~m;
173	int i, len;
174
175	if (m == CEI->bits[1]) {
176CodeSet1:
177		/* Codeset 1: The first byte must have 0x80 in it. */
178		i = len = CEI->count[1];
179		if (n >= len) {
180			if (result)
181				*result = string + len;
182			while (i-- > 0)
183				*string++ = (nm >> (i << 3)) | 0x80;
184		} else
185			if (result)
186				*result = (char *) 0;
187	} else {
188		if (m == CEI->bits[0]) {
189			i = len = CEI->count[0];
190			if (n < len) {
191				if (result)
192					*result = NULL;
193				return (len);
194			}
195		} else
196			if (m == CEI->bits[2]) {
197				i = len = CEI->count[2];
198				if (n < len) {
199					if (result)
200						*result = NULL;
201					return (len);
202				}
203				*string++ = _SS2;
204				--i;
205			} else
206				if (m == CEI->bits[3]) {
207					i = len = CEI->count[3];
208					if (n < len) {
209						if (result)
210							*result = NULL;
211						return (len);
212					}
213					*string++ = _SS3;
214					--i;
215				} else
216					goto CodeSet1;	/* Bletch */
217		while (i-- > 0)
218			*string++ = (nm >> (i << 3)) & 0xff;
219		if (result)
220			*result = string;
221	}
222	return (len);
223}
224