]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/tcs/conv_big5.c
stats: show amount of reclaimable pages (add -r flag)
[plan9front.git] / sys / src / cmd / tcs / conv_big5.c
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 *, 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         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                         big5proc(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         big5proc(-1, &r, nin);
110         if(r > ob)
111                 OUT(out, ob, r-ob);
112         OUT(out, ob, 0);
113 }
114
115 void
116 big5_out(Rune *base, int n, long *)
117 {
118         char *p;
119         int i;
120         Rune r;
121         static int first = 1;
122
123         if(first){
124                 first = 0;
125                 for(i = 0; i < NRUNE; i++)
126                         tab[i] = -1;
127                 for(i = 0; i < BIG5MAX; i++)
128                         if(tabbig5[i] != -1)
129                                 tab[tabbig5[i]] = i;
130         }
131         nrunes += n;
132         p = obuf;
133         for(i = 0; i < n; i++){
134                 r = base[i];
135                 if(r < 128)
136                         *p++ = r;
137                 else {
138                         if(r < NRUNE && tab[r] != -1){
139                                 r = tab[r];
140                                 if(r >= BIG5MAX){
141                                         *p++ = 0xA1;
142                                         *p++ = r-BIG5MAX;
143                                         continue;
144                                 } else {
145                                         *p++ = 0xA1 + (r/BIG5FONT);
146                                         r = r%BIG5FONT;
147                                         if(r <= 62) r += 64;
148                                         else r += 0xA1-63;
149                                         *p++ = r;
150                                         continue;
151                                 }
152                         }
153                         if(squawk)
154                                 EPR "%s: rune 0x%x not in output cs\n", argv0, r);
155                         nerrors++;
156                         if(clean)
157                                 continue;
158                         *p++ = BYTEBADMAP;
159                 }
160         }
161         noutput += p-obuf;
162         if(p > obuf)
163                 write(1, obuf, p-obuf);
164 }