115d9d0b5Syy /*
215d9d0b5Syy  * CDDL HEADER START
315d9d0b5Syy  *
415d9d0b5Syy  * The contents of this file are subject to the terms of the
515d9d0b5Syy  * Common Development and Distribution License (the "License").
615d9d0b5Syy  * You may not use this file except in compliance with the License.
715d9d0b5Syy  *
815d9d0b5Syy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
915d9d0b5Syy  * or http://www.opensolaris.org/os/licensing.
1015d9d0b5Syy  * See the License for the specific language governing permissions
1115d9d0b5Syy  * and limitations under the License.
1215d9d0b5Syy  *
1315d9d0b5Syy  * When distributing Covered Code, include this CDDL HEADER in each
1415d9d0b5Syy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1515d9d0b5Syy  * If applicable, add the following below this CDDL HEADER, with the
1615d9d0b5Syy  * fields enclosed by brackets "[]" replaced with your own identifying
1715d9d0b5Syy  * information: Portions Copyright [yyyy] [name of copyright owner]
1815d9d0b5Syy  *
1915d9d0b5Syy  * CDDL HEADER END
2015d9d0b5Syy  */
2115d9d0b5Syy 
2215d9d0b5Syy /*
2315d9d0b5Syy  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2415d9d0b5Syy  * Use is subject to license terms.
2515d9d0b5Syy  */
2615d9d0b5Syy 
2715d9d0b5Syy #include <sys/types.h>
2815d9d0b5Syy #include <sys/param.h>
2915d9d0b5Syy #include <sys/sysmacros.h>
3015d9d0b5Syy #include <sys/systm.h>
3115d9d0b5Syy #include <sys/debug.h>
3215d9d0b5Syy #include <sys/kmem.h>
3315d9d0b5Syy #include <sys/sunddi.h>
3415d9d0b5Syy #include <sys/byteorder.h>
3515d9d0b5Syy #include <sys/errno.h>
3615d9d0b5Syy #include <sys/euc.h>
3715d9d0b5Syy #include <sys/modctl.h>
3815d9d0b5Syy #include <sys/kiconv.h>
3915d9d0b5Syy 
4015d9d0b5Syy #include <sys/kiconv_ja.h>
4115d9d0b5Syy #include <sys/kiconv_ja_jis_to_unicode.h>
4215d9d0b5Syy #include <sys/kiconv_ja_unicode_to_jis.h>
4315d9d0b5Syy 
4415d9d0b5Syy /*
4515d9d0b5Syy  * The following vector shows remaining bytes in a UTF-8 character.
4615d9d0b5Syy  * Index will be the first byte of the character. This is defined in
4715d9d0b5Syy  * u8_textprep.c.
4815d9d0b5Syy  */
4915d9d0b5Syy extern const int8_t u8_number_of_bytes[];
5015d9d0b5Syy 
5115d9d0b5Syy /*
5215d9d0b5Syy  * The following is a vector of bit-masks to get used bits in
5315d9d0b5Syy  * the first byte of a UTF-8 character. Index is remaining bytes at above of
5415d9d0b5Syy  * the character. This is defined in uconv.c.
5515d9d0b5Syy  */
5615d9d0b5Syy extern const uchar_t u8_masks_tbl[];
5715d9d0b5Syy 
5815d9d0b5Syy /*
5915d9d0b5Syy  * The following two vectors are to provide valid minimum and
6015d9d0b5Syy  * maximum values for the 2'nd byte of a multibyte UTF-8 character for
6115d9d0b5Syy  * better illegal sequence checking. The index value must be the value of
6215d9d0b5Syy  * the first byte of the UTF-8 character. These are defined in u8_textprep.c.
6315d9d0b5Syy  */
6415d9d0b5Syy extern const uint8_t u8_valid_min_2nd_byte[];
6515d9d0b5Syy extern const uint8_t u8_valid_max_2nd_byte[];
6615d9d0b5Syy 
6715d9d0b5Syy static kiconv_ja_euc16_t
kiconv_ja_ucs2_to_euc16(kiconv_ja_ucs2_t ucs2)6815d9d0b5Syy kiconv_ja_ucs2_to_euc16(kiconv_ja_ucs2_t ucs2)
6915d9d0b5Syy {
7015d9d0b5Syy 	const kiconv_ja_euc16_t	*p;
7115d9d0b5Syy 
7215d9d0b5Syy 	if ((p = kiconv_ja_ucs2_to_euc16_index[ucs2 >> 8]) != NULL)
7315d9d0b5Syy 		return (p[ucs2 & 0xff]);
7415d9d0b5Syy 
7515d9d0b5Syy 	return (KICONV_JA_NODEST);
7615d9d0b5Syy }
7715d9d0b5Syy 
7815d9d0b5Syy static size_t
utf8_ucs(uint_t * p,uchar_t ** pip,size_t * pileft,int * errno)7915d9d0b5Syy utf8_ucs(uint_t *p, uchar_t **pip, size_t *pileft, int *errno)
8015d9d0b5Syy {
8115d9d0b5Syy 	uint_t	l;		/* to be copied to *p on successful return */
8215d9d0b5Syy 	uchar_t	ic;		/* current byte */
8315d9d0b5Syy 	uchar_t	ic1;		/* 1st byte */
8415d9d0b5Syy 	uchar_t	*ip = *pip;	/* next byte to read */
8515d9d0b5Syy 	size_t	ileft = *pileft; /* number of bytes available */
86*26672226SToomas Soome 	size_t	rv = 0;		/* return value of this function */
8715d9d0b5Syy 	int	remaining_bytes;
8815d9d0b5Syy 	int	u8_size;
8915d9d0b5Syy 
9015d9d0b5Syy 	KICONV_JA_NGET(ic1);	/* read 1st byte */
9115d9d0b5Syy 
9215d9d0b5Syy 	if (ic1 < 0x80) {
9315d9d0b5Syy 		/* successfully converted */
9415d9d0b5Syy 		*p = (uint_t)ic1;
9515d9d0b5Syy 		goto ret;
9615d9d0b5Syy 	}
9715d9d0b5Syy 
9815d9d0b5Syy 	u8_size = u8_number_of_bytes[ic1];
9915d9d0b5Syy 	if (u8_size == U8_ILLEGAL_CHAR) {
10015d9d0b5Syy 		KICONV_JA_RETERROR(EILSEQ)
10115d9d0b5Syy 	} else if (u8_size == U8_OUT_OF_RANGE_CHAR) {
10215d9d0b5Syy 		KICONV_JA_RETERROR(ERANGE)
10315d9d0b5Syy 	}
10415d9d0b5Syy 
10515d9d0b5Syy 	remaining_bytes = u8_size - 1;
10615d9d0b5Syy 	if (remaining_bytes != 0) {
10715d9d0b5Syy 		l = ic1 & u8_masks_tbl[remaining_bytes];
10815d9d0b5Syy 
10915d9d0b5Syy 		for (; remaining_bytes > 0; remaining_bytes--) {
11015d9d0b5Syy 			KICONV_JA_NGET(ic);
11115d9d0b5Syy 			if (ic1 != 0U) {
11215d9d0b5Syy 				if ((ic < u8_valid_min_2nd_byte[ic1]) ||
11315d9d0b5Syy 				    (ic > u8_valid_max_2nd_byte[ic1])) {
11415d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
11515d9d0b5Syy 				}
11615d9d0b5Syy 				ic1 = 0U; /* 2nd byte check done */
11715d9d0b5Syy 			} else {
11815d9d0b5Syy 				if ((ic < 0x80) || (ic > 0xbf)) {
11915d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
12015d9d0b5Syy 				}
12115d9d0b5Syy 			}
12215d9d0b5Syy 			l = (l << 6) | (ic & 0x3f);
12315d9d0b5Syy 		}
12415d9d0b5Syy 
12515d9d0b5Syy 		/* successfully converted */
12615d9d0b5Syy 		*p = l;
12715d9d0b5Syy 	} else {
12815d9d0b5Syy 		KICONV_JA_RETERROR(EILSEQ)
12915d9d0b5Syy 	}
13015d9d0b5Syy 
13115d9d0b5Syy ret:
13215d9d0b5Syy 	if (rv == 0) {
13315d9d0b5Syy 		/*
13415d9d0b5Syy 		 * Update rv, *pip, and *pileft on successfule return.
13515d9d0b5Syy 		 */
13615d9d0b5Syy 		rv = *pileft - ileft;
13715d9d0b5Syy 		*pip = ip;
13815d9d0b5Syy 		*pileft = ileft;
13915d9d0b5Syy 	}
14015d9d0b5Syy 
14115d9d0b5Syy 	return (rv);
14215d9d0b5Syy }
14315d9d0b5Syy 
14415d9d0b5Syy static size_t
utf8_ucs_replace(uint_t * p,uchar_t ** pip,size_t * pileft,size_t * repnum)14515d9d0b5Syy utf8_ucs_replace(uint_t *p, uchar_t **pip, size_t *pileft, size_t *repnum)
14615d9d0b5Syy {
14715d9d0b5Syy 	uint_t	l;		/* to be copied to *p on successful return */
14815d9d0b5Syy 	uchar_t	ic;		/* current byte */
14915d9d0b5Syy 	uchar_t	ic1;		/* 1st byte */
15015d9d0b5Syy 	uchar_t	*ip = *pip;	/* next byte to read */
15115d9d0b5Syy 	size_t	ileft = *pileft; /* number of bytes available */
152*26672226SToomas Soome 	size_t	rv = 0;		/* return value of this function */
15315d9d0b5Syy 	int	remaining_bytes;
15415d9d0b5Syy 	int	u8_size;
15515d9d0b5Syy 
156*26672226SToomas Soome 	KICONV_JA_NGET_REP_TO_MB(ic1);	/* read 1st byte */
15715d9d0b5Syy 
15815d9d0b5Syy 	if (ic1 < 0x80) {
15915d9d0b5Syy 		/* successfully converted */
16015d9d0b5Syy 		l = (uint_t)ic1;
16115d9d0b5Syy 		goto ret;
16215d9d0b5Syy 	}
16315d9d0b5Syy 
16415d9d0b5Syy 	u8_size = u8_number_of_bytes[ic1];
16515d9d0b5Syy 	if (u8_size == U8_ILLEGAL_CHAR || u8_size == U8_OUT_OF_RANGE_CHAR) {
16615d9d0b5Syy 		l = KICONV_JA_DEF_SINGLE;
16715d9d0b5Syy 		(*repnum)++;
16815d9d0b5Syy 		goto ret;
16915d9d0b5Syy 	}
17015d9d0b5Syy 
17115d9d0b5Syy 	remaining_bytes = u8_size - 1;
17215d9d0b5Syy 
17315d9d0b5Syy 	if (remaining_bytes != 0) {
17415d9d0b5Syy 		l = ic1 & u8_masks_tbl[remaining_bytes];
17515d9d0b5Syy 
17615d9d0b5Syy 		for (; remaining_bytes > 0; remaining_bytes--) {
17715d9d0b5Syy 			KICONV_JA_NGET_REP_TO_MB(ic);
17815d9d0b5Syy 			if (ic1 != 0U) {
17915d9d0b5Syy 				if ((ic < u8_valid_min_2nd_byte[ic1]) ||
18015d9d0b5Syy 				    (ic > u8_valid_max_2nd_byte[ic1])) {
18115d9d0b5Syy 					l = KICONV_JA_DEF_SINGLE;
18215d9d0b5Syy 					(*repnum)++;
18315d9d0b5Syy 					ileft -= (remaining_bytes - 1);
18415d9d0b5Syy 					ip += (remaining_bytes - 1);
18515d9d0b5Syy 					break;
18615d9d0b5Syy 				}
18715d9d0b5Syy 				ic1 = 0U; /* 2nd byte check done */
18815d9d0b5Syy 			} else {
18915d9d0b5Syy 				if ((ic < 0x80) || (ic > 0xbf)) {
19015d9d0b5Syy 					l = KICONV_JA_DEF_SINGLE;
19115d9d0b5Syy 					(*repnum)++;
19215d9d0b5Syy 					ileft -= (remaining_bytes - 1);
19315d9d0b5Syy 					ip += (remaining_bytes - 1);
19415d9d0b5Syy 					break;
19515d9d0b5Syy 				}
19615d9d0b5Syy 			}
19715d9d0b5Syy 			l = (l << 6) | (ic & 0x3f);
19815d9d0b5Syy 		}
19915d9d0b5Syy 	} else {
20015d9d0b5Syy 		l = KICONV_JA_DEF_SINGLE;
20115d9d0b5Syy 		(*repnum)++;
20215d9d0b5Syy 	}
20315d9d0b5Syy 
20415d9d0b5Syy ret:
20515d9d0b5Syy 	/* successfully converted */
20615d9d0b5Syy 	*p = l;
20715d9d0b5Syy 	rv = *pileft - ileft;
20815d9d0b5Syy 
20915d9d0b5Syy 	*pip = ip;
21015d9d0b5Syy 	*pileft = ileft;
21115d9d0b5Syy 
21215d9d0b5Syy 	return (rv);
21315d9d0b5Syy }
21415d9d0b5Syy 
21515d9d0b5Syy static size_t				/* return #bytes read, or -1 */
read_unicode(uint_t * p,uchar_t ** pip,size_t * pileft,int * errno,int flag,size_t * rv)21615d9d0b5Syy read_unicode(
21715d9d0b5Syy 	uint_t	*p,		/* point variable to store UTF-32 */
21815d9d0b5Syy 	uchar_t	**pip,		/* point pointer to input buf */
21915d9d0b5Syy 	size_t	*pileft,	/* point #bytes left in input buf */
22015d9d0b5Syy 	int	*errno,		/* point variable to errno */
22115d9d0b5Syy 	int	flag,		/* kiconvstr flag */
22215d9d0b5Syy 	size_t	*rv)		/* point return valuse */
22315d9d0b5Syy {
22415d9d0b5Syy 	if (flag & KICONV_REPLACE_INVALID)
22515d9d0b5Syy 		return (utf8_ucs_replace(p, pip, pileft, rv));
22615d9d0b5Syy 	else
22715d9d0b5Syy 		return (utf8_ucs(p, pip, pileft, errno));
22815d9d0b5Syy }
22915d9d0b5Syy 
23015d9d0b5Syy static size_t
write_unicode(uint_t u32,char ** pop,size_t * poleft,int * errno)23115d9d0b5Syy write_unicode(
23215d9d0b5Syy 	uint_t	u32,		/* UTF-32 to write */
23315d9d0b5Syy 	char	**pop,		/* point pointer to output buf */
23415d9d0b5Syy 	size_t	*poleft,	/* point #bytes left in output buf */
23515d9d0b5Syy 	int	*errno)		/* point variable to errno */
23615d9d0b5Syy {
23715d9d0b5Syy 	char	*op = *pop;
23815d9d0b5Syy 	size_t	oleft = *poleft;
23915d9d0b5Syy 	size_t	rv = 0;			/* return value */
24015d9d0b5Syy 
24115d9d0b5Syy 	if (u32 <= 0x7f) {
24215d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)(u32));
24315d9d0b5Syy 		rv = 1;
24415d9d0b5Syy 	} else if (u32 <= 0x7ff) {
24515d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)((((u32)>>6) & 0x1f) | 0xc0));
24615d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)(((u32) & 0x3f) | 0x80));
24715d9d0b5Syy 		rv = 2;
24815d9d0b5Syy 	} else if ((u32 >= 0xd800) && (u32 <= 0xdfff)) {
24915d9d0b5Syy 		KICONV_JA_RETERROR(EILSEQ)
25015d9d0b5Syy 	} else if (u32 <= 0xffff) {
25115d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)((((u32)>>12) & 0x0f) | 0xe0));
25215d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)((((u32)>>6) & 0x3f) | 0x80));
25315d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)(((u32) & 0x3f) | 0x80));
25415d9d0b5Syy 		rv = 3;
25515d9d0b5Syy 	} else if (u32 <= 0x10ffff) {
25615d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)((((u32)>>18) & 0x07) | 0xf0));
25715d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)((((u32)>>12) & 0x3f) | 0x80));
25815d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)((((u32)>>6) & 0x3f) | 0x80));
25915d9d0b5Syy 		KICONV_JA_NPUT((uchar_t)(((u32) & 0x3f) | 0x80));
26015d9d0b5Syy 		rv = 4;
26115d9d0b5Syy 	} else {
26215d9d0b5Syy 		KICONV_JA_RETERROR(EILSEQ)
26315d9d0b5Syy 	}
26415d9d0b5Syy 
26515d9d0b5Syy ret:
26615d9d0b5Syy 	if (rv != (size_t)-1) {
26715d9d0b5Syy 		/* update *pop and *poleft only on successful return */
26815d9d0b5Syy 		*pop = op;
26915d9d0b5Syy 		*poleft = oleft;
27015d9d0b5Syy 	}
27115d9d0b5Syy 
27215d9d0b5Syy 	return (rv);
27315d9d0b5Syy }
27415d9d0b5Syy 
27515d9d0b5Syy static void *
_kiconv_ja_open_unicode(uint8_t id)27615d9d0b5Syy _kiconv_ja_open_unicode(uint8_t id)
27715d9d0b5Syy {
27815d9d0b5Syy 	kiconv_state_t	kcd;
27915d9d0b5Syy 
28015d9d0b5Syy 	kcd = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t),
28115d9d0b5Syy 	    KM_SLEEP);
28215d9d0b5Syy 	kcd->id = id;
28315d9d0b5Syy 	kcd->bom_processed = 0;
28415d9d0b5Syy 	return ((void *)kcd);
28515d9d0b5Syy }
28615d9d0b5Syy 
28715d9d0b5Syy static void *
open_eucjp(void)28815d9d0b5Syy open_eucjp(void)
28915d9d0b5Syy {
29015d9d0b5Syy 	return (_kiconv_ja_open_unicode(KICONV_JA_TBLID_EUCJP));
29115d9d0b5Syy }
29215d9d0b5Syy 
29315d9d0b5Syy static void *
open_eucjpms(void)29415d9d0b5Syy open_eucjpms(void)
29515d9d0b5Syy {
29615d9d0b5Syy 	return (_kiconv_ja_open_unicode(KICONV_JA_TBLID_EUCJP_MS));
29715d9d0b5Syy }
29815d9d0b5Syy 
29915d9d0b5Syy static void *
open_sjis(void)30015d9d0b5Syy open_sjis(void)
30115d9d0b5Syy {
30215d9d0b5Syy 	return (_kiconv_ja_open_unicode(KICONV_JA_TBLID_SJIS));
30315d9d0b5Syy }
30415d9d0b5Syy 
30515d9d0b5Syy static void *
open_cp932(void)30615d9d0b5Syy open_cp932(void)
30715d9d0b5Syy {
30815d9d0b5Syy 	return (_kiconv_ja_open_unicode(KICONV_JA_TBLID_CP932));
30915d9d0b5Syy }
31015d9d0b5Syy 
31115d9d0b5Syy int
close_ja(void * kcd)31215d9d0b5Syy close_ja(void *kcd)
31315d9d0b5Syy {
31415d9d0b5Syy 	if (! kcd || kcd == (void *)-1)
31515d9d0b5Syy 		return (EBADF);
31615d9d0b5Syy 
31715d9d0b5Syy 	kmem_free(kcd, sizeof (kiconv_state_data_t));
31815d9d0b5Syy 
31915d9d0b5Syy 	return (0);
32015d9d0b5Syy }
32115d9d0b5Syy 
32215d9d0b5Syy static size_t
_do_kiconv_fr_eucjp(void * kcd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int * errno)32315d9d0b5Syy _do_kiconv_fr_eucjp(void *kcd, char **inbuf, size_t *inbytesleft,
324*26672226SToomas Soome     char **outbuf, size_t *outbytesleft, int *errno)
32515d9d0b5Syy {
32615d9d0b5Syy 	uint_t		u32;		/* UTF-32 */
32715d9d0b5Syy 	uint_t		index;		/* index for table lookup */
32815d9d0b5Syy 	uchar_t		ic1, ic2, ic3;	/* 1st, 2nd, and 3rd bytes of a char */
32915d9d0b5Syy 	size_t		rv = 0;		/* return value of this function */
33015d9d0b5Syy 
33115d9d0b5Syy 	uchar_t	*ip;
33215d9d0b5Syy 	size_t		ileft;
33315d9d0b5Syy 	char		*op;
33415d9d0b5Syy 	size_t		oleft;
33515d9d0b5Syy 	size_t		id = ((kiconv_state_t)kcd)->id;
33615d9d0b5Syy 
33715d9d0b5Syy 	if ((inbuf == NULL) || (*inbuf == NULL)) {
33815d9d0b5Syy 		return (0);
33915d9d0b5Syy 	}
34015d9d0b5Syy 
34115d9d0b5Syy 	ip = (uchar_t *)*inbuf;
34215d9d0b5Syy 	ileft = *inbytesleft;
34315d9d0b5Syy 	op = *outbuf;
34415d9d0b5Syy 	oleft = *outbytesleft;
34515d9d0b5Syy 
34615d9d0b5Syy 	while (ileft != 0) {
347*26672226SToomas Soome 		KICONV_JA_NGET(ic1);		/* get 1st byte */
34815d9d0b5Syy 
349*26672226SToomas Soome 		if (KICONV_JA_ISASC(ic1)) {	/* ASCII; 1 byte */
35015d9d0b5Syy 			u32 = kiconv_ja_jisx0201roman_to_ucs2[ic1];
35115d9d0b5Syy 			KICONV_JA_PUTU(u32);
35215d9d0b5Syy 		} else if (KICONV_JA_ISCS1(ic1)) { /* 0208 or UDC; 2 bytes */
35315d9d0b5Syy 			KICONV_JA_NGET(ic2);
35415d9d0b5Syy 			if (KICONV_JA_ISCS1(ic2)) { /* 2nd byte check passed */
35515d9d0b5Syy 				ic1 &= KICONV_JA_CMASK;
35615d9d0b5Syy 				ic2 &= KICONV_JA_CMASK;
35715d9d0b5Syy 				KICONV_JA_CNV_JISMS_TO_U2(id, u32, ic1, ic2);
35815d9d0b5Syy 				if (u32 == KICONV_JA_NODEST) {
35915d9d0b5Syy 					index = (ic1 - 0x21) * 94 + ic2 - 0x21;
36015d9d0b5Syy 					u32 = kiconv_ja_jisx0208_to_ucs2[index];
36115d9d0b5Syy 				}
36215d9d0b5Syy 				if (u32 == KICONV_JA_REPLACE)
36315d9d0b5Syy 					rv++;
36415d9d0b5Syy 				KICONV_JA_PUTU(u32);
36515d9d0b5Syy 			} else { /* 2nd byte check failed */
36615d9d0b5Syy 				KICONV_JA_RETERROR(EILSEQ)
36715d9d0b5Syy 			}
36815d9d0b5Syy 		} else if (ic1 == SS2) { /* JIS X 0201 Kana; 2 bytes */
36915d9d0b5Syy 			KICONV_JA_NGET(ic2);
37015d9d0b5Syy 			if (KICONV_JA_ISCS2(ic2)) { /* 2nd byte check passed */
37115d9d0b5Syy 				index = (ic2 - 0xa1);
37215d9d0b5Syy 				u32 = kiconv_ja_jisx0201kana_to_ucs2[index];
37315d9d0b5Syy 				KICONV_JA_PUTU(u32);
37415d9d0b5Syy 			} else { /* 2nd byte check failed */
37515d9d0b5Syy 				KICONV_JA_RETERROR(EILSEQ)
37615d9d0b5Syy 			}
37715d9d0b5Syy 		} else if (ic1 == SS3) { /* JIS X 0212 or UDC; 3 bytes */
37815d9d0b5Syy 			KICONV_JA_NGET(ic2);
37915d9d0b5Syy 			if (KICONV_JA_ISCS3(ic2)) { /* 2nd byte check passed */
38015d9d0b5Syy 				KICONV_JA_NGET(ic3);
38115d9d0b5Syy 				if (KICONV_JA_ISCS3(ic3)) {
38215d9d0b5Syy 					/* 3rd byte check passed */
38315d9d0b5Syy 					ic2 &= KICONV_JA_CMASK;
38415d9d0b5Syy 					ic3 &= KICONV_JA_CMASK;
38515d9d0b5Syy 					KICONV_JA_CNV_JIS0212MS_TO_U2(id, u32,
38615d9d0b5Syy 					    ic2, ic3);
38715d9d0b5Syy 					if (u32 == KICONV_JA_NODEST) {
38815d9d0b5Syy 						index = ((ic2 - 0x21) * 94 +
38915d9d0b5Syy 						    (ic3 - 0x21));
39015d9d0b5Syy 						u32 = kiconv_ja_jisx0212_to_ucs2
39115d9d0b5Syy 						    [index];
39215d9d0b5Syy 					}
39315d9d0b5Syy 					if (u32 == KICONV_JA_REPLACE)
39415d9d0b5Syy 						rv++;
39515d9d0b5Syy 					KICONV_JA_PUTU(u32);
39615d9d0b5Syy 				} else { /* 3rd byte check failed */
39715d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
39815d9d0b5Syy 				}
39915d9d0b5Syy 			} else { /* 2nd byte check failed */
40015d9d0b5Syy 				KICONV_JA_RETERROR(EILSEQ)
40115d9d0b5Syy 			}
40215d9d0b5Syy 		} else if (KICONV_JA_ISC1CTRLEUC(ic1)) {
40315d9d0b5Syy 			/* C1 control; 1 byte */
40415d9d0b5Syy 			u32 = ic1;
40515d9d0b5Syy 			KICONV_JA_PUTU(u32);
40615d9d0b5Syy 		} else { /* 1st byte check failed */
40715d9d0b5Syy 			KICONV_JA_RETERROR(EILSEQ)
40815d9d0b5Syy 		}
40915d9d0b5Syy 
41015d9d0b5Syy 		/*
41115d9d0b5Syy 		 * One character successfully converted so update
41215d9d0b5Syy 		 * values outside of this function's stack.
41315d9d0b5Syy 		 */
41415d9d0b5Syy 		*inbuf = (char *)ip;
41515d9d0b5Syy 		*inbytesleft = ileft;
41615d9d0b5Syy 		*outbuf = op;
41715d9d0b5Syy 		*outbytesleft = oleft;
41815d9d0b5Syy 	}
41915d9d0b5Syy 
42015d9d0b5Syy ret:
42115d9d0b5Syy 	return (rv);
42215d9d0b5Syy }
42315d9d0b5Syy 
42415d9d0b5Syy static size_t
_do_kiconv_to_eucjp(void * kcd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int * errno)42515d9d0b5Syy _do_kiconv_to_eucjp(void *kcd, char **inbuf, size_t *inbytesleft,
426*26672226SToomas Soome     char **outbuf, size_t *outbytesleft, int *errno)
42715d9d0b5Syy {
42815d9d0b5Syy 	uchar_t		ic;
42915d9d0b5Syy 	size_t		rv = 0;
43015d9d0b5Syy 	uint_t		ucs4;
43115d9d0b5Syy 	ushort_t	euc16;
43215d9d0b5Syy 
43315d9d0b5Syy 	uchar_t	*ip;
43415d9d0b5Syy 	size_t		ileft;
43515d9d0b5Syy 	char		*op;
43615d9d0b5Syy 	size_t		oleft;
43715d9d0b5Syy 	size_t		read_len;
43815d9d0b5Syy 
43915d9d0b5Syy 	size_t		id = ((kiconv_state_t)kcd)->id;
44015d9d0b5Syy 
44115d9d0b5Syy 	if ((inbuf == NULL) || (*inbuf == NULL)) {
44215d9d0b5Syy 		return (0);
44315d9d0b5Syy 	}
44415d9d0b5Syy 
44515d9d0b5Syy 	ip = (uchar_t *)*inbuf;
44615d9d0b5Syy 	ileft = *inbytesleft;
44715d9d0b5Syy 	op = *outbuf;
44815d9d0b5Syy 	oleft = *outbytesleft;
44915d9d0b5Syy 
45015d9d0b5Syy 	KICONV_JA_CHECK_UTF8_BOM(ip, ileft);
45115d9d0b5Syy 
45215d9d0b5Syy 	while (ileft != 0) {
45315d9d0b5Syy 		KICONV_JA_GETU(&ucs4, 0);
45415d9d0b5Syy 
45515d9d0b5Syy 		if (ucs4 > 0xffff) {
45615d9d0b5Syy 			/* non-BMP */
45715d9d0b5Syy 			KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
45815d9d0b5Syy 			rv++;
45915d9d0b5Syy 			goto next;
46015d9d0b5Syy 		}
46115d9d0b5Syy 
46215d9d0b5Syy 		KICONV_JA_CNV_U2_TO_EUCJPMS(id, euc16, ucs4);
46315d9d0b5Syy 		if (euc16 == KICONV_JA_NODEST) {
46415d9d0b5Syy 			euc16 = kiconv_ja_ucs2_to_euc16((ushort_t)ucs4);
46515d9d0b5Syy 		}
46615d9d0b5Syy 		if (euc16 == KICONV_JA_NODEST) {
46715d9d0b5Syy 			KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
46815d9d0b5Syy 			rv++;
46915d9d0b5Syy 			goto next;
47015d9d0b5Syy 		}
47115d9d0b5Syy 
47215d9d0b5Syy 		switch (euc16 & 0x8080) {
47315d9d0b5Syy 		case 0x0000:	/* CS0 */
47415d9d0b5Syy 			ic = (uchar_t)euc16;
47515d9d0b5Syy 			KICONV_JA_NPUT(ic);
47615d9d0b5Syy 			break;
47715d9d0b5Syy 		case 0x8080:	/* CS1 */
47815d9d0b5Syy 			ic = (uchar_t)((euc16 >> 8) & 0xff);
47915d9d0b5Syy 			KICONV_JA_NPUT(ic);
48015d9d0b5Syy 			ic = (uchar_t)(euc16 & 0xff);
48115d9d0b5Syy 			KICONV_JA_NPUT(ic);
48215d9d0b5Syy 			break;
48315d9d0b5Syy 		case 0x0080:	/* CS2 */
48415d9d0b5Syy 			KICONV_JA_NPUT(SS2);
48515d9d0b5Syy 			ic = (uchar_t)euc16;
48615d9d0b5Syy 			KICONV_JA_NPUT(ic);
48715d9d0b5Syy 			break;
48815d9d0b5Syy 		case 0x8000:	/* CS3 */
48915d9d0b5Syy 			KICONV_JA_NPUT(SS3);
49015d9d0b5Syy 			ic = (uchar_t)((euc16 >> 8) & 0xff);
49115d9d0b5Syy 			KICONV_JA_NPUT(ic);
49215d9d0b5Syy 			ic = (uchar_t)(euc16 & KICONV_JA_CMASK);
49315d9d0b5Syy 			KICONV_JA_NPUT(ic | KICONV_JA_CMSB);
49415d9d0b5Syy 			break;
49515d9d0b5Syy 		}
49615d9d0b5Syy next:
49715d9d0b5Syy 		/*
49815d9d0b5Syy 		 * One character successfully converted so update
49915d9d0b5Syy 		 * values outside of this function's stack.
50015d9d0b5Syy 		 */
50115d9d0b5Syy 		*inbuf = (char *)ip;
50215d9d0b5Syy 		*inbytesleft = ileft;
50315d9d0b5Syy 		*outbuf = op;
50415d9d0b5Syy 		*outbytesleft = oleft;
50515d9d0b5Syy 	}
50615d9d0b5Syy 
50715d9d0b5Syy ret:
50815d9d0b5Syy 	return (rv);
50915d9d0b5Syy }
51015d9d0b5Syy 
51115d9d0b5Syy static size_t
_do_kiconvstr_fr_eucjp(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno,uint8_t id)51215d9d0b5Syy _do_kiconvstr_fr_eucjp(char *inbuf, size_t *inbytesleft, char *outbuf,
513*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno, uint8_t id)
51415d9d0b5Syy {
51515d9d0b5Syy 	uint_t		u32;		/* UTF-32 */
51615d9d0b5Syy 	uint_t		index;		/* index for table lookup */
51715d9d0b5Syy 	uchar_t		ic1, ic2, ic3;	/* 1st, 2nd, and 3rd bytes of a char */
51815d9d0b5Syy 	size_t		rv = 0;		/* return value of this function */
51915d9d0b5Syy 
52015d9d0b5Syy 	uchar_t	*ip;
52115d9d0b5Syy 	size_t		ileft;
52215d9d0b5Syy 	char		*op;
52315d9d0b5Syy 	size_t		oleft;
52415d9d0b5Syy 
52515d9d0b5Syy 	boolean_t do_not_ignore_null;
52615d9d0b5Syy 
527*26672226SToomas Soome 	if ((inbuf == NULL) || (*inbuf == '\0')) {
52815d9d0b5Syy 		return (0);
52915d9d0b5Syy 	}
53015d9d0b5Syy 
53115d9d0b5Syy 	ip = (uchar_t *)inbuf;
53215d9d0b5Syy 	ileft = *inbytesleft;
53315d9d0b5Syy 	op = outbuf;
53415d9d0b5Syy 	oleft = *outbytesleft;
53515d9d0b5Syy 
53615d9d0b5Syy 	do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
53715d9d0b5Syy 
53815d9d0b5Syy 	while (ileft != 0) {
539*26672226SToomas Soome 		KICONV_JA_NGET(ic1);		/* get 1st byte */
54015d9d0b5Syy 
541*26672226SToomas Soome 		if (KICONV_JA_ISASC(ic1)) {	/* ASCII; 1 byte */
54215d9d0b5Syy 			if (ic1 == '\0' && do_not_ignore_null) {
54315d9d0b5Syy 				return (0);
54415d9d0b5Syy 			}
54515d9d0b5Syy 			u32 = kiconv_ja_jisx0201roman_to_ucs2[ic1];
54615d9d0b5Syy 			KICONV_JA_PUTU(u32);
54715d9d0b5Syy 		} else if (KICONV_JA_ISCS1(ic1)) { /* 0208 or UDC; 2 bytes */
54815d9d0b5Syy 			if (flag & KICONV_REPLACE_INVALID) {
54915d9d0b5Syy 				KICONV_JA_NGET_REP_FR_MB(ic2);
55015d9d0b5Syy 			} else {
55115d9d0b5Syy 				KICONV_JA_NGET(ic2);
55215d9d0b5Syy 			}
55315d9d0b5Syy 			if (KICONV_JA_ISCS1(ic2)) { /* 2nd byte check passed */
55415d9d0b5Syy 				ic1 &= KICONV_JA_CMASK;
55515d9d0b5Syy 				ic2 &= KICONV_JA_CMASK;
55615d9d0b5Syy 				KICONV_JA_CNV_JISMS_TO_U2(id, u32, ic1, ic2);
55715d9d0b5Syy 				if (u32 == KICONV_JA_NODEST) {
55815d9d0b5Syy 					index = (ic1 - 0x21) * 94 + ic2 - 0x21;
55915d9d0b5Syy 					u32 = kiconv_ja_jisx0208_to_ucs2[index];
56015d9d0b5Syy 				}
56115d9d0b5Syy 				if (u32 == KICONV_JA_REPLACE)
56215d9d0b5Syy 					rv++;
56315d9d0b5Syy 				KICONV_JA_PUTU(u32);
56415d9d0b5Syy 			} else { /* 2nd byte check failed */
56515d9d0b5Syy 				if (flag & KICONV_REPLACE_INVALID) {
56615d9d0b5Syy 					KICONV_JA_PUTU(KICONV_JA_REPLACE);
56715d9d0b5Syy 					rv++;
56815d9d0b5Syy 				} else {
56915d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
57015d9d0b5Syy 				}
57115d9d0b5Syy 			}
57215d9d0b5Syy 		} else if (ic1 == SS2) { /* JIS X 0201 Kana; 2bytes */
57315d9d0b5Syy 			if (flag & KICONV_REPLACE_INVALID) {
57415d9d0b5Syy 				KICONV_JA_NGET_REP_FR_MB(ic2);
57515d9d0b5Syy 			} else {
57615d9d0b5Syy 				KICONV_JA_NGET(ic2);
57715d9d0b5Syy 			}
57815d9d0b5Syy 			if (KICONV_JA_ISCS2(ic2)) { /* 2nd byte check passed */
57915d9d0b5Syy 				index = (ic2 - 0xa1);
58015d9d0b5Syy 				u32 = kiconv_ja_jisx0201kana_to_ucs2[index];
58115d9d0b5Syy 				KICONV_JA_PUTU(u32);
58215d9d0b5Syy 			} else { /* 2nd byte check failed */
58315d9d0b5Syy 				if (flag & KICONV_REPLACE_INVALID) {
58415d9d0b5Syy 					KICONV_JA_PUTU(KICONV_JA_REPLACE);
58515d9d0b5Syy 					rv++;
58615d9d0b5Syy 				} else {
58715d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
58815d9d0b5Syy 				}
58915d9d0b5Syy 			}
59015d9d0b5Syy 		} else if (ic1 == SS3) { /* JIS X 0212 or UDC; 3 bytes */
59115d9d0b5Syy 			if (flag & KICONV_REPLACE_INVALID) {
59215d9d0b5Syy 				KICONV_JA_NGET_REP_FR_MB(ic2);
59315d9d0b5Syy 			} else {
59415d9d0b5Syy 				KICONV_JA_NGET(ic2);
59515d9d0b5Syy 			}
59615d9d0b5Syy 			if (KICONV_JA_ISCS3(ic2)) { /* 2nd byte check passed */
59715d9d0b5Syy 				if (flag & KICONV_REPLACE_INVALID) {
59815d9d0b5Syy 					KICONV_JA_NGET_REP_FR_MB(ic3);
59915d9d0b5Syy 				} else {
60015d9d0b5Syy 					KICONV_JA_NGET(ic3);
60115d9d0b5Syy 				}
60215d9d0b5Syy 				if (KICONV_JA_ISCS3(ic3)) {
60315d9d0b5Syy 					/* 3rd byte check passed */
60415d9d0b5Syy 					ic2 &= KICONV_JA_CMASK;
60515d9d0b5Syy 					ic3 &= KICONV_JA_CMASK;
60615d9d0b5Syy 					KICONV_JA_CNV_JIS0212MS_TO_U2(id, u32,
60715d9d0b5Syy 					    ic2, ic3);
60815d9d0b5Syy 					if (u32 == KICONV_JA_NODEST) {
60915d9d0b5Syy 						index = ((ic2 - 0x21) * 94 +
61015d9d0b5Syy 						    (ic3 - 0x21));
61115d9d0b5Syy 						u32 = kiconv_ja_jisx0212_to_ucs2
61215d9d0b5Syy 						    [index];
61315d9d0b5Syy 					}
61415d9d0b5Syy 					if (u32 == KICONV_JA_REPLACE)
61515d9d0b5Syy 						rv++;
61615d9d0b5Syy 					KICONV_JA_PUTU(u32);
61715d9d0b5Syy 				} else { /* 3rd byte check failed */
61815d9d0b5Syy 					if (flag & KICONV_REPLACE_INVALID) {
61915d9d0b5Syy 						KICONV_JA_PUTU(
62015d9d0b5Syy 						    KICONV_JA_REPLACE);
62115d9d0b5Syy 						rv++;
62215d9d0b5Syy 					} else {
62315d9d0b5Syy 						KICONV_JA_RETERROR(EILSEQ)
62415d9d0b5Syy 					}
62515d9d0b5Syy 				}
62615d9d0b5Syy 			} else { /* 2nd byte check failed */
62715d9d0b5Syy 				if (flag & KICONV_REPLACE_INVALID) {
62815d9d0b5Syy 					KICONV_JA_PUTU(KICONV_JA_REPLACE);
62915d9d0b5Syy 					rv++;
63015d9d0b5Syy 				} else {
63115d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
63215d9d0b5Syy 				}
63315d9d0b5Syy 			}
63415d9d0b5Syy 		} else if (KICONV_JA_ISC1CTRLEUC(ic1)) {
63515d9d0b5Syy 			/* C1 control; 1 byte */
63615d9d0b5Syy 			u32 = ic1;
63715d9d0b5Syy 			KICONV_JA_PUTU(u32);
63815d9d0b5Syy 		} else { /* 1st byte check failed */
63915d9d0b5Syy 			if (flag & KICONV_REPLACE_INVALID) {
64015d9d0b5Syy 				KICONV_JA_PUTU(KICONV_JA_REPLACE);
64115d9d0b5Syy 				rv++;
64215d9d0b5Syy 			} else {
64315d9d0b5Syy 				KICONV_JA_RETERROR(EILSEQ)
64415d9d0b5Syy 			}
64515d9d0b5Syy 		}
64615d9d0b5Syy 
64715d9d0b5Syy next:
64815d9d0b5Syy 		/*
64915d9d0b5Syy 		 * One character successfully converted so update
65015d9d0b5Syy 		 * values outside of this function's stack.
65115d9d0b5Syy 		 */
65215d9d0b5Syy 		*inbytesleft = ileft;
65315d9d0b5Syy 		*outbytesleft = oleft;
65415d9d0b5Syy 	}
65515d9d0b5Syy 
65615d9d0b5Syy ret:
65715d9d0b5Syy 	return (rv);
65815d9d0b5Syy }
65915d9d0b5Syy 
66015d9d0b5Syy static size_t
_do_kiconvstr_to_eucjp(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno,uint8_t id)66115d9d0b5Syy _do_kiconvstr_to_eucjp(char *inbuf, size_t *inbytesleft, char *outbuf,
662*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno, uint8_t id)
66315d9d0b5Syy {
66415d9d0b5Syy 	uchar_t		ic;
66515d9d0b5Syy 	size_t		rv = 0;
66615d9d0b5Syy 	uint_t		ucs4;
66715d9d0b5Syy 	ushort_t	euc16;
66815d9d0b5Syy 
66915d9d0b5Syy 	uchar_t	*ip;
67015d9d0b5Syy 	size_t		ileft;
67115d9d0b5Syy 	char		*op;
67215d9d0b5Syy 	size_t		oleft;
67315d9d0b5Syy 	size_t		read_len;
67415d9d0b5Syy 
67515d9d0b5Syy 	boolean_t do_not_ignore_null;
67615d9d0b5Syy 
677*26672226SToomas Soome 	if ((inbuf == NULL) || (*inbuf == '\0')) {
67815d9d0b5Syy 		return (0);
67915d9d0b5Syy 	}
68015d9d0b5Syy 
68115d9d0b5Syy 	ip = (uchar_t *)inbuf;
68215d9d0b5Syy 	ileft = *inbytesleft;
68315d9d0b5Syy 	op = outbuf;
68415d9d0b5Syy 	oleft = *outbytesleft;
68515d9d0b5Syy 
68615d9d0b5Syy 	KICONV_JA_CHECK_UTF8_BOM_WITHOUT_STATE(ip, ileft);
68715d9d0b5Syy 
68815d9d0b5Syy 	do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
68915d9d0b5Syy 
69015d9d0b5Syy 	while (ileft != 0) {
69115d9d0b5Syy 		KICONV_JA_GETU(&ucs4, flag);
69215d9d0b5Syy 
69315d9d0b5Syy 		if (ucs4 == 0x0 && do_not_ignore_null) {
69415d9d0b5Syy 			return (0);
69515d9d0b5Syy 		}
69615d9d0b5Syy 
69715d9d0b5Syy 		if (ucs4 > 0xffff) {
69815d9d0b5Syy 			/* non-BMP */
69915d9d0b5Syy 			KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
70015d9d0b5Syy 			rv++;
70115d9d0b5Syy 			goto next;
70215d9d0b5Syy 		}
70315d9d0b5Syy 
70415d9d0b5Syy 		KICONV_JA_CNV_U2_TO_EUCJPMS(id, euc16, ucs4);
70515d9d0b5Syy 		if (euc16 == KICONV_JA_NODEST) {
70615d9d0b5Syy 			euc16 = kiconv_ja_ucs2_to_euc16((ushort_t)ucs4);
70715d9d0b5Syy 		}
70815d9d0b5Syy 		if (euc16 == KICONV_JA_NODEST) {
70915d9d0b5Syy 			KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
71015d9d0b5Syy 			rv++;
71115d9d0b5Syy 			goto next;
71215d9d0b5Syy 		}
71315d9d0b5Syy 
71415d9d0b5Syy 		switch (euc16 & 0x8080) {
71515d9d0b5Syy 		case 0x0000:	/* CS0 */
71615d9d0b5Syy 			ic = (uchar_t)euc16;
71715d9d0b5Syy 			KICONV_JA_NPUT(ic);
71815d9d0b5Syy 			break;
71915d9d0b5Syy 		case 0x8080:	/* CS1 */
72015d9d0b5Syy 			ic = (uchar_t)((euc16 >> 8) & 0xff);
72115d9d0b5Syy 			KICONV_JA_NPUT(ic);
72215d9d0b5Syy 			ic = (uchar_t)(euc16 & 0xff);
72315d9d0b5Syy 			KICONV_JA_NPUT(ic);
72415d9d0b5Syy 			break;
72515d9d0b5Syy 		case 0x0080:	/* CS2 */
72615d9d0b5Syy 			KICONV_JA_NPUT(SS2);
72715d9d0b5Syy 			ic = (uchar_t)euc16;
72815d9d0b5Syy 			KICONV_JA_NPUT(ic);
72915d9d0b5Syy 			break;
73015d9d0b5Syy 		case 0x8000:	/* CS3 */
73115d9d0b5Syy 			KICONV_JA_NPUT(SS3);
73215d9d0b5Syy 			ic = (uchar_t)((euc16 >> 8) & 0xff);
73315d9d0b5Syy 			KICONV_JA_NPUT(ic);
73415d9d0b5Syy 			ic = (uchar_t)(euc16 & KICONV_JA_CMASK);
73515d9d0b5Syy 			KICONV_JA_NPUT(ic | KICONV_JA_CMSB);
73615d9d0b5Syy 			break;
73715d9d0b5Syy 		}
73815d9d0b5Syy next:
73915d9d0b5Syy 		/*
74015d9d0b5Syy 		 * One character successfully converted so update
74115d9d0b5Syy 		 * values outside of this function's stack.
74215d9d0b5Syy 		 */
74315d9d0b5Syy 		*inbytesleft = ileft;
74415d9d0b5Syy 		*outbytesleft = oleft;
74515d9d0b5Syy 	}
74615d9d0b5Syy 
74715d9d0b5Syy ret:
74815d9d0b5Syy 	return (rv);
74915d9d0b5Syy }
75015d9d0b5Syy 
75115d9d0b5Syy static size_t
kiconv_fr_eucjp(void * kcd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int * errno)75215d9d0b5Syy kiconv_fr_eucjp(void *kcd, char **inbuf, size_t *inbytesleft,
753*26672226SToomas Soome     char **outbuf, size_t *outbytesleft, int *errno)
75415d9d0b5Syy {
75515d9d0b5Syy 	if (! kcd || kcd == (void *)-1) {
75615d9d0b5Syy 		*errno = EBADF;
75715d9d0b5Syy 		return ((size_t)-1);
75815d9d0b5Syy 	}
75915d9d0b5Syy 
76015d9d0b5Syy 	return (_do_kiconv_fr_eucjp(kcd, inbuf, inbytesleft,
76115d9d0b5Syy 	    outbuf, outbytesleft, errno));
76215d9d0b5Syy }
76315d9d0b5Syy 
76415d9d0b5Syy static size_t
kiconv_to_eucjp(void * kcd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int * errno)76515d9d0b5Syy kiconv_to_eucjp(void *kcd, char **inbuf, size_t *inbytesleft,
766*26672226SToomas Soome     char **outbuf, size_t *outbytesleft, int *errno)
76715d9d0b5Syy {
76815d9d0b5Syy 	if (! kcd || kcd == (void *)-1) {
76915d9d0b5Syy 		*errno = EBADF;
77015d9d0b5Syy 		return ((size_t)-1);
77115d9d0b5Syy 	}
77215d9d0b5Syy 
77315d9d0b5Syy 	return (_do_kiconv_to_eucjp(kcd, inbuf, inbytesleft,
77415d9d0b5Syy 	    outbuf, outbytesleft, errno));
77515d9d0b5Syy }
77615d9d0b5Syy 
77715d9d0b5Syy static size_t
kiconvstr_fr_eucjp(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno)77815d9d0b5Syy kiconvstr_fr_eucjp(char *inbuf, size_t *inbytesleft, char *outbuf,
779*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno)
78015d9d0b5Syy {
78115d9d0b5Syy 	return (_do_kiconvstr_fr_eucjp(inbuf, inbytesleft, outbuf,
78215d9d0b5Syy 	    outbytesleft, flag, errno, KICONV_JA_TBLID_EUCJP));
78315d9d0b5Syy }
78415d9d0b5Syy 
78515d9d0b5Syy static size_t
kiconvstr_to_eucjp(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno)78615d9d0b5Syy kiconvstr_to_eucjp(char *inbuf, size_t *inbytesleft, char *outbuf,
787*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno)
78815d9d0b5Syy {
78915d9d0b5Syy 	return (_do_kiconvstr_to_eucjp(inbuf, inbytesleft, outbuf,
79015d9d0b5Syy 	    outbytesleft, flag, errno, KICONV_JA_TBLID_EUCJP));
79115d9d0b5Syy }
79215d9d0b5Syy 
79315d9d0b5Syy static size_t
kiconvstr_fr_eucjpms(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno)79415d9d0b5Syy kiconvstr_fr_eucjpms(char *inbuf, size_t *inbytesleft, char *outbuf,
795*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno)
79615d9d0b5Syy {
79715d9d0b5Syy 	return (_do_kiconvstr_fr_eucjp(inbuf, inbytesleft, outbuf,
79815d9d0b5Syy 	    outbytesleft, flag, errno, KICONV_JA_TBLID_EUCJP_MS));
79915d9d0b5Syy }
80015d9d0b5Syy 
80115d9d0b5Syy static size_t
kiconvstr_to_eucjpms(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno)80215d9d0b5Syy kiconvstr_to_eucjpms(char *inbuf, size_t *inbytesleft, char *outbuf,
803*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno)
80415d9d0b5Syy {
80515d9d0b5Syy 	return (_do_kiconvstr_to_eucjp(inbuf, inbytesleft, outbuf,
80615d9d0b5Syy 	    outbytesleft, flag, errno, KICONV_JA_TBLID_EUCJP_MS));
80715d9d0b5Syy }
80815d9d0b5Syy 
80915d9d0b5Syy static size_t
_do_kiconv_fr_sjis(void * kcd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int * errno)81015d9d0b5Syy _do_kiconv_fr_sjis(void *kcd, char **inbuf, size_t *inbytesleft,
811*26672226SToomas Soome     char **outbuf, size_t *outbytesleft, int *errno)
81215d9d0b5Syy {
81315d9d0b5Syy 	uint_t	uni;			/* UTF-32 */
81415d9d0b5Syy 	uint_t	index;			/* index for table lookup */
81515d9d0b5Syy 	uchar_t	ic1, ic2;		/* 1st and 2nd bytes of a char */
81615d9d0b5Syy 	size_t	rv = 0;			/* return value of this function */
81715d9d0b5Syy 
81815d9d0b5Syy 	uchar_t	*ip;
81915d9d0b5Syy 	size_t		ileft;
82015d9d0b5Syy 	char		*op;
82115d9d0b5Syy 	size_t		oleft;
82215d9d0b5Syy 	size_t		id = ((kiconv_state_t)kcd)->id;
82315d9d0b5Syy 
82415d9d0b5Syy 	if ((inbuf == NULL) || (*inbuf == NULL)) {
82515d9d0b5Syy 		return (0);
82615d9d0b5Syy 	}
82715d9d0b5Syy 
82815d9d0b5Syy 	ip = (uchar_t *)*inbuf;
82915d9d0b5Syy 	ileft = *inbytesleft;
83015d9d0b5Syy 	op = *outbuf;
83115d9d0b5Syy 	oleft = *outbytesleft;
83215d9d0b5Syy 
83315d9d0b5Syy 	while (ileft != 0) {
834*26672226SToomas Soome 		KICONV_JA_NGET(ic1);			/* get 1st byte */
83515d9d0b5Syy 
83615d9d0b5Syy 		if (KICONV_JA_ISASC((int)ic1)) {	/* ASCII; 1 byte */
83715d9d0b5Syy 			uni = kiconv_ja_jisx0201roman_to_ucs2[ic1];
83815d9d0b5Syy 			KICONV_JA_PUTU(uni);
83915d9d0b5Syy 		} else if (KICONV_JA_ISSJKANA(ic1)) { /* 0201 Kana; 1byte */
84015d9d0b5Syy 			uni = kiconv_ja_jisx0201kana_to_ucs2[(ic1 - 0xa1)];
84115d9d0b5Syy 			KICONV_JA_PUTU(uni);
84215d9d0b5Syy 		} else if (KICONV_JA_ISSJKANJI1(ic1)) { /* 0208/UDC; 2bytes */
84315d9d0b5Syy 			KICONV_JA_NGET(ic2);
84415d9d0b5Syy 			if (KICONV_JA_ISSJKANJI2(ic2)) {
84515d9d0b5Syy 				ic1 = kiconv_ja_sjtojis1[(ic1 - 0x80)];
84615d9d0b5Syy 				if (ic2 >= 0x9f) {
84715d9d0b5Syy 					ic1++;
84815d9d0b5Syy 				}
84915d9d0b5Syy 				ic2 = kiconv_ja_sjtojis2[ic2];
85015d9d0b5Syy 				KICONV_JA_CNV_JISMS_TO_U2(id, uni, ic1, ic2);
85115d9d0b5Syy 				if (uni == KICONV_JA_NODEST) {
85215d9d0b5Syy 					index = ((ic1 - 0x21) * 94)
85315d9d0b5Syy 					    + (ic2 - 0x21);
85415d9d0b5Syy 					uni = kiconv_ja_jisx0208_to_ucs2[index];
85515d9d0b5Syy 				}
85615d9d0b5Syy 				if (uni == KICONV_JA_REPLACE)
85715d9d0b5Syy 					rv++;
85815d9d0b5Syy 				KICONV_JA_PUTU(uni);
85915d9d0b5Syy 			} else { /* 2nd byte check failed */
86015d9d0b5Syy 				KICONV_JA_RETERROR(EILSEQ)
86115d9d0b5Syy 				/* NOTREACHED */
86215d9d0b5Syy 			}
86315d9d0b5Syy 		} else if (KICONV_JA_ISSJSUPKANJI1(ic1)) { /* VDC, 2 bytes */
86415d9d0b5Syy 			KICONV_JA_NGET(ic2);
86515d9d0b5Syy 			if (KICONV_JA_ISSJKANJI2(ic2)) {
86615d9d0b5Syy 				ic1 = kiconv_ja_sjtojis1[(ic1 - 0x80)];
86715d9d0b5Syy 				if (ic2 >= 0x9f) {
86815d9d0b5Syy 					ic1++;
86915d9d0b5Syy 				}
87015d9d0b5Syy 				index = ((ic1 - 0x21) * 94)
87115d9d0b5Syy 				    + (kiconv_ja_sjtojis2[ic2] - 0x21);
87215d9d0b5Syy 				uni = kiconv_ja_jisx0212_to_ucs2[index];
87315d9d0b5Syy 				if (uni == KICONV_JA_REPLACE)
87415d9d0b5Syy 					rv++;
87515d9d0b5Syy 				KICONV_JA_PUTU(uni);
87615d9d0b5Syy 			} else { /* 2nd byte check failed */
87715d9d0b5Syy 				KICONV_JA_RETERROR(EILSEQ)
87815d9d0b5Syy 			}
87915d9d0b5Syy 		} else if (KICONV_JA_ISSJIBM(ic1) || /* Extended IBM area */
88015d9d0b5Syy 		    KICONV_JA_ISSJNECIBM(ic1)) { /* NEC/IBM area */
88115d9d0b5Syy 			/*
88215d9d0b5Syy 			 * We need a special treatment for each codes.
88315d9d0b5Syy 			 * By adding some offset number for them, we
88415d9d0b5Syy 			 * can process them as the same way of that of
88515d9d0b5Syy 			 * extended IBM chars.
88615d9d0b5Syy 			 */
88715d9d0b5Syy 			KICONV_JA_NGET(ic2);
88815d9d0b5Syy 			if (KICONV_JA_ISSJKANJI2(ic2)) {
88915d9d0b5Syy 				ushort_t dest, upper, lower;
89015d9d0b5Syy 				dest = (ic1 << 8) + ic2;
89115d9d0b5Syy 				if ((0xed40 <= dest) && (dest <= 0xeffc)) {
89215d9d0b5Syy 					KICONV_JA_REMAP_NEC(dest);
89315d9d0b5Syy 					if (dest == 0xffff) {
89415d9d0b5Syy 						KICONV_JA_RETERROR(EILSEQ)
89515d9d0b5Syy 					}
89615d9d0b5Syy 				}
89715d9d0b5Syy 				/*
89815d9d0b5Syy 				 * XXX: 0xfa54 and 0xfa5b must be mapped
89915d9d0b5Syy 				 *	to JIS0208 area. Therefore we
90015d9d0b5Syy 				 *	have to do special treatment.
90115d9d0b5Syy 				 */
90215d9d0b5Syy 				if ((dest == 0xfa54) || (dest == 0xfa5b)) {
90315d9d0b5Syy 					if (dest == 0xfa54) {
90415d9d0b5Syy 						upper = 0x22;
90515d9d0b5Syy 						lower = 0x4c;
90615d9d0b5Syy 					} else {
90715d9d0b5Syy 						upper = 0x22;
90815d9d0b5Syy 						lower = 0x68;
90915d9d0b5Syy 					}
91015d9d0b5Syy 					KICONV_JA_CNV_JISMS_TO_U2(id, uni,
91115d9d0b5Syy 					    upper, lower);
91215d9d0b5Syy 					if (uni == KICONV_JA_NODEST) {
91315d9d0b5Syy 						index = (uint_t)((upper - 0x21)
91415d9d0b5Syy 						    * 94 + (lower - 0x21));
91515d9d0b5Syy 						uni = kiconv_ja_jisx0208_to_ucs2
91615d9d0b5Syy 						    [index];
91715d9d0b5Syy 					}
91815d9d0b5Syy 					if (uni == KICONV_JA_REPLACE)
91915d9d0b5Syy 						rv++;
92015d9d0b5Syy 					KICONV_JA_PUTU(uni);
92115d9d0b5Syy 				} else {
92215d9d0b5Syy 					dest = dest - 0xfa40 -
92315d9d0b5Syy 					    (((dest>>8) - 0xfa) * 0x40);
92415d9d0b5Syy 					dest = kiconv_ja_sjtoibmext[dest];
92515d9d0b5Syy 					if (dest == 0xffff) {
92615d9d0b5Syy 						KICONV_JA_RETERROR(EILSEQ)
92715d9d0b5Syy 					}
92815d9d0b5Syy 					upper = (dest >> 8) & KICONV_JA_CMASK;
92915d9d0b5Syy 					lower = dest & KICONV_JA_CMASK;
93015d9d0b5Syy 					KICONV_JA_CNV_JIS0212MS_TO_U2(id, uni,
93115d9d0b5Syy 					    upper, lower);
93215d9d0b5Syy 					if (uni == KICONV_JA_NODEST) {
93315d9d0b5Syy 						index = (uint_t)((upper - 0x21)
93415d9d0b5Syy 						    * 94 + (lower - 0x21));
93515d9d0b5Syy 						uni = kiconv_ja_jisx0212_to_ucs2
93615d9d0b5Syy 						    [index];
93715d9d0b5Syy 					}
93815d9d0b5Syy 					if (uni == KICONV_JA_REPLACE)
93915d9d0b5Syy 						rv++;
94015d9d0b5Syy 					KICONV_JA_PUTU(uni);
94115d9d0b5Syy 				}
94215d9d0b5Syy 			} else { /* 2nd byte check failed */
94315d9d0b5Syy 				KICONV_JA_RETERROR(EILSEQ)
94415d9d0b5Syy 			}
94515d9d0b5Syy 		} else if ((0xeb <= ic1) && (ic1 <= 0xec)) {
94615d9d0b5Syy 		/*
94715d9d0b5Syy 		 * Based on the draft convention of OSF-JVC CDEWG,
94815d9d0b5Syy 		 * characters in this area will be mapped to
94915d9d0b5Syy 		 * "CHIKAN-MOJI." (convertible character)
95015d9d0b5Syy 		 * We use U+FFFD in this case.
95115d9d0b5Syy 		 */
95215d9d0b5Syy 			KICONV_JA_NGET(ic2);
95315d9d0b5Syy 			if (KICONV_JA_ISSJKANJI2(ic2)) {
95415d9d0b5Syy 				uni = 0xfffd;
95515d9d0b5Syy 				KICONV_JA_PUTU(uni);
95615d9d0b5Syy 			} else { /* 2nd byte check failed */
95715d9d0b5Syy 				KICONV_JA_RETERROR(EILSEQ)
95815d9d0b5Syy 			}
95915d9d0b5Syy 		} else { /* 1st byte check failed */
96015d9d0b5Syy 			KICONV_JA_RETERROR(EILSEQ)
96115d9d0b5Syy 		}
96215d9d0b5Syy 
96315d9d0b5Syy 		/*
96415d9d0b5Syy 		 * One character successfully converted so update
96515d9d0b5Syy 		 * values outside of this function's stack.
96615d9d0b5Syy 		 */
96715d9d0b5Syy 		*inbuf = (char *)ip;
96815d9d0b5Syy 		*inbytesleft = ileft;
96915d9d0b5Syy 		*outbuf = op;
97015d9d0b5Syy 		*outbytesleft = oleft;
97115d9d0b5Syy 	}
97215d9d0b5Syy 
97315d9d0b5Syy ret:
97415d9d0b5Syy 	return (rv);
97515d9d0b5Syy }
97615d9d0b5Syy 
97715d9d0b5Syy /*
97815d9d0b5Syy  * _kiconv_ja_lookuptbl()
97915d9d0b5Syy  * Return the index number if its index-ed number
98015d9d0b5Syy  * is the same as dest value.
98115d9d0b5Syy  */
98215d9d0b5Syy static ushort_t
_kiconv_ja_lookuptbl(ushort_t dest)98315d9d0b5Syy _kiconv_ja_lookuptbl(ushort_t dest)
98415d9d0b5Syy {
98515d9d0b5Syy 	ushort_t tmp;
98615d9d0b5Syy 	int i;
98715d9d0b5Syy 	int sz = (sizeof (kiconv_ja_sjtoibmext) /
98815d9d0b5Syy 	    sizeof (kiconv_ja_sjtoibmext[0]));
98915d9d0b5Syy 
99015d9d0b5Syy 	for (i = 0; i < sz; i++) {
99115d9d0b5Syy 		tmp = (kiconv_ja_sjtoibmext[i] & 0x7f7f);
99215d9d0b5Syy 		if (tmp == dest)
99315d9d0b5Syy 			return ((i + 0xfa40 + ((i / 0xc0) * 0x40)));
99415d9d0b5Syy 	}
99515d9d0b5Syy 	return (0x3f);
99615d9d0b5Syy }
99715d9d0b5Syy 
99815d9d0b5Syy static size_t
_do_kiconv_to_sjis(void * kcd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int * errno)99915d9d0b5Syy _do_kiconv_to_sjis(void *kcd, char **inbuf, size_t *inbytesleft,
1000*26672226SToomas Soome     char **outbuf, size_t *outbytesleft, int *errno)
100115d9d0b5Syy {
100215d9d0b5Syy 	uchar_t	ic;
100315d9d0b5Syy 	size_t		rv = 0;
100415d9d0b5Syy 	uint_t		ucs4;
100515d9d0b5Syy 	ushort_t	euc16;
100615d9d0b5Syy 	ushort_t	dest;
100715d9d0b5Syy 
100815d9d0b5Syy 	uchar_t	*ip;
100915d9d0b5Syy 	size_t		ileft;
101015d9d0b5Syy 	char		*op;
101115d9d0b5Syy 	size_t		oleft;
101215d9d0b5Syy 	size_t		read_len;
101315d9d0b5Syy 
101415d9d0b5Syy 	size_t		id = ((kiconv_state_t)kcd)->id;
101515d9d0b5Syy 
101615d9d0b5Syy 	if ((inbuf == NULL) || (*inbuf == NULL)) {
101715d9d0b5Syy 		return (0);
101815d9d0b5Syy 	}
101915d9d0b5Syy 
102015d9d0b5Syy 	ip = (uchar_t *)*inbuf;
102115d9d0b5Syy 	ileft = *inbytesleft;
102215d9d0b5Syy 	op = *outbuf;
102315d9d0b5Syy 	oleft = *outbytesleft;
102415d9d0b5Syy 
102515d9d0b5Syy 	KICONV_JA_CHECK_UTF8_BOM(ip, ileft);
102615d9d0b5Syy 
102715d9d0b5Syy 	while (ileft != 0) {
102815d9d0b5Syy 		KICONV_JA_GETU(&ucs4, 0);
102915d9d0b5Syy 
103015d9d0b5Syy 		if (ucs4 > 0xffff) {
103115d9d0b5Syy 			/* non-BMP */
103215d9d0b5Syy 			KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
103315d9d0b5Syy 			rv++;
103415d9d0b5Syy 			goto next;
103515d9d0b5Syy 		}
103615d9d0b5Syy 
103715d9d0b5Syy 		KICONV_JA_CNV_U2_TO_EUCJPMS(id, euc16, ucs4);
103815d9d0b5Syy 		if (euc16 == KICONV_JA_NODEST) {
103915d9d0b5Syy 			euc16 = kiconv_ja_ucs2_to_euc16((ushort_t)ucs4);
104015d9d0b5Syy 		}
104115d9d0b5Syy 		if (euc16 == KICONV_JA_NODEST) {
104215d9d0b5Syy 			KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
104315d9d0b5Syy 			rv++;
104415d9d0b5Syy 			goto next;
104515d9d0b5Syy 		}
104615d9d0b5Syy 
104715d9d0b5Syy 		switch (euc16 & 0x8080) {
104815d9d0b5Syy 		case 0x0000:	/* CS0 */
104915d9d0b5Syy 			if (KICONV_JA_ISC1CTRL((uchar_t)euc16)) {
105015d9d0b5Syy 				KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
105115d9d0b5Syy 				rv++;
105215d9d0b5Syy 			} else {
105315d9d0b5Syy 				ic = (uchar_t)euc16;
105415d9d0b5Syy 				KICONV_JA_NPUT(ic);
105515d9d0b5Syy 			}
105615d9d0b5Syy 			break;
105715d9d0b5Syy 		case 0x8080:	/* CS1 */
105815d9d0b5Syy 			ic = (ushort_t)((euc16 >> 8) & KICONV_JA_CMASK);
105915d9d0b5Syy 			KICONV_JA_NPUT(kiconv_ja_jis208tosj1[ic]);
106015d9d0b5Syy 			/*
106115d9d0b5Syy 			 * for even number row (Ku), add 0x80 to
106215d9d0b5Syy 			 * look latter half of kiconv_ja_jistosj2[] array
106315d9d0b5Syy 			 */
106415d9d0b5Syy 			ic = (uchar_t)((euc16 & KICONV_JA_CMASK)
106515d9d0b5Syy 			    + (((ic % 2) == 0) ? 0x80 : 0x00));
106615d9d0b5Syy 			KICONV_JA_NPUT(kiconv_ja_jistosj2[ic]);
106715d9d0b5Syy 			break;
106815d9d0b5Syy 		case 0x0080:	/* CS2 */
106915d9d0b5Syy 			ic = (uchar_t)euc16;
107015d9d0b5Syy 			KICONV_JA_NPUT(ic);
107115d9d0b5Syy 			break;
107215d9d0b5Syy 		case 0x8000:	/* CS3 */
107315d9d0b5Syy 			ic = (ushort_t)((euc16 >> 8) & KICONV_JA_CMASK);
107415d9d0b5Syy 			if (euc16 == 0xa271) {
107515d9d0b5Syy 				/* NUMERO SIGN */
107615d9d0b5Syy 				KICONV_JA_NPUT(0x87);
107715d9d0b5Syy 				KICONV_JA_NPUT(0x82);
107815d9d0b5Syy 			} else if (ic < 0x75) { /* check if IBM VDC */
107915d9d0b5Syy 				dest = _kiconv_ja_lookuptbl(euc16 & 0x7f7f);
108015d9d0b5Syy 				if (dest == 0xffff) {
108115d9d0b5Syy 					KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
108215d9d0b5Syy 				} else {
108315d9d0b5Syy 					/* avoid putting NUL ('\0') */
108415d9d0b5Syy 					if (dest > 0xff) {
108515d9d0b5Syy 						KICONV_JA_NPUT(
108615d9d0b5Syy 						    (dest >> 8) & 0xff);
108715d9d0b5Syy 						KICONV_JA_NPUT(dest & 0xff);
108815d9d0b5Syy 					} else {
108915d9d0b5Syy 						KICONV_JA_NPUT(dest & 0xff);
109015d9d0b5Syy 					}
109115d9d0b5Syy 				}
109215d9d0b5Syy 			} else {
109315d9d0b5Syy 				KICONV_JA_NPUT(kiconv_ja_jis212tosj1[ic]);
109415d9d0b5Syy 				/*
109515d9d0b5Syy 				 * for even number row (Ku), add 0x80 to
109615d9d0b5Syy 				 * look latter half of kiconv_ja_jistosj2[]
109715d9d0b5Syy 				 */
109815d9d0b5Syy 				ic = (ushort_t)((euc16 & KICONV_JA_CMASK)
109915d9d0b5Syy 				    + (((ic % 2) == 0) ? 0x80 : 0x00));
110015d9d0b5Syy 				KICONV_JA_NPUT(kiconv_ja_jistosj2[ic]);
110115d9d0b5Syy 			}
110215d9d0b5Syy 			break;
110315d9d0b5Syy 		}
110415d9d0b5Syy 
110515d9d0b5Syy next:
110615d9d0b5Syy 		/*
110715d9d0b5Syy 		 * One character successfully converted so update
110815d9d0b5Syy 		 * values outside of this function's stack.
110915d9d0b5Syy 		 */
111015d9d0b5Syy 		*inbuf = (char *)ip;
111115d9d0b5Syy 		*inbytesleft = ileft;
111215d9d0b5Syy 		*outbuf = op;
111315d9d0b5Syy 		*outbytesleft = oleft;
111415d9d0b5Syy 	}
111515d9d0b5Syy 
111615d9d0b5Syy ret:
111715d9d0b5Syy 	return (rv);
111815d9d0b5Syy }
111915d9d0b5Syy 
112015d9d0b5Syy static size_t
_do_kiconvstr_fr_sjis(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno,uint8_t id)112115d9d0b5Syy _do_kiconvstr_fr_sjis(char *inbuf, size_t *inbytesleft, char *outbuf,
1122*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno, uint8_t id)
112315d9d0b5Syy {
112415d9d0b5Syy 	uint_t		uni;		/* UTF-32 */
112515d9d0b5Syy 	uint_t		index;		/* index for table lookup */
112615d9d0b5Syy 	uchar_t		ic1, ic2;	/* 1st and 2nd bytes of a char */
112715d9d0b5Syy 	size_t		rv = 0;		/* return value of this function */
112815d9d0b5Syy 
112915d9d0b5Syy 	uchar_t	*ip;
113015d9d0b5Syy 	size_t		ileft;
113115d9d0b5Syy 	char		*op;
113215d9d0b5Syy 	size_t		oleft;
113315d9d0b5Syy 
113415d9d0b5Syy 	boolean_t do_not_ignore_null;
113515d9d0b5Syy 
1136*26672226SToomas Soome 	if ((inbuf == NULL) || (*inbuf == '\0')) {
113715d9d0b5Syy 		return (0);
113815d9d0b5Syy 	}
113915d9d0b5Syy 
114015d9d0b5Syy 	ip = (uchar_t *)inbuf;
114115d9d0b5Syy 	ileft = *inbytesleft;
114215d9d0b5Syy 	op = outbuf;
114315d9d0b5Syy 	oleft = *outbytesleft;
114415d9d0b5Syy 
114515d9d0b5Syy 	do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
114615d9d0b5Syy 
114715d9d0b5Syy 	while (ileft != 0) {
1148*26672226SToomas Soome 		KICONV_JA_NGET(ic1);			/* get 1st byte */
114915d9d0b5Syy 
115015d9d0b5Syy 		if (KICONV_JA_ISASC((int)ic1)) {	/* ASCII; 1 byte */
115115d9d0b5Syy 			if (ic1 == '\0' && do_not_ignore_null) {
115215d9d0b5Syy 				return (0);
115315d9d0b5Syy 			}
115415d9d0b5Syy 			uni = kiconv_ja_jisx0201roman_to_ucs2[ic1];
115515d9d0b5Syy 			KICONV_JA_PUTU(uni);
115615d9d0b5Syy 		} else if (KICONV_JA_ISSJKANA(ic1)) {
115715d9d0b5Syy 			/* JIS X 0201 Kana; 1 byte */
115815d9d0b5Syy 			uni = kiconv_ja_jisx0201kana_to_ucs2[(ic1 - 0xa1)];
115915d9d0b5Syy 			KICONV_JA_PUTU(uni);
116015d9d0b5Syy 		} else if (KICONV_JA_ISSJKANJI1(ic1)) {
116115d9d0b5Syy 			/* JIS X 0208 or UDC; 2 bytes */
116215d9d0b5Syy 			if (flag & KICONV_REPLACE_INVALID) {
116315d9d0b5Syy 				KICONV_JA_NGET_REP_FR_MB(ic2);
116415d9d0b5Syy 			} else {
116515d9d0b5Syy 				KICONV_JA_NGET(ic2);
116615d9d0b5Syy 			}
116715d9d0b5Syy 			if (KICONV_JA_ISSJKANJI2(ic2)) {
116815d9d0b5Syy 				ic1 = kiconv_ja_sjtojis1[(ic1 - 0x80)];
116915d9d0b5Syy 				if (ic2 >= 0x9f) {
117015d9d0b5Syy 					ic1++;
117115d9d0b5Syy 				}
117215d9d0b5Syy 				ic2 = kiconv_ja_sjtojis2[ic2];
117315d9d0b5Syy 				KICONV_JA_CNV_JISMS_TO_U2(id, uni, ic1, ic2);
117415d9d0b5Syy 				if (uni == KICONV_JA_NODEST) {
117515d9d0b5Syy 					index = ((ic1 - 0x21) * 94)
117615d9d0b5Syy 					    + (ic2 - 0x21);
117715d9d0b5Syy 					uni = kiconv_ja_jisx0208_to_ucs2[index];
117815d9d0b5Syy 				}
117915d9d0b5Syy 				if (uni == KICONV_JA_REPLACE)
118015d9d0b5Syy 					rv++;
118115d9d0b5Syy 				KICONV_JA_PUTU(uni);
118215d9d0b5Syy 			} else { /* 2nd byte check failed */
118315d9d0b5Syy 				if (flag & KICONV_REPLACE_INVALID) {
118415d9d0b5Syy 					KICONV_JA_PUTU(KICONV_JA_REPLACE);
118515d9d0b5Syy 					rv++;
118615d9d0b5Syy 				} else {
118715d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
118815d9d0b5Syy 				}
118915d9d0b5Syy 				/* NOTREACHED */
119015d9d0b5Syy 			}
119115d9d0b5Syy 		} else if (KICONV_JA_ISSJSUPKANJI1(ic1)) { /* VDC, 2 bytes */
119215d9d0b5Syy 			if (flag & KICONV_REPLACE_INVALID) {
119315d9d0b5Syy 				KICONV_JA_NGET_REP_FR_MB(ic2);
119415d9d0b5Syy 			} else {
119515d9d0b5Syy 				KICONV_JA_NGET(ic2);
119615d9d0b5Syy 			}
119715d9d0b5Syy 			if (KICONV_JA_ISSJKANJI2(ic2)) {
119815d9d0b5Syy 				ic1 = kiconv_ja_sjtojis1[(ic1 - 0x80)];
119915d9d0b5Syy 				if (ic2 >= 0x9f) {
120015d9d0b5Syy 					ic1++;
120115d9d0b5Syy 				}
120215d9d0b5Syy 				index = ((ic1 - 0x21) * 94)
120315d9d0b5Syy 				    + (kiconv_ja_sjtojis2[ic2] - 0x21);
120415d9d0b5Syy 				uni = kiconv_ja_jisx0212_to_ucs2[index];
120515d9d0b5Syy 				if (uni == KICONV_JA_REPLACE)
120615d9d0b5Syy 					rv++;
120715d9d0b5Syy 				KICONV_JA_PUTU(uni);
120815d9d0b5Syy 			} else { /* 2nd byte check failed */
120915d9d0b5Syy 				if (flag & KICONV_REPLACE_INVALID) {
121015d9d0b5Syy 					KICONV_JA_PUTU(KICONV_JA_REPLACE);
121115d9d0b5Syy 					rv++;
121215d9d0b5Syy 				} else {
121315d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
121415d9d0b5Syy 				}
121515d9d0b5Syy 			}
121615d9d0b5Syy 		} else if (KICONV_JA_ISSJIBM(ic1) || /* Extended IBM area */
121715d9d0b5Syy 		    KICONV_JA_ISSJNECIBM(ic1)) { /* NEC/IBM area */
121815d9d0b5Syy 			/*
121915d9d0b5Syy 			 * We need a special treatment for each codes.
122015d9d0b5Syy 			 * By adding some offset number for them, we
122115d9d0b5Syy 			 * can process them as the same way of that of
122215d9d0b5Syy 			 * extended IBM chars.
122315d9d0b5Syy 			 */
122415d9d0b5Syy 			if (flag & KICONV_REPLACE_INVALID) {
122515d9d0b5Syy 				KICONV_JA_NGET_REP_FR_MB(ic2);
122615d9d0b5Syy 			} else {
122715d9d0b5Syy 				KICONV_JA_NGET(ic2);
122815d9d0b5Syy 			}
122915d9d0b5Syy 			if (KICONV_JA_ISSJKANJI2(ic2)) {
123015d9d0b5Syy 				ushort_t dest, upper, lower;
123115d9d0b5Syy 				dest = (ic1 << 8) + ic2;
123215d9d0b5Syy 				if ((0xed40 <= dest) && (dest <= 0xeffc)) {
123315d9d0b5Syy 					KICONV_JA_REMAP_NEC(dest);
123415d9d0b5Syy 					if (dest == 0xffff) {
123515d9d0b5Syy 						if (flag &
123615d9d0b5Syy 						    KICONV_REPLACE_INVALID) {
123715d9d0b5Syy 							KICONV_JA_PUTU(
123815d9d0b5Syy 							    KICONV_JA_REPLACE);
123915d9d0b5Syy 							rv++;
124015d9d0b5Syy 						} else {
124115d9d0b5Syy 							KICONV_JA_RETERROR(
124215d9d0b5Syy 							    EILSEQ)
124315d9d0b5Syy 						}
124415d9d0b5Syy 					}
124515d9d0b5Syy 				}
124615d9d0b5Syy 				/*
124715d9d0b5Syy 				 * XXX: 0xfa54 and 0xfa5b must be mapped
124815d9d0b5Syy 				 *	to JIS0208 area. Therefore we
124915d9d0b5Syy 				 *	have to do special treatment.
125015d9d0b5Syy 				 */
125115d9d0b5Syy 				if ((dest == 0xfa54) || (dest == 0xfa5b)) {
125215d9d0b5Syy 					if (dest == 0xfa54) {
125315d9d0b5Syy 						upper = 0x22;
125415d9d0b5Syy 						lower = 0x4c;
125515d9d0b5Syy 					} else {
125615d9d0b5Syy 						upper = 0x22;
125715d9d0b5Syy 						lower = 0x68;
125815d9d0b5Syy 					}
125915d9d0b5Syy 					KICONV_JA_CNV_JISMS_TO_U2(id, uni,
126015d9d0b5Syy 					    upper, lower);
126115d9d0b5Syy 					if (uni == KICONV_JA_NODEST) {
126215d9d0b5Syy 						index = (uint_t)((upper - 0x21)
126315d9d0b5Syy 						    * 94 + (lower - 0x21));
126415d9d0b5Syy 						uni = kiconv_ja_jisx0208_to_ucs2
126515d9d0b5Syy 						    [index];
126615d9d0b5Syy 					}
126715d9d0b5Syy 					if (uni == KICONV_JA_REPLACE)
126815d9d0b5Syy 						rv++;
126915d9d0b5Syy 					KICONV_JA_PUTU(uni);
127015d9d0b5Syy 				} else {
127115d9d0b5Syy 					dest = dest - 0xfa40 -
127215d9d0b5Syy 					    (((dest>>8) - 0xfa) * 0x40);
127315d9d0b5Syy 					dest = kiconv_ja_sjtoibmext[dest];
127415d9d0b5Syy 					if (dest == 0xffff) {
127515d9d0b5Syy 						if (flag &
127615d9d0b5Syy 						    KICONV_REPLACE_INVALID) {
127715d9d0b5Syy 							KICONV_JA_PUTU(
127815d9d0b5Syy 							    KICONV_JA_REPLACE);
127915d9d0b5Syy 							rv++;
128015d9d0b5Syy 						} else {
128115d9d0b5Syy 							KICONV_JA_RETERROR(
128215d9d0b5Syy 							    EILSEQ)
128315d9d0b5Syy 						}
128415d9d0b5Syy 					}
128515d9d0b5Syy 					upper = (dest >> 8) & KICONV_JA_CMASK;
128615d9d0b5Syy 					lower = dest & KICONV_JA_CMASK;
128715d9d0b5Syy 					KICONV_JA_CNV_JIS0212MS_TO_U2(id, uni,
128815d9d0b5Syy 					    upper, lower);
128915d9d0b5Syy 					if (uni == KICONV_JA_NODEST) {
129015d9d0b5Syy 						index = (uint_t)((upper - 0x21)
129115d9d0b5Syy 						    * 94 + (lower - 0x21));
129215d9d0b5Syy 						uni = kiconv_ja_jisx0212_to_ucs2
129315d9d0b5Syy 						    [index];
129415d9d0b5Syy 					}
129515d9d0b5Syy 					if (uni == KICONV_JA_REPLACE)
129615d9d0b5Syy 						rv++;
129715d9d0b5Syy 					KICONV_JA_PUTU(uni);
129815d9d0b5Syy 				}
129915d9d0b5Syy 			} else { /* 2nd byte check failed */
130015d9d0b5Syy 				if (flag & KICONV_REPLACE_INVALID) {
130115d9d0b5Syy 					KICONV_JA_PUTU(KICONV_JA_REPLACE);
130215d9d0b5Syy 					rv++;
130315d9d0b5Syy 				} else {
130415d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
130515d9d0b5Syy 				}
130615d9d0b5Syy 			}
130715d9d0b5Syy 		} else if ((0xeb <= ic1) && (ic1 <= 0xec)) {
130815d9d0b5Syy 		/*
130915d9d0b5Syy 		 * Based on the draft convention of OSF-JVC CDEWG,
131015d9d0b5Syy 		 * characters in this area will be mapped to
131115d9d0b5Syy 		 * "CHIKAN-MOJI." (convertible character)
131215d9d0b5Syy 		 * We use U+FFFD in this case.
131315d9d0b5Syy 		 */
131415d9d0b5Syy 			if (flag & KICONV_REPLACE_INVALID) {
131515d9d0b5Syy 				KICONV_JA_NGET_REP_FR_MB(ic2);
131615d9d0b5Syy 			} else {
131715d9d0b5Syy 				KICONV_JA_NGET(ic2);
131815d9d0b5Syy 			}
131915d9d0b5Syy 			if (KICONV_JA_ISSJKANJI2(ic2)) {
132015d9d0b5Syy 				uni = 0xfffd;
132115d9d0b5Syy 				KICONV_JA_PUTU(uni);
132215d9d0b5Syy 			} else { /* 2nd byte check failed */
132315d9d0b5Syy 				if (flag & KICONV_REPLACE_INVALID) {
132415d9d0b5Syy 					KICONV_JA_PUTU(KICONV_JA_REPLACE);
132515d9d0b5Syy 					rv++;
132615d9d0b5Syy 				} else {
132715d9d0b5Syy 					KICONV_JA_RETERROR(EILSEQ)
132815d9d0b5Syy 				}
132915d9d0b5Syy 			}
133015d9d0b5Syy 		} else { /* 1st byte check failed */
133115d9d0b5Syy 			if (flag & KICONV_REPLACE_INVALID) {
133215d9d0b5Syy 				KICONV_JA_PUTU(KICONV_JA_REPLACE);
133315d9d0b5Syy 				rv++;
133415d9d0b5Syy 			} else {
133515d9d0b5Syy 				KICONV_JA_RETERROR(EILSEQ)
133615d9d0b5Syy 			}
133715d9d0b5Syy 		}
133815d9d0b5Syy 
133915d9d0b5Syy next:
134015d9d0b5Syy 		/*
134115d9d0b5Syy 		 * One character successfully converted so update
134215d9d0b5Syy 		 * values outside of this function's stack.
134315d9d0b5Syy 		 */
134415d9d0b5Syy 		*inbytesleft = ileft;
134515d9d0b5Syy 		*outbytesleft = oleft;
134615d9d0b5Syy 	}
134715d9d0b5Syy 
134815d9d0b5Syy ret:
134915d9d0b5Syy 	return (rv);
135015d9d0b5Syy }
135115d9d0b5Syy 
135215d9d0b5Syy static size_t
_do_kiconvstr_to_sjis(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno,uint8_t id)135315d9d0b5Syy _do_kiconvstr_to_sjis(char *inbuf, size_t *inbytesleft, char *outbuf,
1354*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno, uint8_t id)
135515d9d0b5Syy {
135615d9d0b5Syy 	uchar_t		ic;
135715d9d0b5Syy 	size_t		rv = 0;
135815d9d0b5Syy 	uint_t		ucs4;
135915d9d0b5Syy 	ushort_t	euc16;
136015d9d0b5Syy 	ushort_t	dest;
136115d9d0b5Syy 
136215d9d0b5Syy 	uchar_t	*ip;
136315d9d0b5Syy 	size_t		ileft;
136415d9d0b5Syy 	char		*op;
136515d9d0b5Syy 	size_t		oleft;
136615d9d0b5Syy 	size_t		read_len;
136715d9d0b5Syy 
136815d9d0b5Syy 	boolean_t do_not_ignore_null;
136915d9d0b5Syy 
1370*26672226SToomas Soome 	if ((inbuf == NULL) || (*inbuf == '\0')) {
137115d9d0b5Syy 		return (0);
137215d9d0b5Syy 	}
137315d9d0b5Syy 
137415d9d0b5Syy 	ip = (uchar_t *)inbuf;
137515d9d0b5Syy 	ileft = *inbytesleft;
137615d9d0b5Syy 	op = outbuf;
137715d9d0b5Syy 	oleft = *outbytesleft;
137815d9d0b5Syy 
137915d9d0b5Syy 	KICONV_JA_CHECK_UTF8_BOM_WITHOUT_STATE(ip, ileft);
138015d9d0b5Syy 
138115d9d0b5Syy 	do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
138215d9d0b5Syy 
138315d9d0b5Syy 	while (ileft != 0) {
138415d9d0b5Syy 		KICONV_JA_GETU(&ucs4, flag);
138515d9d0b5Syy 
138615d9d0b5Syy 		if (ucs4 == 0x0 && do_not_ignore_null) {
138715d9d0b5Syy 			return (0);
138815d9d0b5Syy 		}
138915d9d0b5Syy 
139015d9d0b5Syy 		if (ucs4 > 0xffff) {
139115d9d0b5Syy 			/* non-BMP */
139215d9d0b5Syy 			KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
139315d9d0b5Syy 			rv++;
139415d9d0b5Syy 			goto next;
139515d9d0b5Syy 		}
139615d9d0b5Syy 
139715d9d0b5Syy 		KICONV_JA_CNV_U2_TO_EUCJPMS(id, euc16, ucs4);
139815d9d0b5Syy 		if (euc16 == KICONV_JA_NODEST) {
139915d9d0b5Syy 			euc16 = kiconv_ja_ucs2_to_euc16((ushort_t)ucs4);
140015d9d0b5Syy 		}
140115d9d0b5Syy 		if (euc16 == KICONV_JA_NODEST) {
140215d9d0b5Syy 			KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
140315d9d0b5Syy 			rv++;
140415d9d0b5Syy 			goto next;
140515d9d0b5Syy 		}
140615d9d0b5Syy 
140715d9d0b5Syy 		switch (euc16 & 0x8080) {
140815d9d0b5Syy 		case 0x0000:	/* CS0 */
140915d9d0b5Syy 			if (KICONV_JA_ISC1CTRL((uchar_t)euc16)) {
141015d9d0b5Syy 				KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
141115d9d0b5Syy 				rv++;
141215d9d0b5Syy 			} else {
141315d9d0b5Syy 				ic = (uchar_t)euc16;
141415d9d0b5Syy 				KICONV_JA_NPUT(ic);
141515d9d0b5Syy 			}
141615d9d0b5Syy 			break;
141715d9d0b5Syy 		case 0x8080:	/* CS1 */
141815d9d0b5Syy 			ic = (ushort_t)((euc16 >> 8) & KICONV_JA_CMASK);
141915d9d0b5Syy 			KICONV_JA_NPUT(kiconv_ja_jis208tosj1[ic]);
142015d9d0b5Syy 			/*
142115d9d0b5Syy 			 * for even number row (Ku), add 0x80 to
142215d9d0b5Syy 			 * look latter half of kiconv_ja_jistosj2[] array
142315d9d0b5Syy 			 */
142415d9d0b5Syy 			ic = (uchar_t)((euc16 & KICONV_JA_CMASK)
142515d9d0b5Syy 			    + (((ic % 2) == 0) ? 0x80 : 0x00));
142615d9d0b5Syy 			KICONV_JA_NPUT(kiconv_ja_jistosj2[ic]);
142715d9d0b5Syy 			break;
142815d9d0b5Syy 		case 0x0080:	/* CS2 */
142915d9d0b5Syy 			ic = (uchar_t)euc16;
143015d9d0b5Syy 			KICONV_JA_NPUT(ic);
143115d9d0b5Syy 			break;
143215d9d0b5Syy 		case 0x8000:	/* CS3 */
143315d9d0b5Syy 			ic = (ushort_t)((euc16 >> 8) & KICONV_JA_CMASK);
143415d9d0b5Syy 			if (euc16 == 0xa271) {
143515d9d0b5Syy 				/* NUMERO SIGN */
143615d9d0b5Syy 				KICONV_JA_NPUT(0x87);
143715d9d0b5Syy 				KICONV_JA_NPUT(0x82);
143815d9d0b5Syy 			} else if (ic < 0x75) { /* check if IBM VDC */
143915d9d0b5Syy 				dest = _kiconv_ja_lookuptbl(euc16 & 0x7f7f);
144015d9d0b5Syy 				if (dest == 0xffff) {
144115d9d0b5Syy 					KICONV_JA_NPUT(KICONV_JA_DEF_SINGLE);
144215d9d0b5Syy 				} else {
144315d9d0b5Syy 					/* avoid putting NUL ('\0') */
144415d9d0b5Syy 					if (dest > 0xff) {
144515d9d0b5Syy 						KICONV_JA_NPUT(
144615d9d0b5Syy 						    (dest >> 8) & 0xff);
144715d9d0b5Syy 						KICONV_JA_NPUT(dest & 0xff);
144815d9d0b5Syy 					} else {
144915d9d0b5Syy 						KICONV_JA_NPUT(dest & 0xff);
145015d9d0b5Syy 					}
145115d9d0b5Syy 				}
145215d9d0b5Syy 			} else {
145315d9d0b5Syy 				KICONV_JA_NPUT(kiconv_ja_jis212tosj1[ic]);
145415d9d0b5Syy 				/*
145515d9d0b5Syy 				 * for even number row (Ku), add 0x80 to
145615d9d0b5Syy 				 * look latter half of kiconv_ja_jistosj2[]
145715d9d0b5Syy 				 */
145815d9d0b5Syy 				ic = (ushort_t)((euc16 & KICONV_JA_CMASK)
145915d9d0b5Syy 				    + (((ic % 2) == 0) ? 0x80 : 0x00));
146015d9d0b5Syy 				KICONV_JA_NPUT(kiconv_ja_jistosj2[ic]);
146115d9d0b5Syy 			}
146215d9d0b5Syy 			break;
146315d9d0b5Syy 		}
146415d9d0b5Syy 
146515d9d0b5Syy next:
146615d9d0b5Syy 		/*
146715d9d0b5Syy 		 * One character successfully converted so update
146815d9d0b5Syy 		 * values outside of this function's stack.
146915d9d0b5Syy 		 */
147015d9d0b5Syy 		*inbytesleft = ileft;
147115d9d0b5Syy 		*outbytesleft = oleft;
147215d9d0b5Syy 	}
147315d9d0b5Syy 
147415d9d0b5Syy ret:
147515d9d0b5Syy 	return (rv);
147615d9d0b5Syy }
147715d9d0b5Syy 
147815d9d0b5Syy static size_t
kiconv_fr_sjis(void * kcd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int * errno)147915d9d0b5Syy kiconv_fr_sjis(void *kcd, char **inbuf, size_t *inbytesleft,
1480*26672226SToomas Soome     char **outbuf, size_t *outbytesleft, int *errno)
148115d9d0b5Syy {
148215d9d0b5Syy 	if (! kcd || kcd == (void *)-1) {
148315d9d0b5Syy 		*errno = EBADF;
148415d9d0b5Syy 		return ((size_t)-1);
148515d9d0b5Syy 	}
148615d9d0b5Syy 
148715d9d0b5Syy 	return (_do_kiconv_fr_sjis(kcd, inbuf, inbytesleft,
148815d9d0b5Syy 	    outbuf, outbytesleft, errno));
148915d9d0b5Syy }
149015d9d0b5Syy 
149115d9d0b5Syy static size_t
kiconv_to_sjis(void * kcd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int * errno)149215d9d0b5Syy kiconv_to_sjis(void *kcd, char **inbuf, size_t *inbytesleft,
1493*26672226SToomas Soome     char **outbuf, size_t *outbytesleft, int *errno)
149415d9d0b5Syy {
149515d9d0b5Syy 	if (! kcd || kcd == (void *)-1) {
149615d9d0b5Syy 		*errno = EBADF;
149715d9d0b5Syy 		return ((size_t)-1);
149815d9d0b5Syy 	}
149915d9d0b5Syy 
150015d9d0b5Syy 	return (_do_kiconv_to_sjis(kcd, inbuf, inbytesleft,
150115d9d0b5Syy 	    outbuf, outbytesleft, errno));
150215d9d0b5Syy }
150315d9d0b5Syy 
150415d9d0b5Syy static size_t
kiconvstr_fr_sjis(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno)150515d9d0b5Syy kiconvstr_fr_sjis(char *inbuf, size_t *inbytesleft, char *outbuf,
1506*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno)
150715d9d0b5Syy {
150815d9d0b5Syy 	return (_do_kiconvstr_fr_sjis(inbuf, inbytesleft, outbuf,
150915d9d0b5Syy 	    outbytesleft, flag, errno, KICONV_JA_TBLID_SJIS));
151015d9d0b5Syy }
151115d9d0b5Syy 
151215d9d0b5Syy static size_t
kiconvstr_to_sjis(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno)151315d9d0b5Syy kiconvstr_to_sjis(char *inbuf, size_t *inbytesleft, char *outbuf,
1514*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno)
151515d9d0b5Syy {
151615d9d0b5Syy 	return (_do_kiconvstr_to_sjis(inbuf, inbytesleft, outbuf,
151715d9d0b5Syy 	    outbytesleft, flag, errno, KICONV_JA_TBLID_SJIS));
151815d9d0b5Syy }
151915d9d0b5Syy 
152015d9d0b5Syy static size_t
kiconvstr_fr_cp932(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno)152115d9d0b5Syy kiconvstr_fr_cp932(char *inbuf, size_t *inbytesleft, char *outbuf,
1522*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno)
152315d9d0b5Syy {
152415d9d0b5Syy 	return (_do_kiconvstr_fr_sjis(inbuf, inbytesleft, outbuf,
152515d9d0b5Syy 	    outbytesleft, flag, errno, KICONV_JA_TBLID_CP932));
152615d9d0b5Syy }
152715d9d0b5Syy 
152815d9d0b5Syy static size_t
kiconvstr_to_cp932(char * inbuf,size_t * inbytesleft,char * outbuf,size_t * outbytesleft,int flag,int * errno)152915d9d0b5Syy kiconvstr_to_cp932(char *inbuf, size_t *inbytesleft, char *outbuf,
1530*26672226SToomas Soome     size_t *outbytesleft, int flag, int *errno)
153115d9d0b5Syy {
153215d9d0b5Syy 	return (_do_kiconvstr_to_sjis(inbuf, inbytesleft, outbuf,
153315d9d0b5Syy 	    outbytesleft, flag, errno, KICONV_JA_TBLID_CP932));
153415d9d0b5Syy }
153515d9d0b5Syy 
153615d9d0b5Syy static kiconv_ops_t kiconv_ja_ops_tbl[] = {
153715d9d0b5Syy 	{
153815d9d0b5Syy 		"eucjp", "utf-8", open_eucjp,
153915d9d0b5Syy 		kiconv_to_eucjp, close_ja, kiconvstr_to_eucjp
154015d9d0b5Syy 	},
154115d9d0b5Syy 	{
154215d9d0b5Syy 		"utf-8", "eucjp", open_eucjp,
154315d9d0b5Syy 		kiconv_fr_eucjp, close_ja, kiconvstr_fr_eucjp
154415d9d0b5Syy 	},
154515d9d0b5Syy 	{
154615d9d0b5Syy 		"eucjpms", "utf-8", open_eucjpms,
154715d9d0b5Syy 		kiconv_to_eucjp, close_ja, kiconvstr_to_eucjpms
154815d9d0b5Syy 	},
154915d9d0b5Syy 	{
155015d9d0b5Syy 		"utf-8", "eucjpms", open_eucjpms,
155115d9d0b5Syy 		kiconv_fr_eucjp, close_ja, kiconvstr_fr_eucjpms
155215d9d0b5Syy 	},
155315d9d0b5Syy 	{
155415d9d0b5Syy 		"sjis", "utf-8", open_sjis,
155515d9d0b5Syy 		kiconv_to_sjis, close_ja, kiconvstr_to_sjis
155615d9d0b5Syy 	},
155715d9d0b5Syy 	{
155815d9d0b5Syy 		"utf-8", "sjis", open_sjis,
155915d9d0b5Syy 		kiconv_fr_sjis, close_ja, kiconvstr_fr_sjis
156015d9d0b5Syy 	},
156115d9d0b5Syy 	{
156215d9d0b5Syy 		"cp932", "utf-8", open_cp932,
156315d9d0b5Syy 		kiconv_to_sjis, close_ja, kiconvstr_to_cp932
156415d9d0b5Syy 	},
156515d9d0b5Syy 	{
156615d9d0b5Syy 		"utf-8", "cp932", open_cp932,
156715d9d0b5Syy 		kiconv_fr_sjis, close_ja, kiconvstr_fr_cp932
156815d9d0b5Syy 	}
156915d9d0b5Syy };
157015d9d0b5Syy 
157115d9d0b5Syy static char *kiconv_ja_aliases[] = {"932", "shiftjis", "pck"};
157215d9d0b5Syy static char *kiconv_ja_canonicals[] = {"cp932", "sjis", "sjis"};
157315d9d0b5Syy 
157415d9d0b5Syy #define	KICONV_JA_MAX_JA_OPS \
157515d9d0b5Syy 	(sizeof (kiconv_ja_ops_tbl) / sizeof (kiconv_ops_t))
157615d9d0b5Syy #define	KICONV_JA_MAX_JA_ALIAS \
157715d9d0b5Syy 	(sizeof (kiconv_ja_aliases) / sizeof (char *))
157815d9d0b5Syy 
157915d9d0b5Syy static kiconv_module_info_t kiconv_ja_info = {
158015d9d0b5Syy 	"kiconv_ja",		/* module name */
158115d9d0b5Syy 	KICONV_JA_MAX_JA_OPS,	/* number of conversion in kiconv_ja */
158215d9d0b5Syy 	kiconv_ja_ops_tbl,	/* kiconv_ja ops table */
158315d9d0b5Syy 	KICONV_JA_MAX_JA_ALIAS,	/* number of alias in kiconv_ja */
158415d9d0b5Syy 	kiconv_ja_aliases,	/* kiconv_ja aliases */
158515d9d0b5Syy 	kiconv_ja_canonicals,	/* kiconv_ja canonicals */
158615d9d0b5Syy 	0
158715d9d0b5Syy };
158815d9d0b5Syy 
158915d9d0b5Syy static struct modlkiconv modlkiconv_ja = {
159015d9d0b5Syy 	&mod_kiconvops,
159115d9d0b5Syy 	"kiconv module for Japanese",
159215d9d0b5Syy 	&kiconv_ja_info
159315d9d0b5Syy };
159415d9d0b5Syy 
159515d9d0b5Syy static struct modlinkage modlinkage = {
159615d9d0b5Syy 	MODREV_1,
159715d9d0b5Syy 	(void *)&modlkiconv_ja,
159815d9d0b5Syy 	NULL
159915d9d0b5Syy };
160015d9d0b5Syy 
160115d9d0b5Syy int
_init(void)160215d9d0b5Syy _init(void)
160315d9d0b5Syy {
160415d9d0b5Syy 	int err;
160515d9d0b5Syy 
160615d9d0b5Syy 	err = mod_install(&modlinkage);
160715d9d0b5Syy 	if (err)
160815d9d0b5Syy 		cmn_err(CE_WARN, "kiconv_ja: failed to load kernel module");
160915d9d0b5Syy 
161015d9d0b5Syy 	return (err);
161115d9d0b5Syy }
161215d9d0b5Syy 
161315d9d0b5Syy int
_info(struct modinfo * modinfop)161415d9d0b5Syy _info(struct modinfo *modinfop)
161515d9d0b5Syy {
161615d9d0b5Syy 	return (mod_info(&modlinkage, modinfop));
161715d9d0b5Syy }
161815d9d0b5Syy 
161915d9d0b5Syy int
_fini(void)162015d9d0b5Syy _fini(void)
162115d9d0b5Syy {
162215d9d0b5Syy 	int err;
162315d9d0b5Syy 
162415d9d0b5Syy 	/*
162515d9d0b5Syy 	 * If this module is being used, then, we cannot remove the module.
162615d9d0b5Syy 	 * The following checking will catch pretty much all usual cases.
162715d9d0b5Syy 	 *
162815d9d0b5Syy 	 * Any remaining will be catached by the kiconv_unregister_module()
162915d9d0b5Syy 	 * during mod_remove() at below.
163015d9d0b5Syy 	 */
163115d9d0b5Syy 	if (kiconv_module_ref_count(KICONV_MODULE_ID_JA))
163215d9d0b5Syy 		return (EBUSY);
163315d9d0b5Syy 
163415d9d0b5Syy 	err = mod_remove(&modlinkage);
163515d9d0b5Syy 	if (err)
163615d9d0b5Syy 		cmn_err(CE_WARN, "kiconv_ja: failed to remove kernel module");
163715d9d0b5Syy 
163815d9d0b5Syy 	return (err);
163915d9d0b5Syy }
1640