xref: /csrg-svn/lib/libc/locale/euc.c (revision 61136)
160471Sbostic /*-
2*61136Sbostic  * Copyright (c) 1993
3*61136Sbostic  *	The Regents of the University of California.  All rights reserved.
460471Sbostic  *
560471Sbostic  * This code is derived from software contributed to Berkeley by
660471Sbostic  * Paul Borman at Krystal Technologies.
760471Sbostic  *
860471Sbostic  * %sccs.include.redist.c%
960471Sbostic  */
1060471Sbostic 
1160471Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*61136Sbostic static char sccsid[] = "@(#)euc.c	8.1 (Berkeley) 06/04/93";
1360471Sbostic #endif /* LIBC_SCCS and not lint */
1460471Sbostic 
1560471Sbostic #include <sys/types.h>
1660471Sbostic 
1760471Sbostic #include <errno.h>
1860471Sbostic #include <rune.h>
1960471Sbostic #include <stddef.h>
2060471Sbostic #include <stdio.h>
2160471Sbostic #include <stdlib.h>
2260471Sbostic 
2360471Sbostic rune_t	_EUC_sgetrune __P((const char *, size_t, char const **));
2460471Sbostic int	_EUC_sputrune __P((rune_t, char *, size_t, char **));
2560471Sbostic 
2660471Sbostic typedef struct {
2760471Sbostic 	int	count[4];
2860471Sbostic 	rune_t	bits[4];
2960471Sbostic 	rune_t	mask;
3060471Sbostic } _EucInfo;
3160471Sbostic 
3260471Sbostic int
_EUC_init(rl)3360471Sbostic _EUC_init(rl)
3460471Sbostic 	_RuneLocale *rl;
3560471Sbostic {
3660471Sbostic 	_EucInfo *ei;
3760471Sbostic 	int x;
3860471Sbostic 	char *v, *e;
3960471Sbostic 
4060471Sbostic 	rl->sgetrune = _EUC_sgetrune;
4160471Sbostic 	rl->sputrune = _EUC_sputrune;
4260471Sbostic 
4360471Sbostic 	if (!rl->variable) {
4460471Sbostic 		free(rl);
4560471Sbostic 		return (EFTYPE);
4660471Sbostic 	}
4760471Sbostic 	v = (char *) rl->variable;
4860471Sbostic 
4960471Sbostic 	while (*v == ' ' || *v == '\t')
5060471Sbostic 		++v;
5160471Sbostic 
5260471Sbostic 	if ((ei = malloc(sizeof(_EucInfo))) == NULL) {
5360471Sbostic 		free(rl);
5460471Sbostic 		return (ENOMEM);
5560471Sbostic 	}
5660471Sbostic 	for (x = 0; x < 4; ++x) {
5760471Sbostic 		ei->count[x] = (int) strtol(v, &e, 0);
5860471Sbostic 		if (v == e || !(v = e)) {
5960471Sbostic 			free(rl);
6060471Sbostic 			free(ei);
6160471Sbostic 			return (EFTYPE);
6260471Sbostic 		}
6360471Sbostic 		while (*v == ' ' || *v == '\t')
6460471Sbostic 			++v;
6560471Sbostic 		ei->bits[x] = (int) strtol(v, &e, 0);
6660471Sbostic 		if (v == e || !(v = e)) {
6760471Sbostic 			free(rl);
6860471Sbostic 			free(ei);
6960471Sbostic 			return (EFTYPE);
7060471Sbostic 		}
7160471Sbostic 		while (*v == ' ' || *v == '\t')
7260471Sbostic 			++v;
7360471Sbostic 	}
7460471Sbostic 	ei->mask = (int)strtol(v, &e, 0);
7560471Sbostic 	if (v == e || !(v = e)) {
7660471Sbostic 		free(rl);
7760471Sbostic 		free(ei);
7860471Sbostic 		return (EFTYPE);
7960471Sbostic 	}
8060471Sbostic 	if (sizeof(_EucInfo) <= rl->variable_len) {
8160471Sbostic 		memcpy(rl->variable, ei, sizeof(_EucInfo));
8260471Sbostic 		free(ei);
8360471Sbostic 	} else {
8460471Sbostic 		rl->variable = &ei;
8560471Sbostic 	}
8660471Sbostic 	rl->variable_len = sizeof(_EucInfo);
8760471Sbostic 	_CurrentRuneLocale = rl;
8860471Sbostic 	__mb_cur_max = 3;
8960471Sbostic 	return (0);
9060471Sbostic }
9160471Sbostic 
9260471Sbostic #define	CEI	((_EucInfo *)(_CurrentRuneLocale->variable))
9360471Sbostic 
9460471Sbostic #define	_SS2	0x008e
9560471Sbostic #define	_SS3	0x008f
9660471Sbostic 
9760471Sbostic static inline int
_euc_set(c)9860471Sbostic _euc_set(c)
9960471Sbostic 	u_int c;
10060471Sbostic {
10160471Sbostic 	c &= 0xff;
10260471Sbostic 
10360471Sbostic 	return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
10460471Sbostic }
10560471Sbostic rune_t
_EUC_sgetrune(string,n,result)10660471Sbostic _EUC_sgetrune(string, n, result)
10760471Sbostic 	const char *string;
10860471Sbostic 	size_t n;
10960471Sbostic 	char const **result;
11060471Sbostic {
11160471Sbostic 	rune_t rune = 0;
11260471Sbostic 	int len, set;
11360471Sbostic 
11460471Sbostic 	if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) {
11560471Sbostic 		if (result)
11660471Sbostic 			*result = string;
11760471Sbostic 		return (_INVALID_RUNE);
11860471Sbostic 	}
11960471Sbostic 	switch (set) {
12060471Sbostic 	case 3:
12160471Sbostic 	case 2:
12260471Sbostic 		--len;
12360471Sbostic 		++string;
12460471Sbostic 		/* FALLTHROUGH */
12560471Sbostic 	case 1:
12660471Sbostic 	case 0:
12760471Sbostic 		while (len-- > 0)
12860471Sbostic 			rune = (rune << 8) | ((u_int)(*string++) & 0xff);
12960471Sbostic 		break;
13060471Sbostic 	}
13160471Sbostic 	if (result)
13260471Sbostic 		*result = string;
13360471Sbostic 	return ((rune & ~CEI->mask) | CEI->bits[set]);
13460471Sbostic }
13560471Sbostic 
13660471Sbostic int
_EUC_sputrune(c,string,n,result)13760471Sbostic _EUC_sputrune(c, string, n, result)
13860471Sbostic 	rune_t c;
13960471Sbostic 	char *string, **result;
14060471Sbostic 	size_t n;
14160471Sbostic {
14260471Sbostic 	rune_t m = c & CEI->mask;
14360471Sbostic 	rune_t nm = c & ~m;
14460471Sbostic 	int i, len;
14560471Sbostic 
14660471Sbostic 	if (m == CEI->bits[1]) {
14760471Sbostic CodeSet1:
14860471Sbostic 		/* Codeset 1: The first byte must have 0x80 in it. */
14960471Sbostic 		i = len = CEI->count[1];
15060471Sbostic 		if (n >= len) {
15160471Sbostic 			if (result)
15260471Sbostic 				*result = string + len;
15360471Sbostic 			while (i-- > 0)
15460471Sbostic 				*string++ = (nm >> (i << 3)) | 0x80;
15560471Sbostic 		} else
15660471Sbostic 			if (result)
15760471Sbostic 				*result = (char *) 0;
15860471Sbostic 	} else {
15960471Sbostic 		if (m == CEI->bits[0]) {
16060471Sbostic 			i = len = CEI->count[0];
16160471Sbostic 			if (n < len) {
16260471Sbostic 				if (result)
16360471Sbostic 					*result = NULL;
16460471Sbostic 				return (len);
16560471Sbostic 			}
16660471Sbostic 		} else
16760471Sbostic 			if (m == CEI->bits[2]) {
16860471Sbostic 				i = len = CEI->count[2];
16960471Sbostic 				if (n < len) {
17060471Sbostic 					if (result)
17160471Sbostic 						*result = NULL;
17260471Sbostic 					return (len);
17360471Sbostic 				}
17460471Sbostic 				*string++ = _SS2;
17560471Sbostic 				--i;
17660471Sbostic 			} else
17760471Sbostic 				if (m == CEI->bits[3]) {
17860471Sbostic 					i = len = CEI->count[3];
17960471Sbostic 					if (n < len) {
18060471Sbostic 						if (result)
18160471Sbostic 							*result = NULL;
18260471Sbostic 						return (len);
18360471Sbostic 					}
18460471Sbostic 					*string++ = _SS3;
18560471Sbostic 					--i;
18660471Sbostic 				} else
18760471Sbostic 					goto CodeSet1;	/* Bletch */
18860471Sbostic 		while (i-- > 0)
18960471Sbostic 			*string++ = (nm >> (i << 3)) & 0xff;
19060471Sbostic 		if (result)
19160471Sbostic 			*result = string;
19260471Sbostic 	}
19360471Sbostic 	return (len);
19460471Sbostic }
195