aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/tcs/conv_ksc.c
blob: da1ebe0a3a1908e9a644677c537e80fe29e79cb3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#ifdef	PLAN9
#include	<u.h>
#include	<libc.h>
#include	<bio.h>
#else
#include	<stdio.h>
#include	<unistd.h>
#include	"plan9.h"
#endif
#include	"hdr.h"
#include	"conv.h"
#include	"ksc.h"

/*
	contributed by kuro@vodka.Eng.Sun.COM (Teruhiko Kurosaka)
*/

/*
	a state machine for interpreting shift-ksc.
*/

#define	SS2	0x8e
#define	SS3	0x8f
/*
 * Convert EUC in Koran locale to Unicode.
 * Only codeset 0 and 1 are used.
 */
void
ukscproc(int c, Rune **r, long input_loc)
{
	static enum { init, cs1last /*, cs2, cs3first, cs3last*/} state = init;
	static int korean646 = 1; /* fixed to 1 for now. */
	static int lastc;
	int n;
	long l;

	switch(state)
	{
	case init:
		if (c < 0){
			return;
		}else if (c < 128){
			if(korean646 && (c=='\\')){
				emit(0x20A9);
			} else {
				emit(c);
			}
/*		}else if (c==SS2){
			state = cs2;
		}else if (c==SS3){
			state = cs3first;
 */		}else{
			lastc = c;
			state = cs1last;
		}
		return;

	case cs1last: /* 2nd byte of codeset 1 (KSC 5601) */
		if(c < 0){
			if(squawk)
				EPR "%s: unexpected EOF in %s\n", argv0, file);
			c = 0x21 | (lastc&0x80);
		}
		n = ((lastc&0x7f)-33)*94 + (c&0x7f)-33;
 		if((n >= ksc5601max) || ((l = tabksc5601[n]) < 0)){
			nerrors++;
			if(squawk)
				EPR "%s: unknown ksc5601 %d (from 0x%x,0x%x) near byte %ld in %s\n", argv0, n, lastc, c, input_loc, file);
			if(!clean)
				emit(BADMAP);
		} else {
			emit(l);
		}
		state = init;
		return;
	default:
		if(squawk)
			EPR "%s: ukscproc: unknown state %d\n",
				argv0, init);
	}
}

void
uksc_in(int fd, long *notused, struct convert *out)
{
	Rune ob[N];
	Rune *r, *re;
	uchar ibuf[N];
	int n, i;
	long nin;

	USED(notused);
	r = ob;
	re = ob+N-3;
	nin = 0;
	while((n = read(fd, ibuf, sizeof ibuf)) > 0){
		for(i = 0; i < n; i++){
			ukscproc(ibuf[i], &r, nin++);
			if(r >= re){
				OUT(out, ob, r-ob);
				r = ob;
			}
		}
		if(r > ob){
			OUT(out, ob, r-ob);
			r = ob;
		}
	}
	ukscproc(-1, &r, nin);
	if(r > ob)
		OUT(out, ob, r-ob);
	OUT(out, ob, 0);
}

void
uksc_out(Rune *base, int n, long *notused)
{
	char *p;
	int i;
	Rune r;
	long l;
	static int first = 1;

	USED(notused);
	if(first){
		first = 0;
		for(i = 0; i < NRUNE; i++)
			tab[i] = -1;
		for(i = 0; i < ksc5601max; i++)
			if((l = tabksc5601[i]) != -1){
				if(l < 0)
					tab[-l] = i;
				else
					tab[l] = i;
			}
	}
	nrunes += n;
	p = obuf;
	for(i = 0; i < n; i++){
		r = base[i];
		if(r < 128)
			*p++ = r;
		else {
			if(tab[r] != -1){
				*p++ = 0x80 | (tab[r]/94 + 0x21);
				*p++ = 0x80 | (tab[r]%94 + 0x21);
				continue;
			}
			if(squawk)
				EPR "%s: rune 0x%x not in output cs\n", argv0, r);
			nerrors++;
			if(clean)
				continue;
			*p++ = BYTEBADMAP;
		}
	}
	noutput += p-obuf;
	if(p > obuf)
		write(1, obuf, p-obuf);
}