xref: /inferno-os/appl/cmd/tcs.b (revision cc1b535fe2e466d426f0aa2d916e306e2a17b163)
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