8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libbc / libc / gen / common / iso.multibyte.c
blobfb1f1c607ff0a7254f921435a6929e35231f5310
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 1988 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
30 #include "codeset.h"
31 #include "mbextern.h"
32 #include "iso2022.h"
34 #define TO_MULTI 2
35 #define TO_SINGLE 1
37 #define BIT7ENV 7 /* 7bit enviornment */
38 #define BIT8ENV 8 /* 8bit environment */
39 #define NUM_OF_STATES 4 /* G0, G1, G2, G3 */
40 #define BIT8(_ch) (_ch & 0x80)
41 #define MAXSIZE 100 /* ESC LOCK upper lower */
43 #define USE_STATE 0 /* use the actual _state info */
44 #define USE_CONTROL 1 /* use C0 or C1 */
45 #define USE_SS2 2 /* use Single shift 2 */
46 #define USE_SS3 3 /* use Single shift 3 */
48 #define G0MASK 0x0000
49 #define G1MASK 0x0080
50 #define G2MASK 0x8000
51 #define G3MASK 0x8080
52 #define FINAL 0x33 /* Temporary final character */
54 #define MMB_CUR_MAX 128
57 * Keep state informations
59 struct state {
60 char width; /* 1 or 2 */
61 char final; /* final character */
64 static char _my_env = BIT7ENV; /* default 7bits environment */
65 static struct state Invoked_G0, Invoked_G1;
66 static char _currentG0 = G0;
67 static char _currentG1 = G1;
68 static struct state _des_states[NUM_OF_STATES] = {
69 {-1, 0}, {-1, 0}, {-1, 0}, {01, 0}
72 void _savestates(void); /* save states */
73 void _restorestates(void); /* restore states */
74 void _initializestates(void);/* Initialize states */
78 * Variables for wc*tomb*()
80 static char _currentOUT = G0; /* G0, G1, G2 or G3 */
81 static int prevcsize = 1;
84 * mbtowc - subroutine for most iso codeset sequences
86 int
87 _mbtowc_iso(wchar_t *pwc, char *s, size_t n)
89 unsigned char ch;
90 unsigned char tch; /* temporary use */
91 unsigned char *us = (unsigned char *)s;
92 int gen_wide_state = USE_STATE; /* used in gen_wide: */
93 int length = 0;
94 int len = 0;
95 wchar_t wide;
96 int mask;
97 int i;
99 isowidth_t * isoinfo = (isowidth_t *) _code_set_info.code_info;
102 * initialize _g0_stuff
104 if (_des_states[G0].width == -1) {
105 _des_states[G0].width = isoinfo->g0_len;
106 _des_states[G1].width = isoinfo->g1_len;
107 _des_states[G2].width = isoinfo->g2_len;
108 _des_states[G3].width = isoinfo->g3_len;
109 _my_env = isoinfo->bit_env;
111 Invoked_G0 = _des_states[G0];
112 Invoked_G1 = _des_states[G1];
116 * get character and proceed
118 loop:
119 ch = *us++;
120 if (++length > n) return (-1); /* too long */
121 switch (ch) { /* get a character */
122 /* escape sequence or locking shifts */
123 case ESC: /* escape sequence */
124 gen_wide_state = USE_STATE; /* used in gen_wide: */
125 ch = *us++;
126 if (++length > n) return (-1); /* too long */
127 switch (ch) {
128 /* DESIGNATE */
129 case 0x24: /* designate */
130 ch = *us++;
131 if (++length > n) return (-1); /* too long */
132 switch (ch) {
133 case 0x28: case 0x29:
134 case 0x2A: case 0x2B:
135 case 0x2D: case 0x2E:
136 case 0x2F:
137 tch = ch; /* save this to decide _des_state */
138 /* Skip intermidiates */
139 do {
140 ch = *us++;
141 if (++length > n) return (-1); /* too long */
142 } while (ch >= 0x20 && ch <= 0x2F);
143 if (ch < 0x30) /* ch should be a final character */
144 return (-1); /* error */
145 if (tch == 0x28)
146 i = G0;
147 else if (tch == 0x29 || tch == 0x2D)
148 i = G1;
149 else if (tch == 0x2A || tch == 0x2E)
150 i = G2;
151 else /* (tch == 0x2B || tch == 0x2F) */
152 i = G3;
153 /* updates state info */
154 _des_states[i].width = TO_MULTI;
155 _des_states[i].final = ch;
157 goto loop;
158 break;
159 default:
160 /* This is an illegal sequence */
161 return (-1);
162 break;
164 break;
165 case 0x28: /* designate */
166 case 0x29: case 0x2A: case 0x2B:
167 case 0x2D: case 0x2E: case 0x2F:
168 tch = ch; /* save this to decide _des_state */
169 /* Skip intermidiates */
170 do {
171 ch = *us++;
172 if (++length > n) return (-1); /* too long */
173 } while (ch >= 0x20 && ch <= 0x2F);
174 if (ch < 0x30) /* ch should be a final character */
175 return (-1); /* error */
176 if (tch == 0x28)
177 i = G0;
178 else if (tch == 0x29 || tch == 0x2D)
179 i = G1;
180 else if (tch == 0x2A || tch == 0x2E)
181 i = G2;
182 else /* (tch == 0x2B || tch == 0x2F) */
183 i = G3;
184 /* updates state info */
185 _des_states[i].width = TO_SINGLE;
186 _des_states[i].final = ch;
188 goto loop;
189 break;
191 /* LOCKING SHIFTS */
192 case LS1R: /* locking shift LS1R */;
193 Invoked_G1 = _des_states[G1];
194 _currentG1 = G1;
195 goto loop;
196 break;
197 case LS2: /* locking shift LS2 */
198 Invoked_G0 = _des_states[G2];
199 _currentG0 = G2;
200 goto loop;
201 break;
202 case LS2R: /* locking shift LS2R */
203 Invoked_G1 = _des_states[G2];
204 _currentG1 = G2;
205 goto loop;
206 break;
207 case LS3: /* locking shift LS3 */
208 Invoked_G0 = _des_states[G3];
209 _currentG0 = G3;
210 goto loop;
211 break;
212 case LS3R: /* locking shift LS3R */
213 Invoked_G1 = _des_states[G3];
214 _currentG1 = G3;
215 goto loop;
216 break;
218 /* CONTROL FUNCTIONS */
219 case 0x21: /* C0 sets */
220 case 0x22: /* C1 sets */
221 do {
222 ch = *us++;
223 if (++length > n) return (-1); /* too long */
224 } while (ch >= 0x20 && ch <= 0x2F);
225 if (ch < 0x30) /* ch should be a final character */
226 return (-1); /* error */
227 goto loop;
228 break;
230 /* SINGLE SHIFT for 7bit environment */
231 case SS2_7B: /* Single shift SS2 for 7bits */
232 case SS3_7B: /* Single shoft SS3 for 7bits */
233 if (ch == SS2_7B)
234 gen_wide_state = USE_SS2;
235 else
236 gen_wide_state = USE_SS3;
237 goto loop;
238 break;
240 default: /* should be an error */
241 return (-1);
242 break;
244 /* locking shifts */
245 case LS0:
246 gen_wide_state = USE_STATE; /* used in gen_wide: */
247 Invoked_G0 = _des_states[G0];
248 _currentG0 = G0;
249 goto loop;
250 break;
252 case LS1:
253 gen_wide_state = USE_STATE; /* used in gen_wide: */
254 Invoked_G0 = _des_states[G1];
255 _currentG0 = G1;
256 goto loop;
257 break;
259 /* Single shift SS3 and SS2 for 8bits */
260 case SS2_8B:
261 case SS3_8B:
262 if (ch == SS2_8B)
263 gen_wide_state = USE_SS2;
264 else
265 gen_wide_state = USE_SS3;
266 goto loop;
267 break;
269 /* This character is not any special character/
270 * It does not change any state.
271 * Goto where it generates wide character.
273 default:
275 * Use this ch to generate pwc.
277 if (ch == 0) { /* end of string or 0 */
278 wide = 0;
279 mask = 0;
280 goto gen_wide;
282 break;
287 * Generate pwc here.
288 * The information here is
289 * current state and length. If the length is two, you need to
290 * read one more character.
292 switch (gen_wide_state) {
293 case USE_STATE:
294 if (BIT8(ch)) { /* 8bit environment ? */
295 /* current mode is G1 mode */
296 if (Invoked_G1.width == 2) {
297 tch = *us++;
298 if (++length > n) return (-1);
299 wide = ch;
300 wide = (wide << 8 | tch);
302 else {
303 wide = ch;
305 if (_currentG1 == G0) mask = G0MASK;
306 else if (_currentG1 == G1) mask = G1MASK;
307 else if (_currentG1 == G2) mask = G2MASK;
308 else mask = G3MASK;
310 else {
311 /* current mode is G0 mode */
312 if (Invoked_G0.width == 2) {
313 tch = *us++;
314 if (++length > n) return (-1);
315 wide = ch;
316 wide = (wide << 8 | tch);
318 else {
319 wide = ch;
321 if (_currentG0 == G0) mask = G0MASK;
322 else if (_currentG0 == G1) mask = G1MASK;
323 else if (_currentG0 == G2) mask = G2MASK;
324 else mask = G3MASK;
326 break;
327 case USE_SS2:
328 if (_des_states[G2].width == 2) {
329 tch = *us++;
330 if (++length > n) return (-1);
331 wide = ch;
332 wide = (wide << 8 | tch);
334 else {
335 wide = ch;
337 mask = G2MASK;
338 break;
339 case USE_SS3:
340 if (_des_states[G3].width == 2) {
341 tch = *us++;
342 if (++length > n) return (-1);
343 wide = ch;
344 wide = (wide << 8 | tch);
346 else {
347 wide = ch;
349 mask = G3MASK;
350 break;
351 default:
352 /* shoult be internal error */
353 return (-1);
354 break;
356 gen_wide:
357 wide &= 0x7F7F; /* strip off the top bit */
358 wide = wide | mask;
359 if (pwc != NULL)
360 *pwc = wide;
361 return (length);
365 #define MAXMBSIZE 128
367 * mbstowcs()
369 size_t
370 _mbstowcs_iso(wchar_t *pwcs, unsigned char *s, size_t n)
372 int ret1;
373 int accsum = 0;
374 wchar_t pwc;
377 * If pwcs == 0, do nothing.
379 if (pwcs == 0)
380 return (0);
382 * States things
384 _savestates(); _initializestates();
385 while (accsum < n) {
386 ret1 = _mbtowc_iso (&pwc, (char *)s, MAXMBSIZE);
387 if (ret1 < 0)
388 return (-1); /* error */
389 if (ret1 == 0 || pwc == 0) {
390 if (pwcs == 0)
391 *pwcs = 0;
393 * Restore states
395 _restorestates();
396 return (accsum);
398 s = s + ret1; /* increment the pointer */
399 *pwcs++ = pwc;
400 ++accsum;
403 * Restore states
405 _restorestates();
406 return (accsum);
410 * wctomb -
413 _wctomb_iso(unsigned char *s, wchar_t pwc)
415 unsigned char ch;
416 unsigned char tch; /* temporary use */
417 unsigned char *us = (unsigned char *)s;
418 int gen_wide_state = USE_STATE; /* used in gen_wide: */
419 int length = 0;
420 int len = 0;
421 wchar_t wide;
422 unsigned short mode;
423 unsigned char buf[MAXSIZE];
424 unsigned char *bp;
425 int csize, i;
426 int n = MMB_CUR_MAX;
428 isowidth_t * isoinfo = (isowidth_t *) _code_set_info.code_info;
431 * If pwc is 0, do this first.
433 if (pwc == 0) {
434 if (s != 0) {
435 *s = 0;
436 return (1);
438 else {
439 return (0);
443 mode = pwc & G3MASK; /* The mode of this character */
444 if (((pwc >> 8) & 0x007f) == 0)
445 csize = 1;
446 else
447 csize = 2;
448 bp = buf;
449 length = 0;
450 #ifdef DDDebug
451 if (_my_env == BIT7ENV)
452 printf ("7b ");
453 else
454 printf ("8b ");
455 printf ("csize = %d, prevcsize = %d, (%x,%x) ",csize, prevcsize, (pwc>>8)&0x00ff, pwc&0x00ff);
456 switch (mode) {
457 case G0MASK:
458 printf ("G0"); break;
459 case G1MASK:
460 printf ("G1"); break;
461 case G2MASK:
462 printf ("G2"); break;
463 case G3MASK:
464 printf ("G3"); break;
465 default:
466 printf ("XXXX"); break;
468 #endif
470 switch (_my_env) {
471 case BIT7ENV: /* 7 bit environment */
472 switch (mode) {
473 case G0MASK:
474 if (_currentOUT != G0 || prevcsize != csize) {
475 _currentOUT = G0;
476 if (csize == 2) {
478 * Emit escape sequences
480 *bp++ = ESC;
481 *bp++ = 0x24;
482 *bp++ = 0x28;
483 *bp++ = FINAL;
484 length += 4;
486 else {
488 * Emit escape sequences
490 *bp++ = ESC;
491 *bp++ = 0x28;
492 *bp++ = FINAL;
493 length += 3;
495 *bp++ = SI;
496 ++length;
498 if (csize == 1) {
499 *bp++ = pwc & 0x007f;
500 ++length;
502 else {
503 *bp++ = (pwc & 0x7f00) >> 8;
504 ++length;
505 *bp++ = pwc & 0x007f;
506 ++length;
508 break;
509 case G1MASK:
510 if (_currentOUT != G1 || prevcsize != csize) {
511 _currentOUT = G1;
512 if (csize == 2) {
514 * Emit escape sequences
516 *bp++ = ESC;
517 *bp++ = 0x24;
518 *bp++ = 0x29;
519 *bp++ = FINAL;
520 length += 4;
522 else {
524 * Emit escape sequences
526 *bp++ = ESC;
527 *bp++ = 0x29;
528 *bp++ = FINAL;
529 length += 3;
531 *bp++ = SO;
532 ++length;
534 if (csize == 1) {
535 *bp++ = pwc & 0x007f;
536 ++length;
538 else {
539 *bp++ = (pwc & 0x7f00) >> 8;
540 ++length;
541 *bp++ = pwc & 0x007f;
542 ++length;
544 break;
545 case G2MASK:
546 if (_currentOUT != G2 || prevcsize != csize) {
547 _currentOUT = G2;
548 if (csize == 2) {
550 * Emit escape sequences
552 *bp++ = ESC;
553 *bp++ = 0x24;
554 *bp++ = 0x2A;
555 *bp++ = FINAL;
556 length += 4;
558 else {
560 * Emit escape sequences
562 *bp++ = ESC;
563 *bp++ = 0x2A;
564 *bp++ = FINAL;
565 length += 3;
567 *bp++ = ESC; *bp++ = LS2;
568 length += 2;
570 if (csize == 1) {
571 *bp++ = pwc & 0x007f;
572 ++length;
574 else {
575 *bp++ = (pwc & 0x7f00) >> 8;
576 ++length;
577 *bp++ = pwc & 0x007f;
578 ++length;
580 break;
581 case G3MASK:
582 if (_currentOUT != G3 || prevcsize != csize) {
583 _currentOUT = G3;
584 if (csize == 2) {
586 * Emit escape sequences
588 *bp++ = ESC;
589 *bp++ = 0x24;
590 *bp++ = 0x2B;
591 *bp++ = FINAL;
592 length += 4;
594 else {
596 * Emit escape sequences
598 *bp++ = ESC;
599 *bp++ = 0x2B;
600 *bp++ = FINAL;
601 length += 3;
603 *bp++ = ESC; *bp++ = LS3;
604 length += 2;
606 if (csize == 1) {
607 *bp++ = pwc & 0x007f;
608 ++length;
610 else {
611 *bp++ = (pwc & 0x7f00) >> 8;
612 ++length;
613 *bp++ = pwc & 0x007f;
614 ++length;
616 break;
618 break;
619 case BIT8ENV: /* 8 bit environment */
620 switch (mode) {
621 case G0MASK:
622 if (_currentOUT != G0 || prevcsize != csize) {
623 _currentOUT = G0;
624 if (csize == 2) {
626 * Emit escape sequences
628 *bp++ = ESC;
629 *bp++ = 0x24;
630 *bp++ = 0x28;
631 *bp++ = FINAL;
632 length += 4;
634 else {
636 * Emit escape sequences
638 *bp++ = ESC;
639 *bp++ = 0x28;
640 *bp++ = FINAL;
641 length += 3;
643 *bp++ = LS0;
644 ++length;
646 if (csize == 1) {
647 *bp++ = pwc & 0x007f;
648 ++length;
650 else {
651 *bp++ = (pwc & 0x7f00) >> 8;
652 ++length;
653 *bp++ = pwc & 0x007f;
654 ++length;
656 break;
657 case G1MASK:
658 if (_currentOUT != G1 || prevcsize != csize) {
659 _currentOUT = G1;
660 if (csize == 2) {
662 * Emit escape sequences
664 *bp++ = ESC;
665 *bp++ = 0x24;
666 *bp++ = 0x29;
667 *bp++ = FINAL;
668 length += 4;
670 else {
672 * Emit escape sequences
674 *bp++ = ESC;
675 *bp++ = 0x29;
676 *bp++ = FINAL;
677 length += 3;
679 *bp++ = ESC; *bp++ = LS1R;
680 length += 2;
684 * If state is G1 or G2, or G3, assume that
685 * this is 8bit characters. To do this more
686 * accurately, wide character needs to be
687 * larger than 16 bits to keep more information.
689 pwc |= 0x8080;
690 if (csize == 1) {
691 *bp++ = pwc & 0x00ff;
692 ++length;
694 else {
695 *bp++ = (pwc & 0xff00) >> 8;
696 ++length;
697 *bp++ = pwc & 0x00ff;
698 ++length;
700 break;
701 case G2MASK:
702 if (_currentOUT != G2 || prevcsize != csize) {
703 _currentOUT = G2;
704 if (csize == 2) {
706 * Emit escape sequences
708 *bp++ = ESC;
709 *bp++ = 0x24;
710 *bp++ = 0x2A;
711 *bp++ = FINAL;
712 length += 4;
714 else {
716 * Emit escape sequences
718 *bp++ = ESC;
719 *bp++ = 0x2A;
720 *bp++ = FINAL;
721 length += 3;
723 *bp++ = ESC; *bp++ = LS2R;
724 length += 2;
727 * If state is G1 or G2, or G3, assume that
728 * this is 8bit characters. To do this more
729 * accurately, wide character needs to be
730 * larger than 16 bits to keep more information.
732 pwc |= 0x8080;
733 if (csize == 1) {
734 *bp++ = pwc & 0x00ff;
735 ++length;
737 else {
738 *bp++ = (pwc & 0xff00) >> 8;
739 ++length;
740 *bp++ = pwc & 0x00ff;
741 ++length;
743 break;
744 case G3MASK:
745 if (_currentOUT != G3 || prevcsize != csize) {
746 _currentOUT = G3;
747 if (csize == 2) {
749 * Emit escape sequences
751 *bp++ = ESC;
752 *bp++ = 0x24;
753 *bp++ = 0x2B;
754 *bp++ = FINAL;
755 length += 4;
757 else {
759 * Emit escape sequences
761 *bp++ = ESC;
762 *bp++ = 0x2B;
763 *bp++ = FINAL;
764 length += 3;
766 *bp++ = ESC; *bp++ = LS3R;
767 length += 2;
770 * If state is G1 or G2, or G3, assume that
771 * this is 8bit characters. To do this more
772 * accurately, wide character needs to be
773 * larger than 16 bits to keep more information.
775 pwc |= 0x8080;
776 if (csize == 1) {
777 *bp++ = pwc & 0x00ff;
778 ++length;
780 else {
781 *bp++ = (pwc & 0xff00) >> 8;
782 ++length;
783 *bp++ = pwc & 0x00ff;
784 ++length;
786 break;
788 break;
789 default: /* Should never happens */
790 return (-1);
791 break;
794 prevcsize = csize;
796 if (length > n) {
797 return (-1); /* buffer too small */
799 for (i = 0; i < length; i++) {
800 *s++ = buf[i];
802 #ifdef DDDebug
803 printf ("\t(");
804 for (i = 0; i < length; i++) {
805 printf ("%x,", buf[i]);
807 printf (")\n");
808 #endif
809 return (length);
813 * wcstombs
815 size_t
816 _wcstombs_iso(char *s, wchar_t *pwcs, int n)
818 int acclen = 0;
819 char buf[MMB_CUR_MAX];
820 int ret1;
821 int i;
823 if (n < 0)
824 return (-1);
826 * Initialize State
828 _savestates(); _initializestates();
829 while (acclen < n) {
830 ret1 = _wctomb_iso ((unsigned char *)buf, *pwcs);
832 * end of string ?
834 if (ret1 == 1 && buf[0] == 0) {
835 *s = 0;
837 * restore states
839 _restorestates();
840 return (acclen);
843 * Error ?
845 if (ret1 < 0)
846 return (-1);
847 acclen += ret1;
848 for (i = 0; i < ret1; i++)
849 *s++ = buf[i];
850 ++pwcs;
854 * restore states
856 _restorestates();
859 * return the length
861 return (acclen);
866 * Supplementary routines
869 void
870 _initializestates(void)
872 _currentG0 = G0;
873 _currentG1 = G1;
875 _des_states[G0].width = -1; /* This makes it Initialize */
877 _currentOUT = G0;
878 prevcsize = 1;
881 static char SAVED_currentG0;
882 static char SAVED_currentG1;
883 static struct state SAVED_des_states[NUM_OF_STATES];
884 static struct state SAVED_Invoked_G0, SAVED_Invoked_G1;
885 static char SAVED_currentOUT = G0; /* G0, G1, G2 or G3 */
886 static int SAVED_prevcsize = 1;
888 void
889 _savestates(void)
892 SAVED_currentG0 = _currentG0;
893 SAVED_currentG1 = _currentG1;
895 SAVED_des_states[G0] = _des_states[G0];
896 SAVED_des_states[G1] = _des_states[G1];
897 SAVED_des_states[G2] = _des_states[G2];
898 SAVED_des_states[G3] = _des_states[G3];
900 SAVED_Invoked_G0 = Invoked_G0;
901 SAVED_Invoked_G1 = Invoked_G1;
903 SAVED_currentOUT = _currentOUT;
904 SAVED_prevcsize = prevcsize;
907 void
908 _restorestates(void)
910 _currentG0 = SAVED_currentG0;
911 _currentG1 = SAVED_currentG1;
913 _des_states[G0] = SAVED_des_states[G0];
914 _des_states[G1] = SAVED_des_states[G1];
915 _des_states[G2] = SAVED_des_states[G2];
916 _des_states[G3] = SAVED_des_states[G3];
918 Invoked_G0 = SAVED_Invoked_G0;
919 Invoked_G1 = SAVED_Invoked_G1;
921 _currentOUT = SAVED_currentOUT;
922 prevcsize = SAVED_prevcsize;