xref: /plan9-contrib/sys/src/cmd/tcs/conv_gbk.c (revision b39189fd423aed869c5cf5189bc504918cff969b)
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