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 "gbk.h"
13
14 static void
gbkproc(int c,Rune ** r,long input_loc)15 gbkproc(int c, Rune **r, long input_loc)
16 {
17 static enum { state0, state1 } state = state0;
18 static int lastc;
19 long ch, cold = c;
20
21 switch(state)
22 {
23 case state0: /* idle state */
24 if(c < 0)
25 return;
26 if(c >= 0x80){
27 lastc = c;
28 state = state1;
29 return;
30 }
31 emit(c);
32 return;
33
34 case state1: /* seen a font spec */
35 ch = -1;
36 c = lastc<<8 | c;
37 if(c >= GBKMIN && c < GBKMAX)
38 ch = tabgbk[c - GBKMIN];
39 if(ch < 0){
40 nerrors++;
41 if(squawk)
42 EPR "%s: bad gbk glyph %d (from 0x%x,0x%lx) near byte %ld in %s\n", argv0, (c & 0xFF), lastc, cold, input_loc, file);
43 if(!clean)
44 emit(BADMAP);
45 state = state0;
46 return;
47 }
48 emit(ch);
49 state = state0;
50 }
51 }
52
53 void
gbk_in(int fd,long * notused,struct convert * out)54 gbk_in(int fd, long *notused, struct convert *out)
55 {
56 Rune ob[N];
57 Rune *r, *re;
58 uchar ibuf[N];
59 int n, i;
60 long nin;
61
62 USED(notused);
63 r = ob;
64 re = ob+N-3;
65 nin = 0;
66 while((n = read(fd, ibuf, sizeof ibuf)) > 0){
67 for(i = 0; i < n; i++){
68 gbkproc(ibuf[i], &r, nin++);
69 if(r >= re){
70 OUT(out, ob, r-ob);
71 r = ob;
72 }
73 }
74 if(r > ob){
75 OUT(out, ob, r-ob);
76 r = ob;
77 }
78 }
79 gbkproc(-1, &r, nin);
80 if(r > ob)
81 OUT(out, ob, r-ob);
82 OUT(out, ob, 0);
83 }
84
85
86 void
gbk_out(Rune * base,int n,long * notused)87 gbk_out(Rune *base, int n, long *notused)
88 {
89 char *p;
90 int i;
91 Rune r;
92 static int first = 1;
93
94 USED(notused);
95 if(first){
96 first = 0;
97 for(i = 0; i < NRUNE; i++)
98 tab[i] = -1;
99 for(i = GBKMIN; i < GBKMAX; i++)
100 tab[tabgbk[i-GBKMIN]] = i;
101 }
102 nrunes += n;
103 p = obuf;
104 for(i = 0; i < n; i++){
105 r = base[i];
106 if(r < 0x80)
107 *p++ = r;
108 else {
109 if(tab[r] != -1){
110 r = tab[r];
111 *p++ = (r>>8) & 0xFF;
112 *p++ = r & 0xFF;
113 continue;
114 }
115 if(squawk)
116 EPR "%s: rune 0x%x not in output cs\n", argv0, r);
117 nerrors++;
118 if(clean)
119 continue;
120 *p++ = BYTEBADMAP;
121 }
122 }
123 noutput += p-obuf;
124 if(p > obuf)
125 write(1, obuf, p-obuf);
126 }
127