xref: /titanic_41/usr/src/lib/libbc/libc/gen/common/xccs.multibyte.c (revision 2b24ab6b3865caeede9eeb9db6b83e1d89dcd1ea)
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
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
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
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
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