xref: /plan9-contrib/sys/src/cmd/tcs/conv_ksc.c (revision ec46fab06dcae3e636b775c4eaa679036316e1d8)
1219b2ee8SDavid du Colombier #ifdef	PLAN9
2219b2ee8SDavid du Colombier #include	<u.h>
3219b2ee8SDavid du Colombier #include	<libc.h>
4219b2ee8SDavid du Colombier #include	<bio.h>
5219b2ee8SDavid du Colombier #else
6219b2ee8SDavid du Colombier #include	<stdio.h>
7219b2ee8SDavid du Colombier #include	<unistd.h>
8219b2ee8SDavid du Colombier #include	"plan9.h"
9219b2ee8SDavid du Colombier #endif
10219b2ee8SDavid du Colombier #include	"hdr.h"
11219b2ee8SDavid du Colombier #include	"conv.h"
12219b2ee8SDavid du Colombier #include	"ksc.h"
13219b2ee8SDavid du Colombier 
14219b2ee8SDavid du Colombier /*
15219b2ee8SDavid du Colombier 	contributed by kuro@vodka.Eng.Sun.COM (Teruhiko Kurosaka)
16219b2ee8SDavid du Colombier */
17219b2ee8SDavid du Colombier 
18219b2ee8SDavid du Colombier /*
19219b2ee8SDavid du Colombier 	a state machine for interpreting shift-ksc.
20219b2ee8SDavid du Colombier */
21219b2ee8SDavid du Colombier 
22219b2ee8SDavid du Colombier #define	SS2	0x8e
23219b2ee8SDavid du Colombier #define	SS3	0x8f
24219b2ee8SDavid du Colombier /*
25219b2ee8SDavid du Colombier  * Convert EUC in Koran locale to Unicode.
26219b2ee8SDavid du Colombier  * Only codeset 0 and 1 are used.
27219b2ee8SDavid du Colombier  */
28219b2ee8SDavid du Colombier void
ukscproc(int c,Rune ** r,long input_loc)29219b2ee8SDavid du Colombier ukscproc(int c, Rune **r, long input_loc)
30219b2ee8SDavid du Colombier {
31219b2ee8SDavid du Colombier 	static enum { init, cs1last /*, cs2, cs3first, cs3last*/} state = init;
32219b2ee8SDavid du Colombier 	static int korean646 = 1; /* fixed to 1 for now. */
33219b2ee8SDavid du Colombier 	static int lastc;
34219b2ee8SDavid du Colombier 	int n;
35219b2ee8SDavid du Colombier 	long l;
36219b2ee8SDavid du Colombier 
37219b2ee8SDavid du Colombier 	switch(state)
38219b2ee8SDavid du Colombier 	{
39219b2ee8SDavid du Colombier 	case init:
40219b2ee8SDavid du Colombier 		if (c < 0){
41219b2ee8SDavid du Colombier 			return;
42219b2ee8SDavid du Colombier 		}else if (c < 128){
43219b2ee8SDavid du Colombier 			if(korean646 && (c=='\\')){
44219b2ee8SDavid du Colombier 				emit(0x20A9);
45219b2ee8SDavid du Colombier 			} else {
46219b2ee8SDavid du Colombier 				emit(c);
47219b2ee8SDavid du Colombier 			}
48219b2ee8SDavid du Colombier /*		}else if (c==SS2){
49219b2ee8SDavid du Colombier 			state = cs2;
50219b2ee8SDavid du Colombier 		}else if (c==SS3){
51219b2ee8SDavid du Colombier 			state = cs3first;
52219b2ee8SDavid du Colombier  */		}else{
53219b2ee8SDavid du Colombier 			lastc = c;
54219b2ee8SDavid du Colombier 			state = cs1last;
55219b2ee8SDavid du Colombier 		}
56219b2ee8SDavid du Colombier 		return;
57219b2ee8SDavid du Colombier 
58219b2ee8SDavid du Colombier 	case cs1last: /* 2nd byte of codeset 1 (KSC 5601) */
59219b2ee8SDavid du Colombier 		if(c < 0){
60219b2ee8SDavid du Colombier 			if(squawk)
61219b2ee8SDavid du Colombier 				EPR "%s: unexpected EOF in %s\n", argv0, file);
62219b2ee8SDavid du Colombier 			c = 0x21 | (lastc&0x80);
63219b2ee8SDavid du Colombier 		}
64219b2ee8SDavid du Colombier 		n = ((lastc&0x7f)-33)*94 + (c&0x7f)-33;
65219b2ee8SDavid du Colombier  		if((n >= ksc5601max) || ((l = tabksc5601[n]) < 0)){
66219b2ee8SDavid du Colombier 			nerrors++;
67219b2ee8SDavid du Colombier 			if(squawk)
68219b2ee8SDavid du Colombier 				EPR "%s: unknown ksc5601 %d (from 0x%x,0x%x) near byte %ld in %s\n", argv0, n, lastc, c, input_loc, file);
69219b2ee8SDavid du Colombier 			if(!clean)
70219b2ee8SDavid du Colombier 				emit(BADMAP);
71219b2ee8SDavid du Colombier 		} else {
72219b2ee8SDavid du Colombier 			emit(l);
73219b2ee8SDavid du Colombier 		}
74219b2ee8SDavid du Colombier 		state = init;
75219b2ee8SDavid du Colombier 		return;
76219b2ee8SDavid du Colombier 	default:
77219b2ee8SDavid du Colombier 		if(squawk)
78219b2ee8SDavid du Colombier 			EPR "%s: ukscproc: unknown state %d\n",
79219b2ee8SDavid du Colombier 				argv0, init);
80219b2ee8SDavid du Colombier 	}
81219b2ee8SDavid du Colombier }
82219b2ee8SDavid du Colombier 
83219b2ee8SDavid du Colombier void
uksc_in(int fd,long * notused,struct convert * out)84219b2ee8SDavid du Colombier uksc_in(int fd, long *notused, struct convert *out)
85219b2ee8SDavid du Colombier {
86219b2ee8SDavid du Colombier 	Rune ob[N];
87219b2ee8SDavid du Colombier 	Rune *r, *re;
88219b2ee8SDavid du Colombier 	uchar ibuf[N];
89219b2ee8SDavid du Colombier 	int n, i;
90219b2ee8SDavid du Colombier 	long nin;
91219b2ee8SDavid du Colombier 
92219b2ee8SDavid du Colombier 	USED(notused);
93219b2ee8SDavid du Colombier 	r = ob;
94219b2ee8SDavid du Colombier 	re = ob+N-3;
95219b2ee8SDavid du Colombier 	nin = 0;
96219b2ee8SDavid du Colombier 	while((n = read(fd, ibuf, sizeof ibuf)) > 0){
97219b2ee8SDavid du Colombier 		for(i = 0; i < n; i++){
98219b2ee8SDavid du Colombier 			ukscproc(ibuf[i], &r, nin++);
99219b2ee8SDavid du Colombier 			if(r >= re){
100219b2ee8SDavid du Colombier 				OUT(out, ob, r-ob);
101219b2ee8SDavid du Colombier 				r = ob;
102219b2ee8SDavid du Colombier 			}
103219b2ee8SDavid du Colombier 		}
104219b2ee8SDavid du Colombier 		if(r > ob){
105219b2ee8SDavid du Colombier 			OUT(out, ob, r-ob);
106219b2ee8SDavid du Colombier 			r = ob;
107219b2ee8SDavid du Colombier 		}
108219b2ee8SDavid du Colombier 	}
109219b2ee8SDavid du Colombier 	ukscproc(-1, &r, nin);
110219b2ee8SDavid du Colombier 	if(r > ob)
111219b2ee8SDavid du Colombier 		OUT(out, ob, r-ob);
112*ec46fab0SDavid du Colombier 	OUT(out, ob, 0);
113219b2ee8SDavid du Colombier }
114219b2ee8SDavid du Colombier 
115219b2ee8SDavid du Colombier void
uksc_out(Rune * base,int n,long * notused)116219b2ee8SDavid du Colombier uksc_out(Rune *base, int n, long *notused)
117219b2ee8SDavid du Colombier {
118219b2ee8SDavid du Colombier 	char *p;
119219b2ee8SDavid du Colombier 	int i;
120219b2ee8SDavid du Colombier 	Rune r;
121219b2ee8SDavid du Colombier 	long l;
122219b2ee8SDavid du Colombier 	static int first = 1;
123219b2ee8SDavid du Colombier 
124219b2ee8SDavid du Colombier 	USED(notused);
125219b2ee8SDavid du Colombier 	if(first){
126219b2ee8SDavid du Colombier 		first = 0;
127219b2ee8SDavid du Colombier 		for(i = 0; i < NRUNE; i++)
128219b2ee8SDavid du Colombier 			tab[i] = -1;
129219b2ee8SDavid du Colombier 		for(i = 0; i < ksc5601max; i++)
130219b2ee8SDavid du Colombier 			if((l = tabksc5601[i]) != -1){
131219b2ee8SDavid du Colombier 				if(l < 0)
132219b2ee8SDavid du Colombier 					tab[-l] = i;
133219b2ee8SDavid du Colombier 				else
134219b2ee8SDavid du Colombier 					tab[l] = i;
135219b2ee8SDavid du Colombier 			}
136219b2ee8SDavid du Colombier 	}
137219b2ee8SDavid du Colombier 	nrunes += n;
138219b2ee8SDavid du Colombier 	p = obuf;
139219b2ee8SDavid du Colombier 	for(i = 0; i < n; i++){
140219b2ee8SDavid du Colombier 		r = base[i];
141219b2ee8SDavid du Colombier 		if(r < 128)
142219b2ee8SDavid du Colombier 			*p++ = r;
143219b2ee8SDavid du Colombier 		else {
144219b2ee8SDavid du Colombier 			if(tab[r] != -1){
145219b2ee8SDavid du Colombier 				*p++ = 0x80 | (tab[r]/94 + 0x21);
146219b2ee8SDavid du Colombier 				*p++ = 0x80 | (tab[r]%94 + 0x21);
147219b2ee8SDavid du Colombier 				continue;
148219b2ee8SDavid du Colombier 			}
149219b2ee8SDavid du Colombier 			if(squawk)
150219b2ee8SDavid du Colombier 				EPR "%s: rune 0x%x not in output cs\n", argv0, r);
151219b2ee8SDavid du Colombier 			nerrors++;
152219b2ee8SDavid du Colombier 			if(clean)
153219b2ee8SDavid du Colombier 				continue;
154219b2ee8SDavid du Colombier 			*p++ = BYTEBADMAP;
155219b2ee8SDavid du Colombier 		}
156219b2ee8SDavid du Colombier 	}
157219b2ee8SDavid du Colombier 	noutput += p-obuf;
158219b2ee8SDavid du Colombier 	if(p > obuf)
159219b2ee8SDavid du Colombier 		write(1, obuf, p-obuf);
160219b2ee8SDavid du Colombier }
161219b2ee8SDavid du Colombier 
162