Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#ifdef  PLAN9
#include        <u.h>
#include        <libc.h>
#include        <bio.h>
#else
#include        <stdio.h>
#include        <unistd.h>
#include        "plan9.h"
#endif
#include        "hdr.h"
#include        "conv.h"
#include        "ksc.h"

/*
        contributed by kuro@vodka.Eng.Sun.COM (Teruhiko Kurosaka)
*/

/*
        a state machine for interpreting shift-ksc.
*/

#define SS2     0x8e
#define SS3     0x8f
/*
 * Convert EUC in Koran locale to Unicode.
 * Only codeset 0 and 1 are used.
 */
void
ukscproc(int c, Rune **r, long input_loc)
{
        static enum { init, cs1last /*, cs2, cs3first, cs3last*/} state = init;
        static int korean646 = 1; /* fixed to 1 for now. */
        static int lastc;
        int n;
        long l;

        switch(state)
        {
        case init:
                if (c < 0){
                        return;
                }else if (c < 128){
                        if(korean646 && (c=='\\')){
                                emit(0x20A9);
                        } else {
                                emit(c);
                        }
/*              }else if (c==SS2){
                        state = cs2;
                }else if (c==SS3){
                        state = cs3first;
 */             }else{
                        lastc = c;
                        state = cs1last;
                }
                return;

        case cs1last: /* 2nd byte of codeset 1 (KSC 5601) */
                if(c < 0){
                        if(squawk)
                                EPR "%s: unexpected EOF in %s\n", argv0, file);
                        c = 0x21 | (lastc&0x80);
                }
                n = ((lastc&0x7f)-33)*94 + (c&0x7f)-33;
                if((n >= ksc5601max) || ((l = tabksc5601[n]) < 0)){
                        nerrors++;
                        if(squawk)
                                EPR "%s: unknown ksc5601 %d (from 0x%x,0x%x) near byte %ld in %s\n", argv0, n, lastc, c, input_loc, file);
                        if(!clean)
                                emit(BADMAP);
                } else {
                        emit(l);
                }
                state = init;
                return;
        default:
                if(squawk)
                        EPR "%s: ukscproc: unknown state %d\n",
                                argv0, init);
        }
}

void
uksc_in(int fd, long *notused, struct convert *out)
{
        Rune ob[N];
        Rune *r, *re;
        uchar ibuf[N];
        int n, i;
        long nin;

        USED(notused);
        r = ob;
        re = ob+N-3;
        nin = 0;
        while((n = read(fd, ibuf, sizeof ibuf)) > 0){
                for(i = 0; i < n; i++){
                        ukscproc(ibuf[i], &r, nin++);
                        if(r >= re){
                                OUT(out, ob, r-ob);
                                r = ob;
                        }
                }
                if(r > ob){
                        OUT(out, ob, r-ob);
                        r = ob;
                }
        }
        ukscproc(-1, &r, nin);
        if(r > ob)
                OUT(out, ob, r-ob);
        OUT(out, ob, 0);
}

void
uksc_out(Rune *base, int n, long *notused)
{
        char *p;
        int i;
        Rune r;
        long l;
        static int first = 1;

        USED(notused);
        if(first){
                first = 0;
                for(i = 0; i < NRUNE; i++)
                        tab[i] = -1;
                for(i = 0; i < ksc5601max; i++)
                        if((l = tabksc5601[i]) != -1){
                                if(l < 0)
                                        tab[-l] = i;
                                else
                                        tab[l] = i;
                        }
        }
        nrunes += n;
        p = obuf;
        for(i = 0; i < n; i++){
                r = base[i];
                if(r < 128)
                        *p++ = r;
                else {
                        if(tab[r] != -1){
                                *p++ = 0x80 | (tab[r]/94 + 0x21);
                                *p++ = 0x80 | (tab[r]%94 + 0x21);
                                continue;
                        }
                        if(squawk)
                                EPR "%s: rune 0x%x not in output cs\n", argv0, r);
                        nerrors++;
                        if(clean)
                                continue;
                        *p++ = BYTEBADMAP;
                }
        }
        noutput += p-obuf;
        if(p > obuf)
                write(1, obuf, p-obuf);
}