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 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 enum { NDY, KSC5601 } designator; 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->designator = NDY; 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 cd->designator = NDY; 103 cd->state = ASCII; 104 return((size_t)0); 105 } 106 107 ib = (unsigned char*)*inbuf; 108 ob = (unsigned char*)*outbuf; 109 ibtail = ib + *inbufleft; 110 obtail = ob + *outbufleft; 111 112 while (ib < ibtail) 113 { 114 if (cd->designator == NDY) 115 { 116 if (*ib == ESC) 117 { 118 if ((ibtail - ib) < 4) 119 { 120 errno = EINVAL; 121 ret_val = (size_t)-1; 122 break; 123 } 124 125 if (*(ib + 1) == '$' && *(ib + 2) == ')' && 126 *(ib + 3) == 'C') 127 { 128 cd->designator = KSC5601; 129 ib += 4; 130 continue; 131 } 132 } 133 134 if (ob >= obtail) 135 { 136 errno = E2BIG; 137 ret_val = (size_t)-1; 138 break; 139 } 140 *ob++ = *ib++; 141 } 142 else 143 { 144 if (*ib == SI) 145 { 146 cd->state = ASCII; 147 ib++; 148 continue; 149 } 150 else if (*ib == SO) 151 { 152 cd->state = WANSUNG; 153 ib++; 154 continue; 155 } 156 else if ((*ib == ' ' && cd->state == WANSUNG) || 157 cd->state == ASCII) 158 { 159 if (ob >= obtail) 160 { 161 errno = E2BIG; 162 ret_val = (size_t)-1; 163 break; 164 } 165 *ob++ = *ib++; 166 continue; 167 } 168 169 /* Pure KS C 5601 Wansung code */ 170 if ((ibtail - ib) < 2) 171 { 172 errno = EINVAL; 173 ret_val = (size_t)-1; 174 break; 175 } 176 177 if (*ib < 0x21 || *ib > 0x7D || *(ib + 1) < 0x21 || 178 *(ib + 1) == 0x7F) 179 { 180 errno = EILSEQ; 181 ret_val = (size_t)-1; 182 break; 183 } 184 185 if ((obtail - ob) < 2) 186 { 187 errno = E2BIG; 188 ret_val = (size_t)-1; 189 break; 190 } 191 *ob++ = *ib++ | 0x80; 192 *ob++ = *ib++ | 0x80; 193 } 194 } 195 196 *inbuf = (char*)ib; 197 *inbufleft = ibtail - ib; 198 *outbuf = (char*)ob; 199 *outbufleft = obtail - ob; 200 201 return(ret_val); 202 } /* end of size_t _icv_iconv(_conv_desc*, char**, size_t*, char**, size_t*).*/ 203 204 void * 205 _cv_open() 206 { 207 struct _cv_state *st; 208 209 if ((st = (struct _cv_state *)malloc(sizeof(struct _cv_state))) == NULL) 210 return ((void *)-1); 211 212 st->_st_status = SHIFT_IN; 213 st->_gstate = _nostate; 214 215 return (st); 216 } 217 218 void 219 _cv_close(struct _cv_state *st) 220 { 221 free(st); 222 } 223 224 225 size_t 226 _cv_enconv(struct _cv_state *st, char **inbuf, size_t*inbytesleft, 227 char **outbuf, size_t*outbytesleft) 228 { 229 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 230 st->_st_status = SHIFT_IN; 231 st->_gstate = _nostate; 232 /* 233 * Note that no shift sequence is needed for 234 * the target encoding. 235 */ 236 return (0); 237 } 238 239 if ( st->_gstate == _nostate ) 240 st->_gstate = _g0; 241 242 while (*inbytesleft > 0 && *outbytesleft > 0) { 243 if ( st->_gstate == _g1 ) { 244 if (**inbuf == SO) { 245 st->_st_status = SHIFT_OUT; 246 } else if (**inbuf == SI) { 247 st->_st_status = SHIFT_IN; 248 } else { 249 if (st->_st_status == SHIFT_OUT) { 250 while (*inbytesleft > 0 && *outbytesleft > 0 && 251 **inbuf != SI ) { 252 **outbuf = (**inbuf == ' ') ? ' ' : (MSB | **inbuf); 253 (*outbuf)++, (*outbytesleft)--; 254 (*inbuf)++, (*inbytesleft)--; 255 } 256 continue; 257 } else { 258 **outbuf = **inbuf; 259 (*outbuf)++, (*outbytesleft)--; 260 } 261 } 262 } else { 263 char *temp; 264 265 temp = *inbuf; 266 267 if ( *inbytesleft >= 4 && temp[0] == ESC && temp[1] == '$' 268 && temp[2] == ')' && temp[3] == 'C' ) { 269 st->_gstate = _g1; 270 *inbuf += 4; 271 *inbytesleft -= 4; 272 continue; 273 } else { 274 **outbuf = **inbuf; 275 (*outbuf)++, (*outbytesleft)--; 276 } 277 } 278 279 (*inbuf)++, (*inbytesleft)--; 280 } 281 return (*inbytesleft); 282 } 283