Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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	"big5.h"
13
 
14
/*
15
	a state machine for interpreting big5 (hk format).
16
*/
17
void
18
big5proc(int c, Rune **r, long input_loc)
19
{
20
	static enum { state0, state1 } state = state0;
21
	static int lastc;
22
	long n, ch, f, cold = c;
23
 
24
	switch(state)
25
	{
26
	case state0:	/* idle state */
27
		if(c < 0)
28
			return;
29
		if(c >= 0xA1){
30
			lastc = c;
31
			state = state1;
32
			return;
33
		}
34
		if(c == 26)
35
			c = '\n';
36
		emit(c);
37
		return;
38
 
39
	case state1:	/* seen a font spec */
40
		if(c >= 64 && c <= 126)
41
			c -= 64;
42
		else if(c >= 161 && c <= 254)
43
			c = c-161 + 63;
44
		else {
45
			nerrors++;
46
			if(squawk)
47
				EPR "%s: bad big5 glyph (from 0x%x,0x%lx) near byte %ld in %s\n",
48
					argv0, lastc, cold, input_loc, file);
49
			if(!clean)
50
				emit(BADMAP);
51
			state = state0;
52
			return;
53
		}
54
		if(lastc >= 161 && lastc <= 254)
55
			f = lastc - 161;
56
		else {
57
			nerrors++;
58
			if(squawk)
59
				EPR "%s: bad big5 font %d (from 0x%x,0x%lx) near byte %ld in %s\n",
60
					argv0, lastc-161, lastc, cold, input_loc, file);
61
			if(!clean)
62
				emit(BADMAP);
63
			state = state0;
64
			return;
65
		}
66
		n = f*BIG5FONT + c;
67
		if(n < BIG5MAX)
68
			ch = tabbig5[n];
69
		else
70
			ch = -1;
71
		if(ch < 0){
72
			nerrors++;
73
			if(squawk)
74
				EPR "%s: unknown big5 %ld (from 0x%x,0x%lx) near byte %ld in %s\n",
75
					argv0, n, lastc, cold, input_loc, file);
76
			if(!clean)
77
				emit(BADMAP);
78
		} else
79
			emit(ch);
80
		state = state0;
81
	}
82
}
83
 
84
void
85
big5_in(int fd, long *notused, struct convert *out)
86
{
87
	Rune ob[N];
88
	Rune *r, *re;
89
	uchar ibuf[N];
90
	int n, i;
91
	long nin;
92
 
93
	USED(notused);
94
	r = ob;
95
	re = ob+N-3;
96
	nin = 0;
97
	while((n = read(fd, ibuf, sizeof ibuf)) > 0){
98
		for(i = 0; i < n; i++){
99
			big5proc(ibuf[i], &r, nin++);
100
			if(r >= re){
101
				OUT(out, ob, r-ob);
102
				r = ob;
103
			}
104
		}
105
		if(r > ob){
106
			OUT(out, ob, r-ob);
107
			r = ob;
108
		}
109
	}
110
	big5proc(-1, &r, nin);
111
	if(r > ob)
112
		OUT(out, ob, r-ob);
113
	OUT(out, ob, 0);
114
}
115
 
116
void
117
big5_out(Rune *base, int n, long *notused)
118
{
119
	char *p;
120
	int i;
121
	Rune r;
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 < BIG5MAX; i++)
130
			if(tabbig5[i] != -1)
131
				tab[tabbig5[i]] = i;
132
	}
133
	nrunes += n;
134
	p = obuf;
135
	for(i = 0; i < n; i++){
136
		r = base[i];
137
		if(r < 128)
138
			*p++ = r;
139
		else {
140
			if(tab[r] != -1){
141
				r = tab[r];
142
				if(r >= BIG5MAX){
143
					*p++ = 0xA1;
144
					*p++ = r-BIG5MAX;
145
					continue;
146
				} else {
147
					*p++ = 0xA1 + (r/BIG5FONT);
148
					r = r%BIG5FONT;
149
					if(r <= 62) r += 64;
150
					else r += 0xA1-63;
151
					*p++ = r;
152
					continue;
153
				}
154
			}
155
			if(squawk)
156
				EPR "%s: rune 0x%x not in output cs\n", argv0, r);
157
			nerrors++;
158
			if(clean)
159
				continue;
160
			*p++ = BYTEBADMAP;
161
		}
162
	}
163
	noutput += p-obuf;
164
	if(p > obuf)
165
		write(1, obuf, p-obuf);
166
}