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 struct _icv_state {
37 int _st_cset;
38 };
39
40 void *
_icv_open(void)41 _icv_open(void)
42 {
43 void *cd;
44 struct _icv_state *st;
45
46 cd = _icv_open_unicode(sizeof (struct _icv_state));
47
48 if (cd != NULL) {
49 st = (struct _icv_state *)(_icv_get_ext(cd));
50 st->_st_cset = CS_0;
51 }
52
53 return (cd);
54 }
55
56 void
_icv_close(void * cd)57 _icv_close(void *cd)
58 {
59 _icv_close_unicode(cd);
60 return;
61 }
62
63 size_t
_icv_iconv(void * cd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)64 _icv_iconv(void *cd, char **inbuf, size_t *inbytesleft,
65 char **outbuf, size_t *outbytesleft)
66 {
67 unsigned int u32; /* UTF-32 */
68 unsigned short e16; /* 16-bit EUC */
69 unsigned char ic1, ic2; /* bytes in a char or an esc seq */
70 unsigned char ic3, ic4; /* bytes in an esc seq */
71 size_t rv = (size_t)0; /* return value of this function */
72 struct _icv_state *st;
73
74 unsigned char *ip;
75 size_t ileft;
76 char *op;
77 size_t oleft;
78
79 st = (struct _icv_state *)(_icv_get_ext(cd));
80
81 /*
82 * If inbuf and/or *inbuf are NULL, reset conversion descriptor
83 * and put escape sequence if needed.
84 */
85 if ((inbuf == NULL) || (*inbuf == NULL)) {
86 st->_st_cset = CS_0;
87 _icv_reset_unicode(cd);
88 return ((size_t)0);
89 }
90
91 ip = (unsigned char *)*inbuf;
92 ileft = *inbytesleft;
93 op = *outbuf;
94 oleft = *outbytesleft;
95
96 while (ileft != 0) {
97 NGET(ic1, "never fail here"); /* get 1st byte */
98
99 if (ic1 == ESC) { /* Escape */
100 NGET(ic2, "ESC-2");
101 switch (ic2) {
102 case 0x24: /* $ */
103 NGET(ic3, "ESC$-3");
104 switch (ic3) {
105 case 0x28: /* $( */
106 NGET(ic4, "ESC$(-4");
107 switch (ic4) {
108 case 0x4f: /* 24-28-4F ESC$(O */
109 st->_st_cset = CS_1;
110 break;
111 case 0x50: /* 24-28-50 ESC$(P */
112 st->_st_cset = CS_3;
113 break;
114 case 0x51: /* 24-28-51 ESC$(Q */
115 st->_st_cset = CS_1;
116 break;
117 default:
118 RETERROR(EILSEQ,
119 "Unknown ESC$(?");
120 }
121 break;
122 case 0x42: /* 24-42 ESC$B */
123 st->_st_cset = CS_1;
124 break;
125 default:
126 RETERROR(EILSEQ, "Unknown ESC$?");
127 }
128 break;
129 case 0x28: /* ( */
130 NGET(ic3, "ESC(-3");
131 switch (ic3) {
132 case 0x42: /* 28-42 ESC(B */
133 st->_st_cset = CS_0;
134 break;
135 default:
136 RETERROR(EILSEQ, "Unknown ESC(?");
137 }
138 break;
139 default:
140 RETERROR(EILSEQ, "Unknown ESC?");
141 }
142 } else if (st->_st_cset == CS_0) { /* IRV */
143 if ((ic1 == 0x0e) || (ic1 == 0x0f) || (ic1 > 0x7f)) {
144 RETERROR(EILSEQ, "IRV-1")
145 }
146 u32 = (unsigned int)_jfp_tbl_jisx0201roman_to_ucs2[ic1];
147 PUTU(u32, "IRV");
148 } else if (st->_st_cset == CS_1) { /* Plane 1 */
149 if ((ic1 < 0x21) || (ic1 > 0x7e)) {
150 RETERROR(EILSEQ, "PLANE1-1")
151 }
152 NGET(ic2, "PLANE1-2");
153 if ((ic2 < 0x21) || (ic2 > 0x7e)) {
154 RETERROR(EILSEQ, "PLANE1-2")
155 }
156 e16 = ((ic1 << 8) | ic2) | 0x8080;
157 u32 = (unsigned int)_jfp_tbl_jisx0208_to_ucs2[
158 (ic1 - 0x21) * 94 + (ic2 - 0x21)];
159 if (IFHISUR(u32)) {
160 u32 = _jfp_lookup_x0213_nonbmp(e16, u32);
161 PUTU(u32, "PLANE1->NONBMP");
162 } else if (u32 == 0xffff) {
163 /* need to compose */
164 unsigned int u32_2;
165 u32 = _jfp_lookup_x0213_compose(e16, &u32_2);
166 PUTU(u32, "PLANE1->CP1");
167 PUTU(u32_2, "PLANE1->CP2");
168 } else {
169 PUTU(u32, "PLANE1->BMP");
170 }
171 } else if (st->_st_cset == CS_3) { /* Plane 2 */
172 if ((ic1 < 0x21) || (ic1 > 0x7e)) {
173 RETERROR(EILSEQ, "PLANE2-1")
174 }
175 NGET(ic2, "PLANE2-2");
176 if ((ic2 < 0x21) || (ic2 > 0x7e)) {
177 RETERROR(EILSEQ, "PLANE2-2")
178 }
179 e16 = ((ic1 << 8) | ic2) | 0x8000;
180 u32 = (unsigned int)_jfp_tbl_jisx0213p2_to_ucs2[
181 (ic1 - 0x21) * 94 + (ic2 - 0x21)];
182 if (IFHISUR(u32)) {
183 u32 = _jfp_lookup_x0213_nonbmp(e16, u32);
184 PUTU(u32, "PLANE2->NONBMP");
185 } else {
186 PUTU(u32, "PLANE2->BMP");
187 }
188 }
189
190 /*
191 * One character successfully converted so update
192 * values outside of this function's stack.
193 */
194 *inbuf = (char *)ip;
195 *inbytesleft = ileft;
196 *outbuf = op;
197 *outbytesleft = oleft;
198 }
199
200 ret:
201 DEBUGPRINTERROR
202
203 /*
204 * Return value for successful return is not defined by XPG
205 * so return same as *inbytesleft as existing codes do.
206 */
207 return ((rv == (size_t)-1) ? rv : *inbytesleft);
208 }
209