1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <euc.h>
30 #include "japanese.h"
31 #include "jfp_iconv_unicode.h"
32 
33 #define	JFP_J2U_ICONV_X0213
34 #include "jfp_jis_to_ucs2.h"
35 
36 void *
_icv_open(void)37 _icv_open(void)
38 {
39 	return (_icv_open_unicode((size_t)0));
40 }
41 
42 void
_icv_close(void * cd)43 _icv_close(void *cd)
44 {
45 	_icv_close_unicode(cd);
46 	return;
47 }
48 
49 size_t
_icv_iconv(void * cd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)50 _icv_iconv(void *cd, char **inbuf, size_t *inbytesleft,
51 				char **outbuf, size_t *outbytesleft)
52 {
53 	unsigned int	u32;		/* UTF-32 */
54 	unsigned short	e16;		/* 16-bit EUC */
55 	unsigned char	ic1, ic2, ic3;	/* 1st, 2nd, and 3rd bytes of a char */
56 	size_t		rv = (size_t)0;	/* return value of this function */
57 
58 	unsigned char	*ip;
59         size_t		ileft;
60 	char		*op;
61         size_t		oleft;
62 
63 	/*
64 	 * If inbuf and/or *inbuf are NULL, reset conversion descriptor
65 	 * and put escape sequence if needed.
66 	 */
67 	if ((inbuf == NULL) || (*inbuf == NULL)) {
68 		_icv_reset_unicode(cd);
69 		return ((size_t)0);
70 	}
71 
72 	ip = (unsigned char *)*inbuf;
73 	ileft = *inbytesleft;
74 	op = *outbuf;
75 	oleft = *outbytesleft;
76 
77 	while (ileft != 0) {
78 		NGET(ic1, "never fail here"); /* get 1st byte */
79 
80 		if (ISASC(ic1)) { /* CS0; 1 byte */
81 			u32 = (unsigned int)_jfp_tbl_jisx0201roman_to_ucs2[ic1];
82 			PUTU(u32, "CS0");
83 		} else if (ISCS1(ic1)) { /* JIS X 0213 plane 1; 2 bytes */
84 			NGET(ic2, "CS1-2");
85 			if (ISCS1(ic2)) { /* 2nd byte check passed */
86 				e16 = (ic1 << 8) | ic2;
87 				u32 = (unsigned int)_jfp_tbl_jisx0208_to_ucs2[
88 					(ic1 - 0xa1) * 94 + (ic2 - 0xa1)];
89 				if (IFHISUR(u32)) {
90 					u32 = _jfp_lookup_x0213_nonbmp(
91 						e16, u32);
92 					PUTU(u32, "CS1->NONBMP");
93 				} else if (u32 == 0xffff) {
94 					/* need to compose */
95 					unsigned int	u32_2;
96 					u32 = _jfp_lookup_x0213_compose(
97 						e16, &u32_2);
98 					PUTU(u32, "CS1->CP1");
99 					PUTU(u32_2, "CS1->CP2");
100 				} else {
101 					PUTU(u32, "CS1->BMP");
102 				}
103 			} else { /* 2nd byte check failed */
104 				RETERROR(EILSEQ, "CS1-2")
105 			}
106 		} else if (ic1 == SS2) { /* JIS X 0201 Kana; 2 bytes */
107 			NGET(ic2, "CS2-2");
108 			if (ISCS2(ic2)) { /* 2nd byte check passed */
109 				u32 = (unsigned int)
110 				_jfp_tbl_jisx0201kana_to_ucs2[ic2 - 0xa1];
111 				PUTU(u32, "CS2->Kana");
112 			} else { /* 2nd byte check failed */
113 				RETERROR(EILSEQ, "CS2-2")
114 			}
115 		} else if (ic1 == SS3) { /* JIS X 0213 plane 2; 3 bytes */
116 			NGET(ic2, "CS3-2");
117 			if (ISCS3(ic2)) { /* 2nd byte check passed */
118 				NGET(ic3, "CS3-3");
119 				if (ISCS3(ic3)) { /* 3rd byte check passed */
120 					e16 = (ic2 << 8) | (ic3 & 0x7f);
121 					u32 = (unsigned int)
122 					_jfp_tbl_jisx0213p2_to_ucs2[
123 					(ic2 - 0xa1) * 94 + (ic3 - 0xa1)];
124 					if (IFHISUR(u32)) {
125 						u32 = _jfp_lookup_x0213_nonbmp(
126 						e16, u32);
127 						PUTU(u32, "CS3->NONBMP");
128 					} else {
129 						PUTU(u32, "CS3->BMP");
130 					}
131 				} else { /* 3rd byte check failed */
132 					RETERROR(EILSEQ, "CS3-3")
133 				}
134 			} else { /* 2nd byte check failed */
135 				RETERROR(EILSEQ, "CS3-2")
136 			}
137 		} else if (ISC1CTRLEUC(ic1)) { /* C1 control; 1 byte */
138 			u32 = ic1;
139 			PUTU(u32, "E2BIG C1CTRL");
140 		} else { /* 1st byte check failed */
141 			RETERROR(EILSEQ, "CS?-1")
142 		}
143 
144 		/*
145 		 * One character successfully converted so update
146 		 * values outside of this function's stack.
147 		 */
148 		*inbuf = (char *)ip;
149 		*inbytesleft = ileft;
150 		*outbuf = op;
151 		*outbytesleft = oleft;
152 	}
153 
154 ret:
155 	DEBUGPRINTERROR
156 
157 	/*
158 	 * Return value for successful return is not defined by XPG
159 	 * so return same as *inbytesleft as existing codes do.
160 	 */
161 	return ((rv == (size_t)-1) ? rv : *inbytesleft);
162 }
163