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 (c) 1994 by Sun Microsystems, Inc. 23 */ 24 25 26 #include <stdlib.h> 27 #include <errno.h> 28 #include "ktable.h" 29 #include "utf_iso2022.h" 30 31 32 /**** _ I C V _ O P E N ****/ 33 34 void* _icv_open() 35 { 36 _conv_desc* cd = (_conv_desc*)malloc(sizeof(_conv_desc)); 37 38 if (cd == (_conv_desc*)NULL) 39 { 40 errno = ENOMEM; 41 return((void*)-1); 42 } 43 44 RESET_CONV_DESC(); 45 cd->designated = 0; 46 cd->state = ASCII; 47 48 return((void*)cd); 49 } /* end of int _icv_open(). */ 50 51 52 /**** _ I C V _ C L O S E ****/ 53 54 void _icv_close(_conv_desc* cd) 55 { 56 if (!cd) 57 errno = EBADF; 58 else 59 free((void*)cd); 60 } /* end of void _icv_close(_conv_desc*). */ 61 62 63 /**** _ I C V _ I C O N V ****/ 64 65 size_t _icv_iconv(_conv_desc* cd, char** inbuf, size_t* inbufleft, 66 char** outbuf, size_t* outbufleft) 67 { 68 extern unsigned short _johap_to_wansung(unsigned short, unsigned short, 69 unsigned short); 70 size_t ret_val = 0; 71 unsigned char* ib; 72 unsigned char* ob; 73 unsigned char* ibtail; 74 unsigned char* obtail; 75 76 if (!cd) 77 { 78 errno = EBADF; 79 return((size_t)-1); 80 } 81 82 /* To keep up with libc.so's iconv(), inbufleft checkings are added. */ 83 if (!inbuf || !(*inbuf) || !inbufleft || !(*inbufleft)) 84 { 85 if (cd->state == WANSUNG && outbufleft && *outbufleft >= 1 && 86 outbuf && *outbuf) 87 { 88 **outbuf = SI; 89 (*outbuf)++; 90 (*outbufleft)--; 91 } 92 else 93 { 94 errno = E2BIG; 95 return((size_t)-1); 96 } 97 98 RESET_CONV_DESC(); 99 cd->designated = 0; 100 cd->state = ASCII; 101 return((size_t)0); 102 } 103 104 ib = (unsigned char*)*inbuf; 105 ob = (unsigned char*)*outbuf; 106 ibtail = ib + *inbufleft; 107 obtail = ob + *outbufleft; 108 109 while (ib < ibtail) 110 { 111 if (!(*ib & 0x80)) /* 7 bits */ 112 { 113 PROCESS_PRIOR_CVC(); 114 115 if ((obtail - ob) < (cd->state == WANSUNG ? 2 : 1)) 116 { 117 errno = E2BIG; 118 ret_val = (size_t)-1; 119 break; 120 } 121 if (cd->state == WANSUNG) 122 { 123 *ob++ = SI; 124 cd->state = ASCII; 125 } 126 *ob++ = *ib++; 127 } 128 else if ((*ib & 0xF0) == 0xE0) /* 16 bits */ 129 { 130 unsigned long u; 131 132 if ((ibtail - ib) < 3) 133 { 134 errno = EINVAL; 135 ret_val = (size_t)-1; 136 break; 137 } 138 139 u = ((unsigned long)(*ib) << 16) | 140 ((unsigned long)(*(ib + 1)) << 8) | 141 (unsigned long)(*(ib + 2)); 142 if (u == 0xE1859F || 143 (u >= 0xE18480 && u <= 0xE18492)) /* Ci */ 144 { 145 PROCESS_PRIOR_CVC(); 146 147 cd->ci = (u == 0xE1859F) ? CVC_FILL 148 : u - 0xE18480; 149 cd->prev_state = CI; 150 } 151 else if (u == 0xE185A0 || 152 (u >= 0xE185A1 && u <= 0xE185B5)) /* V */ 153 { 154 if (cd->prev_state != E && cd->prev_state != CI) 155 PROCESS_PRIOR_CVC(); 156 157 cd->v = (u == 0xE185A0) ? CVC_FILL 158 : u - 0xE185A1; 159 cd->prev_state = V; 160 } 161 else if ((u >= 0xE186A8 && u <= 0xE186BF) || 162 (u >= 0xE18780 && u <= 0xE18782)) /* Cf */ 163 { 164 if (cd->prev_state != E && cd->prev_state != V) 165 PROCESS_PRIOR_CVC(); 166 167 cd->cf = u - ((u >= 0xE18780) ? 0xE18766 168 : 0xE186A6); 169 cd->prev_state = CF; 170 171 PROCESS_PRIOR_CVC(); 172 } 173 else if (u >= 0xE082A1 && u <= 0xEFBFA6) 174 { 175 register int h, i, j, l; 176 short num; 177 178 PROCESS_PRIOR_CVC(); 179 180 num = (cd->designated) ? 181 (cd->state == ASCII ? 3 : 2) : 182 (cd->state == ASCII ? 7 : 6); 183 if ((obtail - ob) < num) 184 { 185 errno = E2BIG; 186 ret_val = (size_t)-1; 187 break; 188 } 189 190 for (l = 0, h = MAX_U2ISO2022_NUM; l < h; ) 191 { 192 i = (l + h) / 2; 193 if (utf82iso2022_tbl[i].utf8 == u) 194 break; 195 else if (utf82iso2022_tbl[l].utf8 == u) 196 { 197 i = l; 198 break; 199 } 200 else if (utf82iso2022_tbl[h].utf8 == u) 201 { 202 i = h; 203 break; 204 } 205 else if (utf82iso2022_tbl[i].utf8 < u) 206 l = i + 1; 207 else 208 h = i - 1; 209 } 210 211 if (utf82iso2022_tbl[i].utf8 != u) 212 { 213 /* Let's assume the code is non- 214 * identical. */ 215 if (cd->designated && 216 cd->state == WANSUNG) 217 { 218 if (ob >= obtail) 219 { 220 errno = E2BIG; 221 ret_val = (size_t)-1; 222 break; 223 } 224 *ob++ = SI; 225 cd->state = ASCII; 226 } 227 *ob++ = NON_IDENTICAL; 228 *ob++ = NON_IDENTICAL; 229 ret_val += 2; 230 } 231 else 232 { 233 if (!cd->designated) 234 { 235 *ob++ = ESC; 236 *ob++ = '$'; 237 *ob++ = ')'; 238 *ob++ = 'C'; 239 cd->designated = 1; 240 } 241 if (cd->state == ASCII) 242 { 243 *ob++ = SO; 244 cd->state = WANSUNG; 245 } 246 *ob++ = (char) 247 ((utf82iso2022_tbl[i].code >> 8) 248 & 0x7F); 249 *ob++ = (char)(utf82iso2022_tbl[i].code 250 & 0x7F); 251 } 252 } 253 else 254 { 255 PROCESS_PRIOR_CVC(); 256 257 /* Let's assume the code is non-identical. */ 258 if ((obtail - ob) < 2) 259 { 260 errno = E2BIG; 261 ret_val = (size_t)-1; 262 break; 263 } 264 *ob++ = NON_IDENTICAL; 265 *ob++ = NON_IDENTICAL; 266 ret_val += 2; 267 } 268 ib += 3; 269 } 270 else /* 11, 21, 26 & 31 bits codes won't be able to convert. */ 271 { 272 short int offset; 273 274 PROCESS_PRIOR_CVC(); 275 276 if ((*ib & 0xE0) == 0xC0) /* 11 */ 277 offset = 2; 278 else if ((*ib & 0xF0) == 0xE0) /* 16 */ 279 offset = 3; 280 else if ((*ib & 0xF8) == 0xF0) /* 21 */ 281 offset = 4; 282 else if ((*ib & 0xFC) == 0xF8) /* 26 */ 283 offset = 5; 284 else if ((*ib & 0xFE) == 0xFC) /* 31 */ 285 offset = 6; 286 else /* Illegal sequence. */ 287 offset = 1; 288 289 if ((ibtail - ib) < offset) 290 { 291 errno = EINVAL; 292 ret_val = (size_t)-1; 293 break; 294 } 295 ib += offset; 296 297 /* Let's assume the code is non-identical. */ 298 offset = (offset > 2) ? 2 : 1; 299 if ((obtail - ob) < offset) 300 { 301 errno = E2BIG; 302 ret_val = (size_t)-1; 303 break; 304 } 305 *ob++ = NON_IDENTICAL; 306 if (offset > 1) 307 *ob++ = NON_IDENTICAL; 308 ret_val += offset; 309 } 310 } 311 312 *inbuf = (char*)ib; 313 *inbufleft = ibtail - ib; 314 *outbuf = (char*)ob; 315 *outbufleft = obtail - ob; 316 317 return(ret_val); 318 } /* end of size_t _icv_iconv(_conv_desc*, char**, size_t*, char**, size_t*).*/ 319