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
|
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "hdr.h"
#include "conv.h"
#include "gb.h"
/*
a state machine for interpreting gb.
*/
void
gbproc(int c, Rune **r, long input_loc)
{
static enum { state0, state1 } state = state0;
static int lastc;
long n, ch, cold = c;
switch(state)
{
case state0: /* idle state */
if(c < 0)
return;
if(c >= 0xA1){
lastc = c;
state = state1;
return;
}
emit(c);
return;
case state1: /* seen a font spec */
if(c >= 0xA1)
n = (lastc-0xA0)*100 + (c-0xA0);
else {
nerrors++;
if(squawk)
warn("bad gb glyph %d (from 0x%x,0x%lx) near byte %ld in %s", c-0xA0, lastc, cold, input_loc, file);
if(!clean)
emit(BADMAP);
state = state0;
return;
}
ch = tabgb[n];
if(ch < 0){
nerrors++;
if(squawk)
warn("unknown gb %ld (from 0x%x,0x%lx) near byte %ld in %s", n, lastc, cold, input_loc, file);
if(!clean)
emit(BADMAP);
} else
emit(ch);
state = state0;
}
}
void
gb_in(int fd, long *, struct convert *out)
{
Rune ob[N];
Rune *r, *re;
uchar ibuf[N];
int n, i;
long nin;
r = ob;
re = ob+N-3;
nin = 0;
while((n = read(fd, ibuf, sizeof ibuf)) > 0){
for(i = 0; i < n; i++){
gbproc(ibuf[i], &r, nin++);
if(r >= re){
OUT(out, ob, r-ob);
r = ob;
}
}
if(r > ob){
OUT(out, ob, r-ob);
r = ob;
}
}
gbproc(-1, &r, nin);
if(r > ob)
OUT(out, ob, r-ob);
OUT(out, ob, 0);
}
void
gb_out(Rune *base, int n, long *)
{
char *p;
int i;
Rune r;
static int first = 1;
if(first){
first = 0;
for(i = 0; i < NRUNE; i++)
tab[i] = -1;
for(i = 0; i < GBMAX; i++)
if(tabgb[i] != -1)
tab[tabgb[i]] = i;
}
nrunes += n;
p = obuf;
for(i = 0; i < n; i++){
r = base[i];
if(r < 128)
*p++ = r;
else {
if(r < NRUNE && tab[r] != -1){
r = tab[r];
*p++ = 0xA0 + (r/100);
*p++ = 0xA0 + (r%100);
continue;
}
if(squawk)
warn("rune 0x%x not in output cs", r);
nerrors++;
if(clean)
continue;
*p++ = BYTEBADMAP;
}
}
noutput += p-obuf;
if(p > obuf)
write(1, obuf, p-obuf);
}
|