137da2899SCharles.Forsythimplement Tcs; 237da2899SCharles.Forsyth 337da2899SCharles.Forsythinclude "sys.m"; 4*cc1b535fSforsyth sys: Sys; 537da2899SCharles.Forsythinclude "draw.m"; 637da2899SCharles.Forsythinclude "arg.m"; 737da2899SCharles.Forsythinclude "bufio.m"; 8*cc1b535fSforsyth bufio: Bufio; 9*cc1b535fSforsyth Iobuf: import bufio; 1037da2899SCharles.Forsythinclude "convcs.m"; 11*cc1b535fSforsyth convcs: Convcs; 1237da2899SCharles.Forsyth 13*cc1b535fSforsythTcs: module 14*cc1b535fSforsyth{ 1537da2899SCharles.Forsyth init: fn (nil: ref Draw->Context, args: list of string); 1637da2899SCharles.Forsyth}; 1737da2899SCharles.Forsyth 1837da2899SCharles.Forsythstderr: ref Sys->FD; 1937da2899SCharles.Forsyth 2037da2899SCharles.Forsythinit(nil: ref Draw->Context, args: list of string) 2137da2899SCharles.Forsyth{ 2237da2899SCharles.Forsyth sys = load Sys Sys->PATH; 2337da2899SCharles.Forsyth stderr = sys->fildes(2); 2437da2899SCharles.Forsyth if ((arg := load Arg Arg->PATH) == nil) 2537da2899SCharles.Forsyth badmodule(Arg->PATH); 2637da2899SCharles.Forsyth if ((bufio = load Bufio Bufio->PATH) == nil) 2737da2899SCharles.Forsyth badmodule(Bufio->PATH); 2837da2899SCharles.Forsyth if ((convcs = load Convcs Convcs->PATH) == nil) 2937da2899SCharles.Forsyth badmodule(Convcs->PATH); 3037da2899SCharles.Forsyth 3137da2899SCharles.Forsyth arg->init(args); 32*cc1b535fSforsyth arg->setusage("tcs [-C configfile] [-l] [-f ics] [-t ocs] file ..."); 33*cc1b535fSforsyth lflag := 0; 34*cc1b535fSforsyth vflag := 0; 35*cc1b535fSforsyth ics := "utf8"; 36*cc1b535fSforsyth ocs := "utf8"; 3737da2899SCharles.Forsyth csfile := ""; 3837da2899SCharles.Forsyth while ((c := arg->opt()) != 0) { 3937da2899SCharles.Forsyth case c { 4037da2899SCharles.Forsyth 'C' => 4137da2899SCharles.Forsyth csfile = arg->arg(); 4237da2899SCharles.Forsyth 'f' => 4337da2899SCharles.Forsyth ics = arg->arg(); 4437da2899SCharles.Forsyth 'l' => 4537da2899SCharles.Forsyth lflag = 1; 4637da2899SCharles.Forsyth 't' => 4737da2899SCharles.Forsyth ocs = arg->arg(); 4837da2899SCharles.Forsyth 'v' => 4937da2899SCharles.Forsyth vflag = 1; 5037da2899SCharles.Forsyth * => 51*cc1b535fSforsyth arg->usage(); 5237da2899SCharles.Forsyth } 5337da2899SCharles.Forsyth } 5437da2899SCharles.Forsyth file := arg->arg(); 5537da2899SCharles.Forsyth 5637da2899SCharles.Forsyth out := bufio->fopen(sys->fildes(1), Sys->OWRITE); 5737da2899SCharles.Forsyth err := convcs->init(csfile); 5837da2899SCharles.Forsyth if (err != nil) { 5937da2899SCharles.Forsyth sys->fprint(stderr, "convcs: %s\n", err); 6037da2899SCharles.Forsyth raise "fail:init"; 6137da2899SCharles.Forsyth } 6237da2899SCharles.Forsyth 6337da2899SCharles.Forsyth if (lflag) { 6437da2899SCharles.Forsyth if (file != nil) 6537da2899SCharles.Forsyth dumpaliases(out, file, vflag); 6637da2899SCharles.Forsyth else 6737da2899SCharles.Forsyth dumpconvs(out, vflag); 6837da2899SCharles.Forsyth return; 6937da2899SCharles.Forsyth } 7037da2899SCharles.Forsyth 7137da2899SCharles.Forsyth stob: Stob; 7237da2899SCharles.Forsyth btos: Btos; 7337da2899SCharles.Forsyth (stob, err) = convcs->getstob(ocs); 7437da2899SCharles.Forsyth if (err != nil) { 75*cc1b535fSforsyth sys->fprint(stderr, "tcs: %s: %s\n", ocs, err); 7637da2899SCharles.Forsyth raise "fail:badarg"; 7737da2899SCharles.Forsyth } 7837da2899SCharles.Forsyth (btos, err) = convcs->getbtos(ics); 7937da2899SCharles.Forsyth if (err != nil) { 80*cc1b535fSforsyth sys->fprint(stderr, "tcs: %s: %s\n", ics, err); 8137da2899SCharles.Forsyth raise "fail:badarg"; 8237da2899SCharles.Forsyth } 8337da2899SCharles.Forsyth 84*cc1b535fSforsyth fd: ref Sys->FD; 85*cc1b535fSforsyth if (file == nil) { 86*cc1b535fSforsyth fd = sys->fildes(0); 87*cc1b535fSforsyth file = "standard input"; 88*cc1b535fSforsyth } else 8937da2899SCharles.Forsyth fd = open(file); 9037da2899SCharles.Forsyth 9137da2899SCharles.Forsyth inbuf := array [Sys->ATOMICIO] of byte; 92*cc1b535fSforsyth for(;;){ 9337da2899SCharles.Forsyth btoss: Convcs->State = nil; 9437da2899SCharles.Forsyth stobs: Convcs->State = nil; 9537da2899SCharles.Forsyth 96*cc1b535fSforsyth unc := 0; 97*cc1b535fSforsyth nc: int; 98*cc1b535fSforsyth s: string; 99*cc1b535fSforsyth while ((n := sys->read(fd, inbuf[unc:], len inbuf - unc)) > 0) { 100*cc1b535fSforsyth n += unc; # include unconsumed prefix 10137da2899SCharles.Forsyth (btoss, s, nc) = btos->btos(btoss, inbuf[0:n], -1); 10237da2899SCharles.Forsyth if (s != nil) 103*cc1b535fSforsyth stobs = output(out, stob, stobs, s); 10437da2899SCharles.Forsyth # copy down unconverted part of buffer 105*cc1b535fSforsyth unc = n - nc; 106*cc1b535fSforsyth if (unc > 0 && nc > 0) 107*cc1b535fSforsyth inbuf[0:] = inbuf[nc: n]; 108*cc1b535fSforsyth } 109*cc1b535fSforsyth if (n < 0) { 110*cc1b535fSforsyth sys->fprint(stderr, "tcs: error reading %s: %r\n", file); 111*cc1b535fSforsyth raise "fail:read error"; 11237da2899SCharles.Forsyth } 11337da2899SCharles.Forsyth 114*cc1b535fSforsyth # flush conversion state 115*cc1b535fSforsyth (nil, s, nil) = btos->btos(btoss, inbuf[0: unc], 0); 116*cc1b535fSforsyth if(s != nil) 117*cc1b535fSforsyth stobs = output(out, stob, stobs, s); 118*cc1b535fSforsyth output(out, stob, stobs, ""); 119*cc1b535fSforsyth 120*cc1b535fSforsyth if(out.flush() != 0) { 121*cc1b535fSforsyth sys->fprint(stderr, "tcs: write error: %r\n"); 122*cc1b535fSforsyth raise "fail:write error"; 123*cc1b535fSforsyth } 12437da2899SCharles.Forsyth file = arg->arg(); 12537da2899SCharles.Forsyth if (file == nil) 12637da2899SCharles.Forsyth break; 12737da2899SCharles.Forsyth fd = open(file); 12837da2899SCharles.Forsyth } 12937da2899SCharles.Forsyth} 13037da2899SCharles.Forsyth 131*cc1b535fSforsythoutput(out: ref Iobuf, stob: Stob, stobs: Convcs->State, s: string): Convcs->State 132*cc1b535fSforsyth{ 133*cc1b535fSforsyth outbuf: array of byte; 134*cc1b535fSforsyth (stobs, outbuf) = stob->stob(stobs, s); 135*cc1b535fSforsyth if(outbuf != nil) 136*cc1b535fSforsyth out.write(outbuf, len outbuf); 137*cc1b535fSforsyth return stobs; 138*cc1b535fSforsyth} 139*cc1b535fSforsyth 14037da2899SCharles.Forsythbadmodule(s: string) 14137da2899SCharles.Forsyth{ 142*cc1b535fSforsyth sys->fprint(stderr, "tcs: cannot load module %s: %r\n", s); 14337da2899SCharles.Forsyth raise "fail:init"; 14437da2899SCharles.Forsyth} 14537da2899SCharles.Forsyth 14637da2899SCharles.Forsythdumpconvs(out: ref Iobuf, verbose: int) 14737da2899SCharles.Forsyth{ 14837da2899SCharles.Forsyth first := 1; 14937da2899SCharles.Forsyth for (csl := convcs->enumcs(); csl != nil; csl = tl csl) { 15037da2899SCharles.Forsyth (name, desc, mode) := hd csl; 15137da2899SCharles.Forsyth if (!verbose) { 15237da2899SCharles.Forsyth if (!first) 15337da2899SCharles.Forsyth out.putc(' '); 15437da2899SCharles.Forsyth out.puts(name); 15537da2899SCharles.Forsyth } else { 15637da2899SCharles.Forsyth ms := ""; 15737da2899SCharles.Forsyth case mode { 15837da2899SCharles.Forsyth Convcs->BTOS => 15937da2899SCharles.Forsyth ms = "(from)"; 16037da2899SCharles.Forsyth Convcs->STOB => 16137da2899SCharles.Forsyth ms = "(to)"; 16237da2899SCharles.Forsyth } 16337da2899SCharles.Forsyth out.puts(sys->sprint("%s%s\t%s\n", name, ms, desc)); 16437da2899SCharles.Forsyth } 16537da2899SCharles.Forsyth first = 0; 16637da2899SCharles.Forsyth } 16737da2899SCharles.Forsyth if (!verbose) 16837da2899SCharles.Forsyth out.putc('\n'); 16937da2899SCharles.Forsyth out.flush(); 17037da2899SCharles.Forsyth} 17137da2899SCharles.Forsyth 17237da2899SCharles.Forsythdumpaliases(out: ref Iobuf, cs: string, verbose: int) 17337da2899SCharles.Forsyth{ 17437da2899SCharles.Forsyth (desc, asl) := convcs->aliases(cs); 17537da2899SCharles.Forsyth if (asl == nil) { 17637da2899SCharles.Forsyth sys->fprint(stderr, "%s\n", desc); 17737da2899SCharles.Forsyth return; 17837da2899SCharles.Forsyth } 17937da2899SCharles.Forsyth 18037da2899SCharles.Forsyth if (verbose) { 18137da2899SCharles.Forsyth out.puts(desc); 18237da2899SCharles.Forsyth out.putc('\n'); 18337da2899SCharles.Forsyth } 18437da2899SCharles.Forsyth first := 1; 18537da2899SCharles.Forsyth for (; asl != nil; asl = tl asl) { 18637da2899SCharles.Forsyth a := hd asl; 18737da2899SCharles.Forsyth if (!first) 18837da2899SCharles.Forsyth out.putc(' '); 18937da2899SCharles.Forsyth out.puts(a); 19037da2899SCharles.Forsyth first = 0; 19137da2899SCharles.Forsyth } 19237da2899SCharles.Forsyth out.putc('\n'); 19337da2899SCharles.Forsyth out.flush(); 19437da2899SCharles.Forsyth} 19537da2899SCharles.Forsyth 19637da2899SCharles.Forsythopen(path: string): ref Sys->FD 19737da2899SCharles.Forsyth{ 19837da2899SCharles.Forsyth fd := sys->open(path, Bufio->OREAD); 199*cc1b535fSforsyth if (fd == nil) { 200*cc1b535fSforsyth sys->fprint(stderr, "tcs: cannot open %s: %r\n", path); 201*cc1b535fSforsyth raise "fail:open"; 202*cc1b535fSforsyth } 20337da2899SCharles.Forsyth return fd; 20437da2899SCharles.Forsyth} 205