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 1994-2003 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <errno.h> 29 #include <euc.h> 30 #include "japanese.h" 31 32 /* 33 * struct _icv_state; to keep stat 34 */ 35 struct _icv_state { 36 int _st_cset; 37 }; 38 39 void * 40 _icv_open() 41 { 42 struct _icv_state *st; 43 44 if ((st = (struct _icv_state *)malloc(sizeof (struct _icv_state))) 45 == NULL) 46 return ((void *)ERR_RETURN); 47 48 st->_st_cset = CS_0; 49 return (st); 50 } 51 52 void 53 _icv_close(struct _icv_state *st) 54 { 55 free(st); 56 } 57 58 size_t 59 _icv_iconv(struct _icv_state *st, char **inbuf, size_t *inbytesleft, 60 char **outbuf, size_t *outbytesleft) 61 { 62 int cset, stat; 63 unsigned char *ip, ic; 64 char *op; 65 size_t ileft, oleft; 66 size_t retval; 67 68 stat = ST_INIT; 69 70 /* 71 * If inbuf and/or *inbuf are NULL, reset conversion descriptor 72 * and put escape sequence if needed. 73 */ 74 if ((inbuf == NULL) || (*inbuf == NULL)) { 75 if ((st->_st_cset == CS_1) || (st->_st_cset == CS_3)) { 76 if ((outbuf != NULL) && (*outbuf != NULL) 77 && (outbytesleft != NULL)) { 78 op = (char *)*outbuf; 79 oleft = *outbytesleft; 80 if (oleft < SEQ_SBTOG0) { 81 errno = E2BIG; 82 return ((size_t)-1); 83 } 84 PUT(ESC); 85 PUT(SBTOG0_1); 86 PUT(F_X0201_RM); 87 *outbuf = (char *)op; 88 *outbytesleft = oleft; 89 } 90 st->_st_cset = CS_0; 91 } else if (st->_st_cset == CS_2) { 92 if ((outbuf != NULL) && (*outbuf != NULL) 93 && (outbytesleft != NULL)) { 94 op = (char *)*outbuf; 95 oleft = *outbytesleft; 96 if (oleft < SEQ_SOSI) { 97 errno = E2BIG; 98 return ((size_t)-1); 99 } 100 PUT(SI); 101 *outbuf = (char *)op; 102 *outbytesleft = oleft; 103 } 104 st->_st_cset = CS_0; 105 } 106 return ((size_t)0); 107 } 108 109 cset = st->_st_cset; 110 111 ip = (unsigned char *)*inbuf; 112 op = *outbuf; 113 ileft = *inbytesleft; 114 oleft = *outbytesleft; 115 116 /* 117 * Main loop; basically 1 loop per 1 input byte 118 */ 119 120 while ((int)ileft > 0) { 121 GET(ic); 122 if (stat == ST_INCS2) { 123 PUT(ic & CMASK); 124 stat = ST_INIT; 125 continue; 126 } else if (stat == ST_INCS1) { 127 PUT(ic & CMASK); 128 stat = ST_INIT; 129 continue; 130 } else if (stat == ST_INCS3) { 131 PUT(ic & CMASK); 132 GET(ic); 133 PUT(ic & CMASK); 134 stat = ST_INIT; 135 continue; 136 } 137 if (ISASC((int)ic)) { /* ASCII */ 138 if ((cset == CS_1) || (cset == CS_3)) { 139 if (oleft < SEQ_SBTOG0) { 140 UNGET(); 141 errno = E2BIG; 142 retval = (size_t)ERR_RETURN; 143 goto ret; 144 } 145 PUT(ESC); /* Kanji Out */ 146 PUT(SBTOG0_1); 147 PUT(F_X0201_RM); 148 } else if (cset == CS_2) { 149 if (oleft < SEQ_SOSI) { 150 UNGET(); 151 errno = E2BIG; 152 retval = (size_t)ERR_RETURN; 153 goto ret; 154 } 155 PUT(SI); /* Shift In */ 156 } 157 cset = CS_0; 158 if (oleft < JISW0) { 159 UNGET(); 160 errno = E2BIG; 161 retval = (size_t)ERR_RETURN; 162 goto ret; 163 } 164 PUT(ic); 165 continue; 166 } else if (ISCS1(ic)) { 167 if ((int)ileft > 0) { /* Kanj starts */ 168 if (ISCS1(*ip)) { 169 if (cset == CS_2) { 170 if (oleft < SEQ_SOSI) { 171 UNGET(); 172 errno = E2BIG; 173 retval = 174 (size_t)ERR_RETURN; 175 goto ret; 176 } 177 cset = CS_0; 178 PUT(SI); 179 } 180 if (cset != CS_1) { 181 if (oleft < SEQ_MBTOG0_O) { 182 UNGET(); 183 errno = E2BIG; 184 retval = 185 (size_t)ERR_RETURN; 186 goto ret; 187 } 188 cset = CS_1; 189 PUT(ESC); 190 PUT(MBTOG0_1); 191 PUT(F_X0208_83_90); 192 } 193 if (oleft < JISW1) { 194 UNGET(); 195 errno = E2BIG; 196 retval = (size_t)ERR_RETURN; 197 goto ret; 198 } 199 stat = ST_INCS1; 200 PUT(ic & CMASK); 201 continue; 202 } else { /* 2nd byte is illegal */ 203 errno = EILSEQ; 204 retval = (size_t)ERR_RETURN; 205 goto ret; 206 } 207 } else { /* input fragment of Kanji */ 208 UNGET(); 209 errno = EINVAL; 210 retval = (size_t)ERR_RETURN; 211 goto ret; 212 } 213 } else if (ic == SS2) { /* Kana starts */ 214 if ((int)ileft > 0) { 215 if (ISCS2(*ip)) { 216 if ((cset == CS_1) || (cset == CS_3)) { 217 if (oleft < SEQ_SBTOG0) { 218 UNGET(); 219 errno = E2BIG; 220 retval = 221 (size_t)ERR_RETURN; 222 goto ret; 223 } 224 cset = CS_0; 225 PUT(ESC); 226 PUT(SBTOG0_1); 227 PUT(F_X0201_RM); 228 } 229 if (cset != CS_2) { 230 if (oleft < SEQ_SOSI) { 231 UNGET(); 232 errno = E2BIG; 233 retval = 234 (size_t)ERR_RETURN; 235 goto ret; 236 } 237 cset = CS_2; 238 PUT(SO); 239 } 240 if (oleft < JISW2) { 241 UNGET(); 242 errno = E2BIG; 243 retval = (size_t)ERR_RETURN; 244 goto ret; 245 } 246 stat = ST_INCS2; 247 continue; 248 } else { /* 2nd byte is illegal */ 249 errno = EILSEQ; 250 retval = (size_t)ERR_RETURN; 251 goto ret; 252 } 253 } else { /* input fragment of Kana */ 254 UNGET(); 255 errno = EINVAL; 256 retval = (size_t)ERR_RETURN; 257 goto ret; 258 } 259 } else if (ic == SS3) { /* JISX0212 starts */ 260 if (ileft >= EUCW3) { 261 if (ISCS3(*ip) && ISCS3(*(ip + 1))) { 262 if (cset == CS_2) { 263 if (oleft < SEQ_SOSI) { 264 UNGET(); 265 errno = E2BIG; 266 retval = 267 (size_t)ERR_RETURN; 268 goto ret; 269 } 270 cset = CS_0; 271 PUT(SI); 272 } 273 if (cset != CS_3) { 274 if (oleft < SEQ_MBTOG0) { 275 UNGET(); 276 errno = E2BIG; 277 retval = 278 (size_t)ERR_RETURN; 279 goto ret; 280 } 281 cset = CS_3; 282 PUT(ESC); 283 PUT(MBTOG0_1); 284 PUT(MBTOG0_2); 285 PUT(F_X0212_90); 286 } 287 if (oleft < JISW3) { 288 UNGET(); 289 errno = E2BIG; 290 retval = (size_t)ERR_RETURN; 291 goto ret; 292 } 293 stat = ST_INCS3; 294 continue; 295 } else { 296 errno = EILSEQ; 297 retval = (size_t)ERR_RETURN; 298 goto ret; 299 } 300 } else { /* input fragment of JISX0212 */ 301 UNGET(); 302 errno = EINVAL; 303 retval = (size_t)ERR_RETURN; 304 goto ret; 305 } 306 } else { 307 UNGET(); 308 errno = EILSEQ; 309 retval = (size_t)ERR_RETURN; 310 goto ret; 311 } 312 } 313 retval = ileft; 314 ret: 315 *inbuf = (char *)ip; 316 *inbytesleft = ileft; 317 *outbuf = op; 318 *outbytesleft = oleft; 319 st->_st_cset = cset; 320 321 return (retval); 322 } 323