Blob


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"
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;
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;
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 }
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;
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;
105 if(r > ob){
106 OUT(out, ob, r-ob);
107 r = ob;
110 big5proc(-1, &r, nin);
111 if(r > ob)
112 OUT(out, ob, r-ob);
113 OUT(out, ob, 0);
116 void
117 big5_out(Rune *base, int n, long *notused)
119 char *p;
120 int i;
121 Rune r;
122 static int first = 1;
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;
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++ = (char)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;
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;
163 noutput += p-obuf;
164 if(p > obuf)
165 write(1, obuf, p-obuf);