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 34 void * 35 _icv_open(void) 36 { 37 return (_icv_open_stateless()); 38 } 39 40 void 41 _icv_close(void *cd) 42 { 43 _icv_close_stateless(cd); 44 return; 45 } 46 47 size_t 48 _icv_iconv(void *cd, char **inbuf, size_t *inbytesleft, 49 char **outbuf, size_t *outbytesleft) 50 { 51 int stat; 52 unsigned char *ip, ic, *op; 53 size_t ileft, oleft; 54 size_t retval; 55 56 /* 57 * If inbuf and/or *inbuf are NULL, reset conversion descriptor 58 * and put escape sequence if needed. 59 */ 60 if ((inbuf == NULL) || (*inbuf == NULL)) { 61 /* nothing to do here for this module */ 62 return ((size_t)0); 63 } 64 65 stat = ST_INIT; 66 67 ip = (unsigned char *)*inbuf; 68 op = (unsigned char *)*outbuf; 69 ileft = *inbytesleft; 70 oleft = *outbytesleft; 71 72 /* 73 * Main loop; basically 1 loop per 1 input byte 74 */ 75 76 while ((int)ileft > 0) { 77 GET(ic); 78 if ((stat == ST_INCS1) || (stat == ST_INCS3)) { 79 ic = sjtojis2[ic]; 80 PUT(ic | CMSB); 81 stat = ST_INIT; 82 continue; 83 } else if (ISASC((int)ic)) { /* ASCII */ 84 CHECK2BIG(EUCW0,1); 85 PUT(ic); 86 continue; 87 } else if (ISSJKANA(ic)) { /* kana start */ 88 CHECK2BIG((SS2W + EUCW2),1); 89 PUT(SS2); 90 PUT(ic); 91 continue; 92 } else if (ISSJKANJI1(ic)) { /* CS_1 kanji starts */ 93 if ((int)ileft > 0) { 94 if (ISSJKANJI2(*ip)) { 95 CHECK2BIG(EUCW1,1); 96 stat = ST_INCS1; 97 ic = sjtojis1[(ic - 0x80)]; 98 if (*ip >= 0x9f) { 99 ic++; 100 } 101 PUT(ic | CMSB); 102 continue; 103 } else { /* 2nd byte is illegal */ 104 UNGET(); 105 errno = EILSEQ; 106 retval = (size_t)ERR_RETURN; 107 goto ret; 108 } 109 } else { /* input fragment of Kanji */ 110 UNGET(); 111 errno = EINVAL; 112 retval = (size_t)ERR_RETURN; 113 goto ret; 114 } 115 } else if (ISSJSUPKANJI1(ic)) { /* CS_3 kanji starts */ 116 if ((int)ileft > 0) { 117 if (ISSJKANJI2(*ip)) { 118 CHECK2BIG((SS3W + EUCW3),1); 119 stat = ST_INCS3; 120 ic = sjtojis1[(ic - 0x80)]; 121 if (*ip >= 0x9f) { 122 ic++; 123 } 124 PUT(SS3); 125 PUT(ic | CMSB); 126 continue; 127 } else { /* 2nd byte is illegal */ 128 UNGET(); 129 errno = EILSEQ; 130 retval = (size_t)ERR_RETURN; 131 goto ret; 132 } 133 } else { /* input fragment of Kanji */ 134 UNGET(); 135 errno = EINVAL; 136 retval = (size_t)ERR_RETURN; 137 goto ret; 138 } 139 } else if (ISSJIBM(ic) || /* Extended IBM char. area */ 140 ISSJNECIBM(ic)) { /* NEC/IBM char. area */ 141 /* 142 * We need a special treatment for each codes. 143 * By adding some offset number for them, we 144 * can process them as the same way of that of 145 * extended IBM chars. 146 */ 147 if ((int)ileft > 0) { 148 if (ISSJKANJI2(*ip)) { 149 unsigned short dest; 150 dest = (ic << 8); 151 GET(ic); 152 dest += ic; 153 if ((0xed40 <= dest) && 154 (dest <= 0xeffc)) { 155 REMAP_NEC(dest); 156 if (dest == 0xffff) { 157 goto ill_ibm; 158 } 159 } 160 if ((dest == 0xfa54) || 161 (dest == 0xfa5b)) { 162 CHECK2BIG(EUCW1,2); 163 if (dest == 0xfa54) { 164 PUT(0xa2); 165 PUT(0xcc); 166 } else { 167 PUT(0xa2); 168 PUT(0xe8); 169 } 170 continue; 171 } 172 CHECK2BIG((SS3W + EUCW3),2); 173 dest = dest - 0xfa40 - 174 (((dest>>8) - 0xfa) * 0x40); 175 dest = sjtoibmext[dest]; 176 if (dest == 0xffff) { 177 /* 178 * Illegal code points 179 * in IBM-EXT area. 180 */ 181 ill_ibm: 182 UNGET(); 183 UNGET(); 184 errno = EILSEQ; 185 retval = (size_t)ERR_RETURN; 186 goto ret; 187 } 188 PUT(SS3); 189 PUT((dest>>8) & 0xff); 190 PUT(dest & 0xff); 191 continue; 192 } else { /* 2nd byte is illegal */ 193 UNGET(); 194 errno = EILSEQ; 195 retval = (size_t)ERR_RETURN; 196 goto ret; 197 } 198 } else { /* input fragment of Kanji */ 199 UNGET(); 200 errno = EINVAL; 201 retval = (size_t)ERR_RETURN; 202 goto ret; 203 } 204 } else if ((0xeb <= ic) && (ic <= 0xec)) { 205 /* 206 * Based on the draft convention of OSF-JVC CDEWG, 207 * characters in this area will be mapped to 208 * "CHIKAN-MOJI." (convertible character) 209 * So far, we'll use (0x222e) for it. 210 */ 211 if ((int)ileft > 0) { 212 if (ISSJKANJI2(*ip)) { 213 CHECK2BIG(EUCW1,1); 214 GET(ic); /* Dummy */ 215 PUT((EGETA>>8) & 0xff); 216 PUT(EGETA & 0xff); 217 continue; 218 } else { /* 2nd byte is illegal */ 219 UNGET(); 220 errno = EILSEQ; 221 retval = (size_t)ERR_RETURN; 222 goto ret; 223 } 224 } else { /* input fragment of Kanji */ 225 UNGET(); 226 errno = EINVAL; 227 retval = (size_t)ERR_RETURN; 228 goto ret; 229 } 230 } else { /* 1st byte is illegal */ 231 UNGET(); 232 errno = EILSEQ; 233 retval = (size_t)ERR_RETURN; 234 goto ret; 235 } 236 } 237 retval = ileft; 238 ret: 239 *inbuf = (char *)ip; 240 *inbytesleft = ileft; 241 *outbuf = (char *)op; 242 *outbytesleft = oleft; 243 244 return (retval); 245 } 246