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 #define JFP_ICONV_STATELESS 31 #include "japanese.h" 32 33 static unsigned short lookuptbl(unsigned short); 34 35 void * 36 _icv_open(void) 37 { 38 return (_icv_open_stateless()); 39 } 40 41 void 42 _icv_close(void *cd) 43 { 44 _icv_close_stateless(cd); 45 return; 46 } 47 48 size_t 49 _icv_iconv(void *cd, char **inbuf, size_t *inbytesleft, 50 char **outbuf, size_t *outbytesleft) 51 { 52 int stat; 53 unsigned char *ip, ic, *op; 54 size_t ileft, oleft; 55 size_t retval; 56 57 stat = ST_INIT; 58 59 /* 60 * If inbuf and/or *inbuf are NULL, reset conversion descriptor 61 * and put escape sequence if needed. 62 */ 63 if ((inbuf == NULL) || (*inbuf == NULL)) { 64 /* nothing to do here for this module */ 65 return ((size_t)0); 66 } 67 68 ip = (unsigned char *)*inbuf; 69 op = (unsigned char *)*outbuf; 70 ileft = *inbytesleft; 71 oleft = *outbytesleft; 72 73 /* 74 * Main loop; basically 1 loop per 1 input byte 75 */ 76 77 while ((int)ileft > 0) { 78 GET(ic); 79 if (stat == ST_INCS2) { 80 PUT(ic); 81 stat = ST_INIT; 82 continue; 83 } 84 if (ISASC((int)ic)) { /* ASCII */ 85 if (oleft < SJISW0) { 86 UNGET(); 87 errno = E2BIG; 88 retval = (size_t)ERR_RETURN; 89 goto ret; 90 } 91 PUT(ic); 92 continue; 93 } 94 if (ISCS1(ic)) { /* Kanji starts */ 95 if ((int)ileft > 0) { 96 if (ISCS1(*ip)) { 97 int even_ku; 98 if (oleft < SJISW1) { 99 UNGET(); 100 errno = E2BIG; 101 retval = (size_t)ERR_RETURN; 102 goto ret; 103 } 104 ic &= 0x7f; 105 PUT(jis208tosj1[ic]); 106 if ((ic % 2) == 0) 107 even_ku = TRUE; 108 else 109 even_ku = FALSE; 110 GET(ic); 111 ic &= 0x7f; 112 if (even_ku) 113 ic += 0x80; 114 PUT(jistosj2[ic]); 115 continue; 116 } else { /* 2nd byte is illegal */ 117 UNGET(); 118 errno = EILSEQ; 119 retval = (size_t)ERR_RETURN; 120 goto ret; 121 } 122 } else { /* input fragment of Kanji */ 123 UNGET(); 124 errno = EINVAL; 125 retval = (size_t)ERR_RETURN; 126 goto ret; 127 } 128 } else if (ic == SS2) { /* Kana starts */ 129 if ((int)ileft > 0) { 130 if (ISCS2(*ip)) { 131 if (oleft < SJISW2) { 132 UNGET(); 133 errno = E2BIG; 134 retval = (size_t)ERR_RETURN; 135 goto ret; 136 } 137 stat = ST_INCS2; 138 continue; 139 } else { /* 2nd byte is illegal */ 140 UNGET(); 141 errno = EILSEQ; 142 retval = (size_t)ERR_RETURN; 143 goto ret; 144 } 145 } else { /* input fragment of Kana */ 146 UNGET(); 147 errno = EINVAL; 148 retval = (size_t)ERR_RETURN; 149 goto ret; 150 } 151 } else if (ic == SS3) { /* CS_3 Kanji starts */ 152 unsigned short dest; 153 if (ileft >= EUCW3) { 154 if (ISCS3(*ip) && ISCS3(*(ip + 1))) { 155 if (oleft < SJISW1) { 156 UNGET(); 157 errno = E2BIG; 158 retval = (size_t)ERR_RETURN; 159 goto ret; 160 } 161 if (*ip < 0xf5) { /* check IBM area */ 162 GET(ic); 163 dest = (ic << 8); 164 GET(ic); 165 dest += ic; 166 dest = lookuptbl(dest); 167 if (dest == 0xffff) { 168 /* 169 * Illegal code points 170 * in G3 plane. 171 */ 172 UNGET(); 173 UNGET(); 174 errno = E2BIG; 175 retval = 176 (size_t)ERR_RETURN; 177 goto ret; 178 } else { 179 PUT((dest >> 8) & 180 0xff); 181 PUT(dest & 0xff); 182 } 183 continue; 184 } else { 185 unsigned char c1, c2; 186 187 GET(c1); 188 GET(c2); 189 c1 &= 0x7f; 190 c2 &= 0x7f; 191 if ((c1 % 2) == 0) 192 c2 += 0x80; 193 c1 = jis212tosj1[c1]; 194 c2 = jistosj2[c2]; 195 if ((c1 != 0xff) && 196 (c2 != 0xff)) { 197 PUT(c1); 198 PUT(c2); 199 continue; 200 } 201 PUT((PGETA >> 8) & 0xff); 202 PUT(PGETA & 0xff); 203 continue; 204 } 205 } else { 206 errno = EILSEQ; 207 retval = (size_t)ERR_RETURN; 208 goto ret; 209 } 210 } else { /* input fragment of JISX0212 */ 211 UNGET(); 212 errno = EINVAL; 213 retval = (size_t)ERR_RETURN; 214 goto ret; 215 } 216 } else { 217 UNGET(); 218 errno = EILSEQ; 219 retval = (size_t)ERR_RETURN; 220 goto ret; 221 } 222 } 223 retval = ileft; 224 ret: 225 *inbuf = (char *)ip; 226 *inbytesleft = ileft; 227 *outbuf = (char *)op; 228 *outbytesleft = oleft; 229 230 return (retval); 231 } 232 233 /* 234 * lookuptbl() 235 * Return the index number if its index-ed number 236 * is the same as dest value. 237 */ 238 static unsigned short 239 lookuptbl(unsigned short dest) 240 { 241 unsigned short tmp; 242 int i; 243 int sz = (sizeof (sjtoibmext) / sizeof (sjtoibmext[0])); 244 245 for (i = 0; i < sz; i++) { 246 tmp = sjtoibmext[i]; 247 if (tmp == dest) 248 return ((i + 0xfa40 + ((i / 0xc0) * 0x40))); 249 } 250 return (PGETA); 251 } 252