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) 1995 by Sun Microsystems, Inc. 23 * All Rights Reserved. 24 */ 25 26 27 #include <stdio.h> 28 #include <libintl.h> 29 #include <stdlib.h> 30 #include <errno.h> 31 #include "ktable.h" 32 #include "hangulcode.h" 33 34 #define MSB 0x80 35 #define MSB_OFF 0x7f 36 37 struct _cv_state { 38 int _st_status; 39 int _gstate; 40 }; 41 42 enum _GSTATE { _nostate, _g0, _g1}; 43 44 enum SHIFT_STAT {SHIFT_IN, SHIFT_OUT}; 45 46 47 typedef struct __conv_desc { 48 char designated; 49 enum { ASCII, WANSUNG } state; 50 } _conv_desc; 51 52 53 /**** _ I C V _ O P E N ****/ 54 55 void* _icv_open() 56 { 57 _conv_desc* cd = (_conv_desc*)malloc(sizeof(_conv_desc)); 58 59 if (cd == (_conv_desc*)NULL) 60 { 61 errno = ENOMEM; 62 return((void*)-1); 63 } 64 65 cd->designated = 0; 66 cd->state = ASCII; 67 68 return((void*)cd); 69 } /* end of int _icv_open(). */ 70 71 72 /**** _ I C V _ C L O S E ****/ 73 74 void _icv_close(_conv_desc* cd) 75 { 76 if (!cd) 77 errno = EBADF; 78 else 79 free((void*)cd); 80 } /* end of void _icv_close(_conv_desc*). */ 81 82 83 /**** _ I C V _ I C O N V ****/ 84 85 size_t _icv_iconv(_conv_desc* cd, char** inbuf, size_t* inbufleft, 86 char** outbuf, size_t* outbufleft) 87 { 88 size_t ret_val = 0; 89 unsigned char* ib; 90 unsigned char* ob; 91 unsigned char* ibtail; 92 unsigned char* obtail; 93 94 if (!cd) 95 { 96 errno = EBADF; 97 return((size_t)-1); 98 } 99 100 if (!inbuf || !(*inbuf)) 101 { 102 if (cd->state == WANSUNG) 103 { 104 if (outbufleft && *outbufleft >= 1 && outbuf && *outbuf) 105 { 106 **outbuf = SI; 107 (*outbuf)++; 108 (*outbufleft)--; 109 } 110 else 111 { 112 errno = E2BIG; 113 return((size_t)-1); 114 } 115 } 116 117 cd->designated = 0; 118 cd->state = ASCII; 119 return((size_t)0); 120 } 121 122 ib = (unsigned char*)*inbuf; 123 ob = (unsigned char*)*outbuf; 124 ibtail = ib + *inbufleft; 125 obtail = ob + *outbufleft; 126 127 while (ib < ibtail) 128 { 129 if (!(*ib & 0x80)) /* 7 bits */ 130 { 131 if (cd->state == WANSUNG) 132 { 133 if (ob >= obtail) 134 { 135 errno = E2BIG; 136 ret_val = (size_t)-1; 137 break; 138 } 139 *ob++ = SI; 140 cd->state = ASCII; 141 } 142 if (ob >= obtail) 143 { 144 errno = E2BIG; 145 ret_val = (size_t)-1; 146 break; 147 } 148 *ob++ = *ib++; 149 } 150 else 151 { 152 if ((ibtail - ib) < 2) 153 { 154 errno = EINVAL; 155 ret_val = (size_t)-1; 156 break; 157 } 158 159 if (!cd->designated) 160 { 161 if ((obtail - ob) < 4) 162 { 163 errno = E2BIG; 164 ret_val = (size_t)-1; 165 break; 166 } 167 *ob++ = ESC; *ob++ = '$'; 168 *ob++ = ')'; *ob++ = 'C'; 169 cd->designated = 1; 170 } 171 if (cd->state == ASCII) 172 { 173 if (ob >= obtail) 174 { 175 errno = E2BIG; 176 ret_val = (size_t)-1; 177 break; 178 } 179 *ob++ = SO; 180 cd->state = WANSUNG; 181 } 182 183 if ((obtail - ob) < 2) 184 { 185 errno = E2BIG; 186 ret_val = (size_t)-1; 187 break; 188 } 189 *ob++ = *ib++ & 0x7F; 190 *ob++ = *ib++ & 0x7F; 191 } 192 } 193 194 *inbuf = (char*)ib; 195 *inbufleft = ibtail - ib; 196 *outbuf = (char*)ob; 197 *outbufleft = obtail - ob; 198 199 return(ret_val); 200 } /* end of size_t _icv_iconv(_conv_desc*, char**, size_t*, char**, size_t*).*/ 201 202 void * 203 _cv_open() 204 { 205 struct _cv_state *st; 206 207 if ((st = (struct _cv_state *)malloc(sizeof(struct _cv_state))) == NULL) 208 return ((void *)-1); 209 210 st->_st_status = SHIFT_IN; 211 st->_gstate = _nostate; 212 213 return (st); 214 } 215 216 void 217 _cv_close(struct _cv_state *st) 218 { 219 free(st); 220 } 221 222 223 size_t 224 _cv_enconv(struct _cv_state *st, char **inbuf, size_t*inbytesleft, 225 char **outbuf, size_t*outbytesleft) 226 { 227 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 228 if (st->_st_status == SHIFT_OUT && *outbytesleft > 0) 229 { 230 **outbuf = SI; 231 (*outbytesleft)--; 232 (*outbuf)++; 233 } 234 st->_st_status = SHIFT_IN; 235 st->_gstate = _nostate; 236 /* 237 * Note that no shift sequence is needed for 238 * thetarget encoding. 239 */ 240 return (0); 241 } 242 243 if ( st->_gstate == _nostate ) 244 st->_gstate = _g0; 245 246 while (*inbytesleft > 0 && *outbytesleft > 0) { 247 if ( **inbuf & MSB ) { 248 if (st->_st_status == SHIFT_IN ) { 249 if ( st->_gstate == _g0 ) { 250 /* 251 * Check the outbytesleft : enough to hold ESC sequence 252 */ 253 if ( *outbytesleft < 4 ) { 254 break; 255 } 256 257 st->_gstate = _g1; 258 259 **outbuf = ESC; 260 (*outbuf)++, (*outbytesleft)--; 261 **outbuf = '$'; 262 (*outbuf)++, (*outbytesleft)--; 263 **outbuf = ')'; 264 (*outbuf)++, (*outbytesleft)--; 265 **outbuf = 'C'; 266 (*outbuf)++, (*outbytesleft)--; 267 268 if ( *outbytesleft <= 0 ) 269 break; 270 } 271 272 st->_st_status = SHIFT_OUT; 273 **outbuf = SO; 274 (*outbuf)++, (*outbytesleft)--; 275 276 if ( *outbytesleft <= 0 ) 277 break; 278 } 279 280 **outbuf = **inbuf & MSB_OFF; 281 (*outbuf)++, (*outbytesleft)--; 282 283 } else { 284 if (st->_st_status == SHIFT_OUT) { 285 st->_st_status = SHIFT_IN; 286 **outbuf = SI; 287 (*outbuf)++, (*outbytesleft)--; 288 289 if ( *outbytesleft <= 0 ) 290 break; 291 } 292 293 **outbuf = **inbuf; 294 (*outbuf)++, (*outbytesleft)--; 295 296 } 297 298 (*inbuf)++, (*inbytesleft)--; 299 } 300 return (*inbytesleft); 301 } 302