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 
31 #include "japanese.h"
32 #include "jfp_iconv_unicode.h"
33 
34 #define	JFP_U2E_ICONV_X0213
35 #include "jfp_ucs2_to_euc16.h"
36 
37 #define	DEF_SINGLE	'?'
38 
39 #define	CS0_SEQ2	0x28	/* ( */
40 #define	CS0_SEQ3	0x42	/* B */
41 
42 #define	CS1_SEQ2	0x24	/* $ */
43 #define	CS1_SEQ3	0x28	/* ( */
44 #define	CS1_SEQ4	0x51	/* Q */
45 
46 #define	CS3_SEQ2	0x24	/* $ */
47 #define	CS3_SEQ3	0x28	/* ( */
48 #define	CS3_SEQ4	0x50	/* P */
49 
50 struct _icv_state {
51 	int	_st_cset;
52 };
53 
54 void *
_icv_open(void)55 _icv_open(void)
56 {
57 	void			*cd;
58 	struct _icv_state	*st;
59 
60 	cd = _icv_open_unicode(sizeof (struct _icv_state));
61 
62 	if (cd != NULL) {
63 		st = (struct _icv_state *)(_icv_get_ext(cd));
64 		st->_st_cset = CS_0;
65 	}
66 
67 	return (cd);
68 }
69 
70 void
_icv_close(void * cd)71 _icv_close(void *cd)
72 {
73 	_icv_close_unicode(cd);
74 	return;
75 }
76 
77 size_t
_icv_iconv(void * cd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)78 _icv_iconv(void *cd, char **inbuf, size_t *inbytesleft,
79 				char **outbuf, size_t *outbytesleft)
80 {
81 	unsigned int	u32;		/* UTF-32 */
82 	unsigned short	e16;		/* 16-bit EUC */
83 	unsigned char	ic;
84 	size_t		rv = (size_t)0;
85 
86 	struct _icv_state	*st = (struct _icv_state *)(_icv_get_ext(cd));
87 	int			cset;
88 
89 	unsigned char	*ip;
90         size_t		ileft;
91 	char		*op;
92         size_t		oleft;
93 
94 	/*
95 	 * If inbuf and/or *inbuf are NULL, reset conversion descriptor
96 	 * and put escape sequence if needed.
97 	 */
98 	if ((inbuf == NULL) || (*inbuf == NULL)) {
99 		if (st->_st_cset != CS_0) {
100 			if ((outbuf != NULL) && (*outbuf != NULL)
101 					&& (outbytesleft != NULL)) {
102 				op = (char *)*outbuf;
103 				oleft = *outbytesleft;
104 				NPUT(ESC, "RESET-SEQ-ESC");
105 				NPUT(CS0_SEQ2, "RESET-SEQ2");
106 				NPUT(CS0_SEQ3, "RESET-SEQ3");
107 				*outbuf = (char *)op;
108 				*outbytesleft = oleft;
109 			}
110 			st->_st_cset = CS_0;
111 			_icv_reset_unicode(cd);
112 		}
113 		return ((size_t)0);
114 	}
115 
116 	cset = st->_st_cset;
117 
118 	ip = (unsigned char *)*inbuf;
119 	ileft = *inbytesleft;
120 	op = *outbuf;
121 	oleft = *outbytesleft;
122 
123 	while (ileft != 0) {
124 		GETU(&u32)
125 
126 		e16 = _jfp_u32_to_euc16(u32);
127 
128 		switch (e16 & 0x8080) {
129 		case 0x0000:	/* CS0 */
130 			if (cset != CS_0) {
131 				NPUT(ESC, "CS0-SEQ-ESC");
132 				NPUT(CS0_SEQ2, "CS0-SEQ2");
133 				NPUT(CS0_SEQ3, "CS0-SEQ3");
134 				cset = CS_0;
135 			}
136 			ic = (unsigned char)e16;
137 			NPUT(ic, "CS0");
138 			break;
139 		case 0x8080:	/* CS1 */
140 			if (cset != CS_1) {
141 				NPUT(ESC, "CS1-SEQ-ESC");
142 				NPUT(CS1_SEQ2, "CS1-SEQ2");
143 				NPUT(CS1_SEQ3, "CS1-SEQ3");
144 				NPUT(CS1_SEQ4, "CS1-SEQ4");
145 				cset = CS_1;
146 			}
147 			ic = (unsigned char)((e16 >> 8) & 0x7f);
148 			NPUT(ic, "CS1-1");
149 			ic = (unsigned char)(e16 & 0x7f);
150 			NPUT(ic, "CS1-2");
151 			break;
152 		case 0x0080:	/* CS2 */
153 			if (cset != CS_0) {
154 				NPUT(ESC, "CS2-REPL-SEQ-ESC");
155 				NPUT(CS0_SEQ2, "CS2-REPL-SEQ2");
156 				NPUT(CS0_SEQ3, "CS2-REPL-SEQ3");
157 				cset = CS_0;
158 			}
159 			ic = DEF_SINGLE;
160 			NPUT(ic, "CS2-REPL");
161 			break;
162 		case 0x8000:	/* CS3 */
163 			if (cset != CS_3) {
164 				NPUT(ESC, "CS3-SEQ-ESC");
165 				NPUT(CS3_SEQ2, "CS3-SEQ2");
166 				NPUT(CS3_SEQ3, "CS3-SEQ3");
167 				NPUT(CS3_SEQ4, "CS3-SEQ4");
168 				cset = CS_3;
169 			}
170 			ic = (unsigned char)((e16 >> 8) & 0x7f);
171 			NPUT(ic, "CS3-1");
172 			ic = (unsigned char)(e16 & 0x7f);
173 			NPUT(ic, "CS3-2");
174 			break;
175 		}
176 
177 next:
178 		/*
179 		 * One character successfully converted so update
180 		 * values outside of this function's stack.
181 		 */
182 		*inbuf = (char *)ip;
183 		*inbytesleft = ileft;
184 		*outbuf = op;
185 		*outbytesleft = oleft;
186 
187 		st->_st_cset = cset;
188 	}
189 
190 ret:
191 
192 	DEBUGPRINTERROR
193 
194 	/*
195 	 * Return value for successful return is not defined by XPG
196 	 * so return same as *inbytesleft as existing codes do.
197 	 */
198 	return ((rv == (size_t)-1) ? rv : *inbytesleft);
199 }
200