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
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]
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>
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 */
52 #define FINAL 0x33 /* Temporary final character */
54 #define MMB_CUR_MAX 128
57 * Keep state informations
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
87 _mbtowc_iso(wchar_t *pwc
, char *s
, size_t n
)
90 unsigned char tch
; /* temporary use */
91 unsigned char *us
= (unsigned char *)s
;
92 int gen_wide_state
= USE_STATE
; /* used in gen_wide: */
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
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: */
126 if (++length
> n
) return (-1); /* too long */
129 case 0x24: /* designate */
131 if (++length
> n
) return (-1); /* too long */
133 case 0x28: case 0x29:
134 case 0x2A: case 0x2B:
135 case 0x2D: case 0x2E:
137 tch
= ch
; /* save this to decide _des_state */
138 /* Skip intermidiates */
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 */
147 else if (tch
== 0x29 || tch
== 0x2D)
149 else if (tch
== 0x2A || tch
== 0x2E)
151 else /* (tch == 0x2B || tch == 0x2F) */
153 /* updates state info */
154 _des_states
[i
].width
= TO_MULTI
;
155 _des_states
[i
].final
= ch
;
160 /* This is an illegal sequence */
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 */
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 */
178 else if (tch
== 0x29 || tch
== 0x2D)
180 else if (tch
== 0x2A || tch
== 0x2E)
182 else /* (tch == 0x2B || tch == 0x2F) */
184 /* updates state info */
185 _des_states
[i
].width
= TO_SINGLE
;
186 _des_states
[i
].final
= ch
;
192 case LS1R
: /* locking shift LS1R */;
193 Invoked_G1
= _des_states
[G1
];
197 case LS2
: /* locking shift LS2 */
198 Invoked_G0
= _des_states
[G2
];
202 case LS2R
: /* locking shift LS2R */
203 Invoked_G1
= _des_states
[G2
];
207 case LS3
: /* locking shift LS3 */
208 Invoked_G0
= _des_states
[G3
];
212 case LS3R
: /* locking shift LS3R */
213 Invoked_G1
= _des_states
[G3
];
218 /* CONTROL FUNCTIONS */
219 case 0x21: /* C0 sets */
220 case 0x22: /* C1 sets */
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 */
230 /* SINGLE SHIFT for 7bit environment */
231 case SS2_7B
: /* Single shift SS2 for 7bits */
232 case SS3_7B
: /* Single shoft SS3 for 7bits */
234 gen_wide_state
= USE_SS2
;
236 gen_wide_state
= USE_SS3
;
240 default: /* should be an error */
246 gen_wide_state
= USE_STATE
; /* used in gen_wide: */
247 Invoked_G0
= _des_states
[G0
];
253 gen_wide_state
= USE_STATE
; /* used in gen_wide: */
254 Invoked_G0
= _des_states
[G1
];
259 /* Single shift SS3 and SS2 for 8bits */
263 gen_wide_state
= USE_SS2
;
265 gen_wide_state
= USE_SS3
;
269 /* This character is not any special character/
270 * It does not change any state.
271 * Goto where it generates wide character.
275 * Use this ch to generate pwc.
277 if (ch
== 0) { /* end of string or 0 */
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
) {
294 if (BIT8(ch
)) { /* 8bit environment ? */
295 /* current mode is G1 mode */
296 if (Invoked_G1
.width
== 2) {
298 if (++length
> n
) return (-1);
300 wide
= (wide
<< 8 | tch
);
305 if (_currentG1
== G0
) mask
= G0MASK
;
306 else if (_currentG1
== G1
) mask
= G1MASK
;
307 else if (_currentG1
== G2
) mask
= G2MASK
;
311 /* current mode is G0 mode */
312 if (Invoked_G0
.width
== 2) {
314 if (++length
> n
) return (-1);
316 wide
= (wide
<< 8 | tch
);
321 if (_currentG0
== G0
) mask
= G0MASK
;
322 else if (_currentG0
== G1
) mask
= G1MASK
;
323 else if (_currentG0
== G2
) mask
= G2MASK
;
328 if (_des_states
[G2
].width
== 2) {
330 if (++length
> n
) return (-1);
332 wide
= (wide
<< 8 | tch
);
340 if (_des_states
[G3
].width
== 2) {
342 if (++length
> n
) return (-1);
344 wide
= (wide
<< 8 | tch
);
352 /* shoult be internal error */
357 wide
&= 0x7F7F; /* strip off the top bit */
365 #define MAXMBSIZE 128
370 _mbstowcs_iso(wchar_t *pwcs
, unsigned char *s
, size_t n
)
377 * If pwcs == 0, do nothing.
384 _savestates(); _initializestates();
386 ret1
= _mbtowc_iso (&pwc
, (char *)s
, MAXMBSIZE
);
388 return (-1); /* error */
389 if (ret1
== 0 || pwc
== 0) {
398 s
= s
+ ret1
; /* increment the pointer */
413 _wctomb_iso(unsigned char *s
, wchar_t pwc
)
416 unsigned char tch
; /* temporary use */
417 unsigned char *us
= (unsigned char *)s
;
418 int gen_wide_state
= USE_STATE
; /* used in gen_wide: */
423 unsigned char buf
[MAXSIZE
];
428 isowidth_t
* isoinfo
= (isowidth_t
*) _code_set_info
.code_info
;
431 * If pwc is 0, do this first.
443 mode
= pwc
& G3MASK
; /* The mode of this character */
444 if (((pwc
>> 8) & 0x007f) == 0)
451 if (_my_env
== BIT7ENV
)
455 printf ("csize = %d, prevcsize = %d, (%x,%x) ",csize
, prevcsize
, (pwc
>>8)&0x00ff, pwc
&0x00ff);
458 printf ("G0"); break;
460 printf ("G1"); break;
462 printf ("G2"); break;
464 printf ("G3"); break;
466 printf ("XXXX"); break;
471 case BIT7ENV
: /* 7 bit environment */
474 if (_currentOUT
!= G0
|| prevcsize
!= csize
) {
478 * Emit escape sequences
488 * Emit escape sequences
499 *bp
++ = pwc
& 0x007f;
503 *bp
++ = (pwc
& 0x7f00) >> 8;
505 *bp
++ = pwc
& 0x007f;
510 if (_currentOUT
!= G1
|| prevcsize
!= csize
) {
514 * Emit escape sequences
524 * Emit escape sequences
535 *bp
++ = pwc
& 0x007f;
539 *bp
++ = (pwc
& 0x7f00) >> 8;
541 *bp
++ = pwc
& 0x007f;
546 if (_currentOUT
!= G2
|| prevcsize
!= csize
) {
550 * Emit escape sequences
560 * Emit escape sequences
567 *bp
++ = ESC
; *bp
++ = LS2
;
571 *bp
++ = pwc
& 0x007f;
575 *bp
++ = (pwc
& 0x7f00) >> 8;
577 *bp
++ = pwc
& 0x007f;
582 if (_currentOUT
!= G3
|| prevcsize
!= csize
) {
586 * Emit escape sequences
596 * Emit escape sequences
603 *bp
++ = ESC
; *bp
++ = LS3
;
607 *bp
++ = pwc
& 0x007f;
611 *bp
++ = (pwc
& 0x7f00) >> 8;
613 *bp
++ = pwc
& 0x007f;
619 case BIT8ENV
: /* 8 bit environment */
622 if (_currentOUT
!= G0
|| prevcsize
!= csize
) {
626 * Emit escape sequences
636 * Emit escape sequences
647 *bp
++ = pwc
& 0x007f;
651 *bp
++ = (pwc
& 0x7f00) >> 8;
653 *bp
++ = pwc
& 0x007f;
658 if (_currentOUT
!= G1
|| prevcsize
!= csize
) {
662 * Emit escape sequences
672 * Emit escape sequences
679 *bp
++ = ESC
; *bp
++ = LS1R
;
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.
691 *bp
++ = pwc
& 0x00ff;
695 *bp
++ = (pwc
& 0xff00) >> 8;
697 *bp
++ = pwc
& 0x00ff;
702 if (_currentOUT
!= G2
|| prevcsize
!= csize
) {
706 * Emit escape sequences
716 * Emit escape sequences
723 *bp
++ = ESC
; *bp
++ = LS2R
;
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.
734 *bp
++ = pwc
& 0x00ff;
738 *bp
++ = (pwc
& 0xff00) >> 8;
740 *bp
++ = pwc
& 0x00ff;
745 if (_currentOUT
!= G3
|| prevcsize
!= csize
) {
749 * Emit escape sequences
759 * Emit escape sequences
766 *bp
++ = ESC
; *bp
++ = LS3R
;
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.
777 *bp
++ = pwc
& 0x00ff;
781 *bp
++ = (pwc
& 0xff00) >> 8;
783 *bp
++ = pwc
& 0x00ff;
789 default: /* Should never happens */
797 return (-1); /* buffer too small */
799 for (i
= 0; i
< length
; i
++) {
804 for (i
= 0; i
< length
; i
++) {
805 printf ("%x,", buf
[i
]);
816 _wcstombs_iso(char *s
, wchar_t *pwcs
, int n
)
819 char buf
[MMB_CUR_MAX
];
828 _savestates(); _initializestates();
830 ret1
= _wctomb_iso ((unsigned char *)buf
, *pwcs
);
834 if (ret1
== 1 && buf
[0] == 0) {
848 for (i
= 0; i
< ret1
; i
++)
866 * Supplementary routines
870 _initializestates(void)
875 _des_states
[G0
].width
= -1; /* This makes it Initialize */
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;
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
;
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
;