xref: /titanic_51/usr/src/lib/iconv_modules/zh/common/zh_CN.euc%HZ-GB-2312.c (revision 91e1e26ac6a73ce959289cf7d3d96c4baedbe0b8)
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 #include <stdio.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 
29 #define	MSB	0x80
30 
31 enum	_GSTATE { G0, G1, G2};
32 
33 
34 typedef struct _icv_state {
35 	char	_lastc;
36 	short	_gstate;
37 } _iconv_st;
38 
39 /*
40  * Open; called from iconv_open()
41  */
42 void *
43 _icv_open()
44 {
45 	_iconv_st *st;
46 
47 	if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) {
48 		errno = ENOMEM;
49 		return ((void *) -1);
50 	}
51 
52 	st->_gstate = G0;
53 	return ((void *)st);
54 }
55 
56 
57 /*
58  * Close; called from iconv_close()
59  */
60 void
61 _icv_close(_iconv_st *st)
62 {
63 	if (st == NULL)
64 		errno = EBADF;
65 	else
66 		free(st);
67 }
68 
69 
70 /*
71  * Actual conversion; called from iconv()
72  */
73 /*=======================================================================
74  *
75  *
76  *      +-------------------------------------+
77  *      V   MSB              MSB       ascii  |
78  *  +-> G0 ------------> G1 ------> G2 -------+
79  *  | ascii  (~{)    ^   MSB        |  (~})
80  *  +----+               +----------+
81  *=======================================================================*/
82 size_t
83 _icv_iconv(_iconv_st *st, char **inbuf, size_t*inbytesleft,
84 			char **outbuf, size_t*outbytesleft)
85 {
86 	if (st == NULL) {
87 		errno = EBADF;
88 		return -1;
89 	}
90 	if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */
91 		st->_gstate = G0;
92 		return 0;
93 	}
94 
95 	errno = 0;
96 
97 	while (*inbytesleft > 0 && *outbytesleft > 0) {
98 	    switch (st->_gstate) {
99 	    case G0:
100 		if ( **inbuf & MSB ) {
101 		   if(*outbytesleft >=2) {
102 		    **outbuf = '~';
103                     *(*outbuf+1) = '{';
104 		    (*outbuf) += 2, (*outbytesleft) -= 2;
105 		    st->_lastc = **inbuf;
106 		    st->_gstate = G1;
107 		    } else {
108 			errno = E2BIG;
109 			return (size_t)-1;
110                     }
111 
112 		} else {
113 		    **outbuf = **inbuf;
114 		    (*outbuf)++, (*outbytesleft)--;
115 		    if (**inbuf == '~') {
116 		    **outbuf = '~';
117 		    (*outbuf)++, (*outbytesleft)--;
118 		    }
119 		}
120 		break;
121 	    case G1:
122 		if ( **inbuf  & MSB ) {
123 		   if(*outbytesleft >=2) {
124 			**outbuf = st->_lastc - 0x80;
125 			*(*outbuf+1) = **inbuf - 0x80;
126 			(*outbuf) += 2, (*outbytesleft) -= 2;
127 			st->_gstate = G2;
128 		    } else {
129                         errno = E2BIG;
130                         return (size_t)-1;
131                     }
132 
133 		} else {
134 		    errno = E2BIG;
135 		    return (size_t)-1;
136 		}
137 		break;
138 	    case G2:
139 		if ( **inbuf & MSB ) {
140 		    st->_lastc = **inbuf;
141 		    st->_gstate = G1;
142 		} else {
143 		   if(*outbytesleft >=3) {
144 		    **outbuf = '~';
145                     *(*outbuf+1) = '}';
146                     *(*outbuf+2) = **inbuf;
147 		    (*outbuf) += 3, (*outbytesleft) -= 3;
148 		    st->_gstate = G0;
149 		    }else {
150                         errno = E2BIG;
151                         return (size_t)-1;
152                     }
153 
154 		}
155 		break;
156 	    }
157 
158 	    (*inbuf)++, (*inbytesleft)--;
159 	    if (errno)
160 		return -1;
161 	}
162 	if (*inbytesleft > 0 && *outbytesleft == 0) {
163 		errno = E2BIG;
164 		return -1;
165 	}
166 	return (*inbytesleft);
167 }
168