plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

conv_big5.c (2845B)


      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 *notused, 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 	USED(notused);
     94 	r = ob;
     95 	re = ob+N-3;
     96 	nin = 0;
     97 	while((n = read(fd, ibuf, sizeof ibuf)) > 0){
     98 		for(i = 0; i < n; i++){
     99 			big5proc(ibuf[i], &r, nin++);
    100 			if(r >= re){
    101 				OUT(out, ob, r-ob);
    102 				r = ob;
    103 			}
    104 		}
    105 		if(r > ob){
    106 			OUT(out, ob, r-ob);
    107 			r = ob;
    108 		}
    109 	}
    110 	big5proc(-1, &r, nin);
    111 	if(r > ob)
    112 		OUT(out, ob, r-ob);
    113 	OUT(out, ob, 0);
    114 }
    115 
    116 void
    117 big5_out(Rune *base, int n, long *notused)
    118 {
    119 	char *p;
    120 	int i;
    121 	Rune r;
    122 	static int first = 1;
    123 
    124 	USED(notused);
    125 	if(first){
    126 		first = 0;
    127 		for(i = 0; i < NRUNE; i++)
    128 			tab[i] = -1;
    129 		for(i = 0; i < BIG5MAX; i++)
    130 			if(tabbig5[i] != -1)
    131 				tab[tabbig5[i]] = i;
    132 	}
    133 	nrunes += n;
    134 	p = obuf;
    135 	for(i = 0; i < n; i++){
    136 		r = base[i];
    137 		if(r < 128)
    138 			*p++ = r;
    139 		else {
    140 			if(tab[r] != -1){
    141 				r = tab[r];
    142 				if(r >= BIG5MAX){
    143 					*p++ = (char)0xA1;
    144 					*p++ = r-BIG5MAX;
    145 					continue;
    146 				} else {
    147 					*p++ = 0xA1 + (r/BIG5FONT);
    148 					r = r%BIG5FONT;
    149 					if(r <= 62) r += 64;
    150 					else r += 0xA1-63;
    151 					*p++ = r;
    152 					continue;
    153 				}
    154 			}
    155 			if(squawk)
    156 				EPR "%s: rune 0x%x not in output cs\n", argv0, r);
    157 			nerrors++;
    158 			if(clean)
    159 				continue;
    160 			*p++ = BYTEBADMAP;
    161 		}
    162 	}
    163 	noutput += p-obuf;
    164 	if(p > obuf)
    165 		write(1, obuf, p-obuf);
    166 }