Blob
1 #ifdef PLAN92 #include <u.h>3 #include <libc.h>4 #include <bio.h>5 #else6 #include <stdio.h>7 #include <unistd.h>8 #include "plan9.h"9 #endif10 #include "hdr.h"11 #include "conv.h"12 #include "big5.h"14 /*15 a state machine for interpreting big5 (hk format).16 */17 void18 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;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;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 else70 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 } else79 emit(ch);80 state = state0;81 }82 }84 void85 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;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 }115 void116 big5_out(Rune *base, int n, long *notused)117 {118 char *p;119 int i;120 Rune r;121 static int first = 1;123 USED(notused);124 if(first){125 first = 0;126 for(i = 0; i < NRUNE; i++)127 tab[i] = -1;128 for(i = 0; i < BIG5MAX; i++)129 if(tabbig5[i] != -1)130 tab[tabbig5[i]] = i;131 }132 nrunes += n;133 p = obuf;134 for(i = 0; i < n; i++){135 r = base[i];136 if(r < 128)137 *p++ = r;138 else {139 if(tab[r] != -1){140 r = tab[r];141 if(r >= BIG5MAX){142 *p++ = 0xA1;143 *p++ = r-BIG5MAX;144 continue;145 } else {146 *p++ = 0xA1 + (r/BIG5FONT);147 r = r%BIG5FONT;148 if(r <= 62) r += 64;149 else r += 0xA1-63;150 *p++ = r;151 continue;152 }153 }154 if(squawk)155 EPR "%s: rune 0x%x not in output cs\n", argv0, r);156 nerrors++;157 if(clean)158 continue;159 *p++ = BYTEBADMAP;160 }161 }162 noutput += p-obuf;163 if(p > obuf)164 write(1, obuf, p-obuf);165 }