1*74a4d8c2SCharles.Forsyth #include <lib9.h>
2*74a4d8c2SCharles.Forsyth
3*74a4d8c2SCharles.Forsyth typedef struct PCB /* Control block controlling specification parse */
4*74a4d8c2SCharles.Forsyth {
5*74a4d8c2SCharles.Forsyth char *base; /* start of specification */
6*74a4d8c2SCharles.Forsyth char *current; /* current parse point */
7*74a4d8c2SCharles.Forsyth long last; /* last Rune returned */
8*74a4d8c2SCharles.Forsyth long final; /* final Rune in a span */
9*74a4d8c2SCharles.Forsyth } Pcb;
10*74a4d8c2SCharles.Forsyth
11*74a4d8c2SCharles.Forsyth uchar bits[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
12*74a4d8c2SCharles.Forsyth
13*74a4d8c2SCharles.Forsyth #define SETBIT(a, c) ((a)[(c)/8] |= bits[(c)&07])
14*74a4d8c2SCharles.Forsyth #define CLEARBIT(a,c) ((a)[(c)/8] &= ~bits[(c)&07])
15*74a4d8c2SCharles.Forsyth #define BITSET(a,c) ((a)[(c)/8] & bits[(c)&07])
16*74a4d8c2SCharles.Forsyth
17*74a4d8c2SCharles.Forsyth #define MAXRUNE 0xFFFF
18*74a4d8c2SCharles.Forsyth
19*74a4d8c2SCharles.Forsyth uchar f[(MAXRUNE+1)/8];
20*74a4d8c2SCharles.Forsyth uchar t[(MAXRUNE+1)/8];
21*74a4d8c2SCharles.Forsyth char wbuf[4096];
22*74a4d8c2SCharles.Forsyth char *wptr;
23*74a4d8c2SCharles.Forsyth
24*74a4d8c2SCharles.Forsyth Pcb pfrom, pto;
25*74a4d8c2SCharles.Forsyth
26*74a4d8c2SCharles.Forsyth int cflag;
27*74a4d8c2SCharles.Forsyth int dflag;
28*74a4d8c2SCharles.Forsyth int sflag;
29*74a4d8c2SCharles.Forsyth
30*74a4d8c2SCharles.Forsyth void complement(void);
31*74a4d8c2SCharles.Forsyth void delete(void);
32*74a4d8c2SCharles.Forsyth void squeeze(void);
33*74a4d8c2SCharles.Forsyth void translit(void);
34*74a4d8c2SCharles.Forsyth void error(char*);
35*74a4d8c2SCharles.Forsyth long canon(Pcb*);
36*74a4d8c2SCharles.Forsyth char *getrune(char*, Rune*);
37*74a4d8c2SCharles.Forsyth void Pinit(Pcb*, char*);
38*74a4d8c2SCharles.Forsyth void Prewind(Pcb *p);
39*74a4d8c2SCharles.Forsyth int readrune(int, long*);
40*74a4d8c2SCharles.Forsyth void wflush(int);
41*74a4d8c2SCharles.Forsyth void writerune(int, Rune);
42*74a4d8c2SCharles.Forsyth
43*74a4d8c2SCharles.Forsyth void
main(int argc,char ** argv)44*74a4d8c2SCharles.Forsyth main(int argc, char **argv)
45*74a4d8c2SCharles.Forsyth {
46*74a4d8c2SCharles.Forsyth ARGBEGIN{
47*74a4d8c2SCharles.Forsyth case 's': sflag++; break;
48*74a4d8c2SCharles.Forsyth case 'd': dflag++; break;
49*74a4d8c2SCharles.Forsyth case 'c': cflag++; break;
50*74a4d8c2SCharles.Forsyth default: error("bad option");
51*74a4d8c2SCharles.Forsyth }ARGEND
52*74a4d8c2SCharles.Forsyth if(argc>0)
53*74a4d8c2SCharles.Forsyth Pinit(&pfrom, argv[0]);
54*74a4d8c2SCharles.Forsyth if(argc>1)
55*74a4d8c2SCharles.Forsyth Pinit(&pto, argv[1]);
56*74a4d8c2SCharles.Forsyth if(argc>2)
57*74a4d8c2SCharles.Forsyth error("arg count");
58*74a4d8c2SCharles.Forsyth if(dflag) {
59*74a4d8c2SCharles.Forsyth if ((sflag && argc != 2) || (!sflag && argc != 1))
60*74a4d8c2SCharles.Forsyth error("arg count");
61*74a4d8c2SCharles.Forsyth delete();
62*74a4d8c2SCharles.Forsyth } else {
63*74a4d8c2SCharles.Forsyth if (argc != 2)
64*74a4d8c2SCharles.Forsyth error("arg count");
65*74a4d8c2SCharles.Forsyth if (cflag)
66*74a4d8c2SCharles.Forsyth complement();
67*74a4d8c2SCharles.Forsyth else translit();
68*74a4d8c2SCharles.Forsyth }
69*74a4d8c2SCharles.Forsyth exits(0);
70*74a4d8c2SCharles.Forsyth }
71*74a4d8c2SCharles.Forsyth
72*74a4d8c2SCharles.Forsyth void
delete(void)73*74a4d8c2SCharles.Forsyth delete(void)
74*74a4d8c2SCharles.Forsyth {
75*74a4d8c2SCharles.Forsyth long c, last;
76*74a4d8c2SCharles.Forsyth
77*74a4d8c2SCharles.Forsyth if (cflag) {
78*74a4d8c2SCharles.Forsyth memset((char *) f, 0xff, sizeof f);
79*74a4d8c2SCharles.Forsyth while ((c = canon(&pfrom)) >= 0)
80*74a4d8c2SCharles.Forsyth CLEARBIT(f, c);
81*74a4d8c2SCharles.Forsyth } else {
82*74a4d8c2SCharles.Forsyth while ((c = canon(&pfrom)) >= 0)
83*74a4d8c2SCharles.Forsyth SETBIT(f, c);
84*74a4d8c2SCharles.Forsyth }
85*74a4d8c2SCharles.Forsyth if (sflag) {
86*74a4d8c2SCharles.Forsyth while ((c = canon(&pto)) >= 0)
87*74a4d8c2SCharles.Forsyth SETBIT(t, c);
88*74a4d8c2SCharles.Forsyth }
89*74a4d8c2SCharles.Forsyth
90*74a4d8c2SCharles.Forsyth last = 0x10000;
91*74a4d8c2SCharles.Forsyth while (readrune(0, &c) > 0) {
92*74a4d8c2SCharles.Forsyth if(!BITSET(f, c) && (c != last || !BITSET(t,c))) {
93*74a4d8c2SCharles.Forsyth last = c;
94*74a4d8c2SCharles.Forsyth writerune(1, (Rune) c);
95*74a4d8c2SCharles.Forsyth }
96*74a4d8c2SCharles.Forsyth }
97*74a4d8c2SCharles.Forsyth wflush(1);
98*74a4d8c2SCharles.Forsyth }
99*74a4d8c2SCharles.Forsyth
100*74a4d8c2SCharles.Forsyth void
complement(void)101*74a4d8c2SCharles.Forsyth complement(void)
102*74a4d8c2SCharles.Forsyth {
103*74a4d8c2SCharles.Forsyth Rune *p;
104*74a4d8c2SCharles.Forsyth int i;
105*74a4d8c2SCharles.Forsyth long from, to, lastc, high;
106*74a4d8c2SCharles.Forsyth
107*74a4d8c2SCharles.Forsyth lastc = 0;
108*74a4d8c2SCharles.Forsyth high = 0;
109*74a4d8c2SCharles.Forsyth while ((from = canon(&pfrom)) >= 0) {
110*74a4d8c2SCharles.Forsyth if (from > high) high = from;
111*74a4d8c2SCharles.Forsyth SETBIT(f, from);
112*74a4d8c2SCharles.Forsyth }
113*74a4d8c2SCharles.Forsyth while ((to = canon(&pto)) > 0) {
114*74a4d8c2SCharles.Forsyth if (to > high) high = to;
115*74a4d8c2SCharles.Forsyth SETBIT(t,to);
116*74a4d8c2SCharles.Forsyth }
117*74a4d8c2SCharles.Forsyth Prewind(&pto);
118*74a4d8c2SCharles.Forsyth if ((p = (Rune *) malloc((high+1)*sizeof(Rune))) == 0)
119*74a4d8c2SCharles.Forsyth error("can't allocate memory");
120*74a4d8c2SCharles.Forsyth for (i = 0; i <= high; i++){
121*74a4d8c2SCharles.Forsyth if (!BITSET(f,i)) {
122*74a4d8c2SCharles.Forsyth if ((to = canon(&pto)) < 0)
123*74a4d8c2SCharles.Forsyth to = lastc;
124*74a4d8c2SCharles.Forsyth else lastc = to;
125*74a4d8c2SCharles.Forsyth p[i] = to;
126*74a4d8c2SCharles.Forsyth }
127*74a4d8c2SCharles.Forsyth else p[i] = i;
128*74a4d8c2SCharles.Forsyth }
129*74a4d8c2SCharles.Forsyth if (sflag){
130*74a4d8c2SCharles.Forsyth lastc = 0x10000;
131*74a4d8c2SCharles.Forsyth while (readrune(0, &from) > 0) {
132*74a4d8c2SCharles.Forsyth if (from > high)
133*74a4d8c2SCharles.Forsyth from = to;
134*74a4d8c2SCharles.Forsyth else
135*74a4d8c2SCharles.Forsyth from = p[from];
136*74a4d8c2SCharles.Forsyth if (from != lastc || !BITSET(t,from)) {
137*74a4d8c2SCharles.Forsyth lastc = from;
138*74a4d8c2SCharles.Forsyth writerune(1, (Rune) from);
139*74a4d8c2SCharles.Forsyth }
140*74a4d8c2SCharles.Forsyth }
141*74a4d8c2SCharles.Forsyth
142*74a4d8c2SCharles.Forsyth } else {
143*74a4d8c2SCharles.Forsyth while (readrune(0, &from) > 0){
144*74a4d8c2SCharles.Forsyth if (from > high)
145*74a4d8c2SCharles.Forsyth from = to;
146*74a4d8c2SCharles.Forsyth else
147*74a4d8c2SCharles.Forsyth from = p[from];
148*74a4d8c2SCharles.Forsyth writerune(1, (Rune) from);
149*74a4d8c2SCharles.Forsyth }
150*74a4d8c2SCharles.Forsyth }
151*74a4d8c2SCharles.Forsyth wflush(1);
152*74a4d8c2SCharles.Forsyth }
153*74a4d8c2SCharles.Forsyth
154*74a4d8c2SCharles.Forsyth void
translit(void)155*74a4d8c2SCharles.Forsyth translit(void)
156*74a4d8c2SCharles.Forsyth {
157*74a4d8c2SCharles.Forsyth Rune *p;
158*74a4d8c2SCharles.Forsyth int i;
159*74a4d8c2SCharles.Forsyth long from, to, lastc, high;
160*74a4d8c2SCharles.Forsyth
161*74a4d8c2SCharles.Forsyth lastc = 0;
162*74a4d8c2SCharles.Forsyth high = 0;
163*74a4d8c2SCharles.Forsyth while ((from = canon(&pfrom)) >= 0)
164*74a4d8c2SCharles.Forsyth if (from > high) high = from;
165*74a4d8c2SCharles.Forsyth Prewind(&pfrom);
166*74a4d8c2SCharles.Forsyth if ((p = (Rune *) malloc((high+1)*sizeof(Rune))) == 0)
167*74a4d8c2SCharles.Forsyth error("can't allocate memory");
168*74a4d8c2SCharles.Forsyth for (i = 0; i <= high; i++)
169*74a4d8c2SCharles.Forsyth p[i] = i;
170*74a4d8c2SCharles.Forsyth while ((from = canon(&pfrom)) >= 0) {
171*74a4d8c2SCharles.Forsyth if ((to = canon(&pto)) < 0)
172*74a4d8c2SCharles.Forsyth to = lastc;
173*74a4d8c2SCharles.Forsyth else lastc = to;
174*74a4d8c2SCharles.Forsyth if (BITSET(f,from) && p[from] != to)
175*74a4d8c2SCharles.Forsyth error("ambiguous translation");
176*74a4d8c2SCharles.Forsyth SETBIT(f,from);
177*74a4d8c2SCharles.Forsyth p[from] = to;
178*74a4d8c2SCharles.Forsyth SETBIT(t,to);
179*74a4d8c2SCharles.Forsyth }
180*74a4d8c2SCharles.Forsyth while ((to = canon(&pto)) >= 0) {
181*74a4d8c2SCharles.Forsyth SETBIT(t,to);
182*74a4d8c2SCharles.Forsyth }
183*74a4d8c2SCharles.Forsyth if (sflag){
184*74a4d8c2SCharles.Forsyth lastc = 0x10000;
185*74a4d8c2SCharles.Forsyth while (readrune(0, &from) > 0) {
186*74a4d8c2SCharles.Forsyth if (from <= high)
187*74a4d8c2SCharles.Forsyth from = p[from];
188*74a4d8c2SCharles.Forsyth if (from != lastc || !BITSET(t,from)) {
189*74a4d8c2SCharles.Forsyth lastc = from;
190*74a4d8c2SCharles.Forsyth writerune(1, (Rune) from);
191*74a4d8c2SCharles.Forsyth }
192*74a4d8c2SCharles.Forsyth }
193*74a4d8c2SCharles.Forsyth
194*74a4d8c2SCharles.Forsyth } else {
195*74a4d8c2SCharles.Forsyth while (readrune(0, &from) > 0) {
196*74a4d8c2SCharles.Forsyth if (from <= high)
197*74a4d8c2SCharles.Forsyth from = p[from];
198*74a4d8c2SCharles.Forsyth writerune(1, (Rune) from);
199*74a4d8c2SCharles.Forsyth }
200*74a4d8c2SCharles.Forsyth }
201*74a4d8c2SCharles.Forsyth wflush(1);
202*74a4d8c2SCharles.Forsyth }
203*74a4d8c2SCharles.Forsyth
204*74a4d8c2SCharles.Forsyth int
readrune(int fd,long * rp)205*74a4d8c2SCharles.Forsyth readrune(int fd, long *rp)
206*74a4d8c2SCharles.Forsyth {
207*74a4d8c2SCharles.Forsyth Rune r;
208*74a4d8c2SCharles.Forsyth int j;
209*74a4d8c2SCharles.Forsyth static int i, n;
210*74a4d8c2SCharles.Forsyth static char buf[4096];
211*74a4d8c2SCharles.Forsyth
212*74a4d8c2SCharles.Forsyth j = i;
213*74a4d8c2SCharles.Forsyth for (;;) {
214*74a4d8c2SCharles.Forsyth if (i >= n) {
215*74a4d8c2SCharles.Forsyth wflush(1);
216*74a4d8c2SCharles.Forsyth if (j != i)
217*74a4d8c2SCharles.Forsyth memcpy(buf, buf+j, n-j);
218*74a4d8c2SCharles.Forsyth i = n-j;
219*74a4d8c2SCharles.Forsyth n = read(fd, &buf[i], sizeof(buf)-i);
220*74a4d8c2SCharles.Forsyth if (n < 0)
221*74a4d8c2SCharles.Forsyth error("read error");
222*74a4d8c2SCharles.Forsyth if (n == 0)
223*74a4d8c2SCharles.Forsyth return 0;
224*74a4d8c2SCharles.Forsyth j = 0;
225*74a4d8c2SCharles.Forsyth n += i;
226*74a4d8c2SCharles.Forsyth }
227*74a4d8c2SCharles.Forsyth i++;
228*74a4d8c2SCharles.Forsyth if (fullrune(&buf[j], i-j))
229*74a4d8c2SCharles.Forsyth break;
230*74a4d8c2SCharles.Forsyth }
231*74a4d8c2SCharles.Forsyth chartorune(&r, &buf[j]);
232*74a4d8c2SCharles.Forsyth *rp = r;
233*74a4d8c2SCharles.Forsyth return 1;
234*74a4d8c2SCharles.Forsyth }
235*74a4d8c2SCharles.Forsyth
236*74a4d8c2SCharles.Forsyth void
writerune(int fd,Rune r)237*74a4d8c2SCharles.Forsyth writerune(int fd, Rune r)
238*74a4d8c2SCharles.Forsyth {
239*74a4d8c2SCharles.Forsyth char buf[UTFmax];
240*74a4d8c2SCharles.Forsyth int n;
241*74a4d8c2SCharles.Forsyth
242*74a4d8c2SCharles.Forsyth if (!wptr)
243*74a4d8c2SCharles.Forsyth wptr = wbuf;
244*74a4d8c2SCharles.Forsyth n = runetochar(buf, (Rune*)&r);
245*74a4d8c2SCharles.Forsyth if (wptr+n >= wbuf+sizeof(wbuf))
246*74a4d8c2SCharles.Forsyth wflush(fd);
247*74a4d8c2SCharles.Forsyth memcpy(wptr, buf, n);
248*74a4d8c2SCharles.Forsyth wptr += n;
249*74a4d8c2SCharles.Forsyth }
250*74a4d8c2SCharles.Forsyth
251*74a4d8c2SCharles.Forsyth void
wflush(int fd)252*74a4d8c2SCharles.Forsyth wflush(int fd)
253*74a4d8c2SCharles.Forsyth {
254*74a4d8c2SCharles.Forsyth if (wptr && wptr > wbuf)
255*74a4d8c2SCharles.Forsyth if (write(fd, wbuf, wptr-wbuf) != wptr-wbuf)
256*74a4d8c2SCharles.Forsyth error("write error");
257*74a4d8c2SCharles.Forsyth wptr = wbuf;
258*74a4d8c2SCharles.Forsyth }
259*74a4d8c2SCharles.Forsyth
260*74a4d8c2SCharles.Forsyth char *
getrune(char * s,Rune * rp)261*74a4d8c2SCharles.Forsyth getrune(char *s, Rune *rp)
262*74a4d8c2SCharles.Forsyth {
263*74a4d8c2SCharles.Forsyth Rune r;
264*74a4d8c2SCharles.Forsyth char *save;
265*74a4d8c2SCharles.Forsyth int i, n;
266*74a4d8c2SCharles.Forsyth
267*74a4d8c2SCharles.Forsyth s += chartorune(rp, s);
268*74a4d8c2SCharles.Forsyth if((r = *rp) == '\\' && *s){
269*74a4d8c2SCharles.Forsyth n = 0;
270*74a4d8c2SCharles.Forsyth if (*s == 'x') {
271*74a4d8c2SCharles.Forsyth s++;
272*74a4d8c2SCharles.Forsyth for (i = 0; i < 4; i++) {
273*74a4d8c2SCharles.Forsyth save = s;
274*74a4d8c2SCharles.Forsyth s += chartorune(&r, s);
275*74a4d8c2SCharles.Forsyth if ('0' <= r && r <= '9')
276*74a4d8c2SCharles.Forsyth n = 16*n + r - '0';
277*74a4d8c2SCharles.Forsyth else if ('a' <= r && r <= 'f')
278*74a4d8c2SCharles.Forsyth n = 16*n + r - 'a' + 10;
279*74a4d8c2SCharles.Forsyth else if ('A' <= r && r <= 'F')
280*74a4d8c2SCharles.Forsyth n = 16*n + r - 'A' + 10;
281*74a4d8c2SCharles.Forsyth else {
282*74a4d8c2SCharles.Forsyth if (i == 0)
283*74a4d8c2SCharles.Forsyth *rp = 'x';
284*74a4d8c2SCharles.Forsyth else *rp = n;
285*74a4d8c2SCharles.Forsyth return save;
286*74a4d8c2SCharles.Forsyth }
287*74a4d8c2SCharles.Forsyth }
288*74a4d8c2SCharles.Forsyth } else {
289*74a4d8c2SCharles.Forsyth for(i = 0; i < 3; i++) {
290*74a4d8c2SCharles.Forsyth save = s;
291*74a4d8c2SCharles.Forsyth s += chartorune(&r, s);
292*74a4d8c2SCharles.Forsyth if('0' <= r && r <= '7')
293*74a4d8c2SCharles.Forsyth n = 8*n + r - '0';
294*74a4d8c2SCharles.Forsyth else {
295*74a4d8c2SCharles.Forsyth if (i == 0)
296*74a4d8c2SCharles.Forsyth {
297*74a4d8c2SCharles.Forsyth *rp = r;
298*74a4d8c2SCharles.Forsyth return s;
299*74a4d8c2SCharles.Forsyth }
300*74a4d8c2SCharles.Forsyth *rp = n;
301*74a4d8c2SCharles.Forsyth return save;
302*74a4d8c2SCharles.Forsyth }
303*74a4d8c2SCharles.Forsyth }
304*74a4d8c2SCharles.Forsyth if(n > 0377)
305*74a4d8c2SCharles.Forsyth error("char>0377");
306*74a4d8c2SCharles.Forsyth }
307*74a4d8c2SCharles.Forsyth *rp = n;
308*74a4d8c2SCharles.Forsyth }
309*74a4d8c2SCharles.Forsyth return s;
310*74a4d8c2SCharles.Forsyth }
311*74a4d8c2SCharles.Forsyth
312*74a4d8c2SCharles.Forsyth long
canon(Pcb * p)313*74a4d8c2SCharles.Forsyth canon(Pcb *p)
314*74a4d8c2SCharles.Forsyth {
315*74a4d8c2SCharles.Forsyth Rune r;
316*74a4d8c2SCharles.Forsyth
317*74a4d8c2SCharles.Forsyth if (p->final >= 0) {
318*74a4d8c2SCharles.Forsyth if (p->last < p->final)
319*74a4d8c2SCharles.Forsyth return ++p->last;
320*74a4d8c2SCharles.Forsyth p->final = -1;
321*74a4d8c2SCharles.Forsyth }
322*74a4d8c2SCharles.Forsyth if (*p->current == '\0')
323*74a4d8c2SCharles.Forsyth return -1;
324*74a4d8c2SCharles.Forsyth if(*p->current == '-' && p->last >= 0 && p->current[1]){
325*74a4d8c2SCharles.Forsyth p->current = getrune(p->current+1, &r);
326*74a4d8c2SCharles.Forsyth if (r < p->last)
327*74a4d8c2SCharles.Forsyth error ("Invalid range specification");
328*74a4d8c2SCharles.Forsyth if (r > p->last) {
329*74a4d8c2SCharles.Forsyth p->final = r;
330*74a4d8c2SCharles.Forsyth return ++p->last;
331*74a4d8c2SCharles.Forsyth }
332*74a4d8c2SCharles.Forsyth }
333*74a4d8c2SCharles.Forsyth p->current = getrune(p->current, &r);
334*74a4d8c2SCharles.Forsyth p->last = r;
335*74a4d8c2SCharles.Forsyth return p->last;
336*74a4d8c2SCharles.Forsyth }
337*74a4d8c2SCharles.Forsyth
338*74a4d8c2SCharles.Forsyth void
Pinit(Pcb * p,char * cp)339*74a4d8c2SCharles.Forsyth Pinit(Pcb *p, char *cp)
340*74a4d8c2SCharles.Forsyth {
341*74a4d8c2SCharles.Forsyth p->current = p->base = cp;
342*74a4d8c2SCharles.Forsyth p->last = p->final = -1;
343*74a4d8c2SCharles.Forsyth }
344*74a4d8c2SCharles.Forsyth void
Prewind(Pcb * p)345*74a4d8c2SCharles.Forsyth Prewind(Pcb *p)
346*74a4d8c2SCharles.Forsyth {
347*74a4d8c2SCharles.Forsyth p->current = p->base;
348*74a4d8c2SCharles.Forsyth p->last = p->final = -1;
349*74a4d8c2SCharles.Forsyth }
350*74a4d8c2SCharles.Forsyth void
error(char * s)351*74a4d8c2SCharles.Forsyth error(char *s)
352*74a4d8c2SCharles.Forsyth {
353*74a4d8c2SCharles.Forsyth fprint(2, "tr: %s\n", s);
354*74a4d8c2SCharles.Forsyth exits(s);
355*74a4d8c2SCharles.Forsyth }
356