URI:
       tconv_big5.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tconv_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 }