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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1990 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #if !defined(lint) && defined(SCCSIDS)
30 static char *sccsid = "%Z%%M% %I% %E% SMI";
31 #endif
32
33 #include <stdio.h>
34 #include <sys/types.h>
35
36 #define CS377 0377
37 #define MASK 0x0000ffff
38 #define TOP1 0x80000000
39 #define TOP2 0x08000000
40
41
42 /*
43 * mbtowc routines for the Xerox XCCS codeset standard
44 */
45 int
_mbtowc_xccs(pwc,s,n)46 _mbtowc_xccs(pwc, s, n)
47 wchar_t *pwc;
48 char *s;
49 int n;
50 {
51 static unsigned int CSselect = 0;
52 static int CSlength = 1;
53 wchar_t twchar = 0;
54
55 /*
56 * If length is negative, return error
57 */
58 if (n <= 0)
59 return (-1);
60
61 /*
62 * End of string ?
63 */
64 if (*s == 0 && CSlength == 1)
65 return (0);
66 if (*s == 0 && *(s + 1) == 0 && CSlength == 2)
67 return (0);
68
69 /*
70 * Get a character
71 */
72 if ((unsigned char)*s == CS377) {
73 /*
74 * Switching code set
75 */
76 ++s;
77 /*
78 * Change characteristics
79 */
80 if ((unsigned char)*s == CS377) {
81 ++s;
82 /*
83 * two byte sequence
84 */
85 if (*s++ != 0)
86 return (-1);
87 CSselect = 0;
88 CSlength = 2;
89
90 }
91 else {
92 /*
93 * Change CSselect
94 */
95 CSselect = (unsigned int)*s++;
96 CSlength = 1;
97 }
98 }
99
100 /*
101 * Get a character and return
102 */
103 if (CSlength == 1) {
104 twchar = CSselect;
105 }
106 else {
107 twchar = *s++;
108 }
109 twchar = twchar << 8;
110 twchar = twchar | *s;
111 if (pwc)
112 *pwc = twchar & MASK;
113 /*
114 * Encode additional information
115 */
116 if (CSlength == 2)
117 if (pwc)
118 *pwc |= TOP1;
119 return (CSlength);
120 }
121
122 /*
123 * wctomb routines
124 */
125 int
_wctomb_xccs(s,pwc)126 _wctomb_xccs(s, pwc)
127 char *s;
128 wchar_t pwc;
129 {
130 unsigned char upper, lower;
131 char *old = s;
132 #ifdef DEBUG
133 printf ("XCCS- xctomb\n");
134 #endif
135
136 if (!s)
137 return (0);
138
139 /*
140 * Get lower and upper anyway
141 */
142 lower = pwc & 0x00ff;
143 upper = (pwc >> 8) & 0x00ff;
144 if (lower == CS377 || upper == CS377)
145 return (-1);
146 if (pwc & TOP1) { /* length == 2 */
147 /*
148 * This was the marker.
149 * Emitt 3 additional characters.
150 */
151 *s++ = CS377;
152 *s++ = CS377;
153 *s++ = 0;
154 *s++ = upper;
155 *s++ = lower;
156 }
157 else {
158 /*
159 * This was the marker.
160 * Emitt 2 additional characters.
161 */
162 *s++ = CS377;
163 *s++ = upper;
164 *s++ = lower;
165 }
166 return (s - old);
167 }
168
169
170 /*
171 * mbstowcs routines
172 */
173 size_t
_mbstowcs_xccs(pwc,s,n)174 _mbstowcs_xccs(pwc, s, n)
175 wchar_t *pwc;
176 char *s;
177 int n;
178 {
179 static unsigned int CSselect = 0;
180 static int CSlength = 1;
181 wchar_t twchar = 0;
182 int cnt = 0;
183
184 /*
185 * If length is negative, return error
186 */
187 if (n <= 0)
188 return (-1);
189
190 /*
191 * End of string ?
192 */
193 if (*s == 0 && CSlength == 1)
194 return (0);
195 if (*s == 0 && *(s + 1) == 0 && CSlength == 2)
196 return (0);
197
198 do {
199 /*
200 * Check for an end of the string
201 */
202 if (((*s == 0 && CSlength == 1)) ||
203 ((*s == 0 && *(s + 1) == 0 && CSlength == 2))) {
204 *pwc = 0;
205 ++cnt;
206 --n;
207 break;
208 }
209 /*
210 * Get a character
211 */
212 if ((unsigned char)*s == CS377) {
213 ++s;
214 /*
215 * Change characterristics
216 */
217 if ((unsigned char)*s == CS377) {
218 ++s;
219 /*
220 * two byte sequence
221 */
222 if (*s++ != 0)
223 return (-1);
224 CSselect = 0;
225 CSlength = 2;
226
227 }
228 else {
229 /*
230 * Change CSselect
231 */
232 CSselect = (unsigned int)*s++;
233 CSlength = 1;
234 }
235 }
236
237 /*
238 * Get a character and return
239 */
240 if (CSlength == 1) {
241 twchar = CSselect;
242 }
243 else {
244 twchar = *s++;
245 }
246 twchar = twchar << 8;
247 twchar = twchar | *s++;
248 *pwc = twchar & MASK;
249 if (CSlength == 2)
250 *pwc |= TOP1;
251 ++pwc;
252 ++cnt;
253 --n;
254 } while (n >= 0);
255 return (cnt);
256 }
257
258
259 /*
260 * wcstombs routines
261 */
262 size_t
_wcstombs_xccs(s,pwc,n)263 _wcstombs_xccs(s, pwc, n)
264 char *s;
265 wchar_t *pwc;
266 int n;
267 {
268 int cnt = 0;
269 unsigned char lower, upper;
270 int in_2byte = 0;
271 int in_1byte = 0;
272 int current = 0;
273
274 if (n <= 0)
275 return (-1);
276
277 if (*pwc == 0)
278 return (0);
279
280 do {
281 lower = *pwc & 0x00ff;
282 upper = (*pwc >> 8) & 0x00ff;
283 /*
284 * End of string ?
285 */
286 if (lower == 0) {
287 *s++ = 0;
288 ++cnt;
289 --n;
290 if (n == 0)
291 break;
292 *s++ = 0;
293 ++cnt;
294 break;
295 }
296 if (lower == CS377 || upper == CS377)
297 return (-1);
298 if (*pwc & TOP1) { /* length == 2 */
299 if (in_2byte == 0) {
300 /*
301 * This was the marker.
302 * Emitt 3 additional characters.
303 */
304 *s++ = CS377; ++cnt; --n;
305 *s++ = CS377; ++cnt; --n;
306 *s++ = 0; ++cnt; --n;
307 in_2byte = 1;
308 in_1byte = 0;
309 }
310 *s++ = upper; ++cnt; --n;
311 if (n == 0)
312 break;
313 *s++ = lower; ++cnt; --n;
314 if (n == 0)
315 break;
316 }
317 else {
318 if ((in_1byte == 0 && in_2byte == 1) ||
319 (in_1byte == 1 && upper != current) ||
320 (in_1byte == 0 && in_2byte == 0 && upper != 0)) {
321 /*
322 * This was the marker.
323 * Emitt 2 additional characters.
324 */
325 *s++ = CS377; ++cnt; --n;
326 if (n == 0)
327 break;
328 *s++ = upper; ++cnt; --n;
329 if (n == 0)
330 break;
331 in_2byte = 0;
332 in_1byte = 1;
333 current = upper;
334 }
335 *s++ = lower; ++cnt; --n;
336 if (n == 0)
337 break;
338 }
339 ++pwc;
340 } while (n >= 0);
341 return (cnt);
342 }
343