xref: /plan9-contrib/sys/src/cmd/tcs/conv_ksc.c (revision ec46fab06dcae3e636b775c4eaa679036316e1d8)
1 #ifdef	PLAN9
2 #include	<u.h>
3 #include	<libc.h>
4 #include	<bio.h>
5 #else
6 #include	<stdio.h>
7 #include	<unistd.h>
8 #include	"plan9.h"
9 #endif
10 #include	"hdr.h"
11 #include	"conv.h"
12 #include	"ksc.h"
13 
14 /*
15 	contributed by kuro@vodka.Eng.Sun.COM (Teruhiko Kurosaka)
16 */
17 
18 /*
19 	a state machine for interpreting shift-ksc.
20 */
21 
22 #define	SS2	0x8e
23 #define	SS3	0x8f
24 /*
25  * Convert EUC in Koran locale to Unicode.
26  * Only codeset 0 and 1 are used.
27  */
28 void
ukscproc(int c,Rune ** r,long input_loc)29 ukscproc(int c, Rune **r, long input_loc)
30 {
31 	static enum { init, cs1last /*, cs2, cs3first, cs3last*/} state = init;
32 	static int korean646 = 1; /* fixed to 1 for now. */
33 	static int lastc;
34 	int n;
35 	long l;
36 
37 	switch(state)
38 	{
39 	case init:
40 		if (c < 0){
41 			return;
42 		}else if (c < 128){
43 			if(korean646 && (c=='\\')){
44 				emit(0x20A9);
45 			} else {
46 				emit(c);
47 			}
48 /*		}else if (c==SS2){
49 			state = cs2;
50 		}else if (c==SS3){
51 			state = cs3first;
52  */		}else{
53 			lastc = c;
54 			state = cs1last;
55 		}
56 		return;
57 
58 	case cs1last: /* 2nd byte of codeset 1 (KSC 5601) */
59 		if(c < 0){
60 			if(squawk)
61 				EPR "%s: unexpected EOF in %s\n", argv0, file);
62 			c = 0x21 | (lastc&0x80);
63 		}
64 		n = ((lastc&0x7f)-33)*94 + (c&0x7f)-33;
65  		if((n >= ksc5601max) || ((l = tabksc5601[n]) < 0)){
66 			nerrors++;
67 			if(squawk)
68 				EPR "%s: unknown ksc5601 %d (from 0x%x,0x%x) near byte %ld in %s\n", argv0, n, lastc, c, input_loc, file);
69 			if(!clean)
70 				emit(BADMAP);
71 		} else {
72 			emit(l);
73 		}
74 		state = init;
75 		return;
76 	default:
77 		if(squawk)
78 			EPR "%s: ukscproc: unknown state %d\n",
79 				argv0, init);
80 	}
81 }
82 
83 void
uksc_in(int fd,long * notused,struct convert * out)84 uksc_in(int fd, long *notused, struct convert *out)
85 {
86 	Rune ob[N];
87 	Rune *r, *re;
88 	uchar ibuf[N];
89 	int n, i;
90 	long nin;
91 
92 	USED(notused);
93 	r = ob;
94 	re = ob+N-3;
95 	nin = 0;
96 	while((n = read(fd, ibuf, sizeof ibuf)) > 0){
97 		for(i = 0; i < n; i++){
98 			ukscproc(ibuf[i], &r, nin++);
99 			if(r >= re){
100 				OUT(out, ob, r-ob);
101 				r = ob;
102 			}
103 		}
104 		if(r > ob){
105 			OUT(out, ob, r-ob);
106 			r = ob;
107 		}
108 	}
109 	ukscproc(-1, &r, nin);
110 	if(r > ob)
111 		OUT(out, ob, r-ob);
112 	OUT(out, ob, 0);
113 }
114 
115 void
uksc_out(Rune * base,int n,long * notused)116 uksc_out(Rune *base, int n, long *notused)
117 {
118 	char *p;
119 	int i;
120 	Rune r;
121 	long l;
122 	static int first = 1;
123 
124 	USED(notused);
125 	if(first){
126 		first = 0;
127 		for(i = 0; i < NRUNE; i++)
128 			tab[i] = -1;
129 		for(i = 0; i < ksc5601max; i++)
130 			if((l = tabksc5601[i]) != -1){
131 				if(l < 0)
132 					tab[-l] = i;
133 				else
134 					tab[l] = i;
135 			}
136 	}
137 	nrunes += n;
138 	p = obuf;
139 	for(i = 0; i < n; i++){
140 		r = base[i];
141 		if(r < 128)
142 			*p++ = r;
143 		else {
144 			if(tab[r] != -1){
145 				*p++ = 0x80 | (tab[r]/94 + 0x21);
146 				*p++ = 0x80 | (tab[r]%94 + 0x21);
147 				continue;
148 			}
149 			if(squawk)
150 				EPR "%s: rune 0x%x not in output cs\n", argv0, r);
151 			nerrors++;
152 			if(clean)
153 				continue;
154 			*p++ = BYTEBADMAP;
155 		}
156 	}
157 	noutput += p-obuf;
158 	if(p > obuf)
159 		write(1, obuf, p-obuf);
160 }
161 
162