forsyth20121205-174063a80cc13 years agoHistory
212 lines · 4.1 KB · Brainfuck
RawDownload
implement Bytes;include "sys.m";	sys: Sys;	stderr: ref Sys->FD;include "draw.m";include "bufio.m";	bufio: Bufio;	Iobuf: import bufio; stdin, stdout: ref Iobuf; Bytes: module {	init: fn(nil: ref Draw->Context, argv: list of string);}; usage(){	sys->fprint(stderr, "usage: bytes start end [bytes]\n");	raise "fail:usage";} END: con 16r7fffffff;init(nil: ref Draw->Context, argv: list of string){	sys = load Sys Sys->PATH;	stderr = sys->fildes(2);	bufio = load Bufio Bufio->PATH;	if (bufio == nil) {		sys->fprint(stderr, "bytes: cannot load %s: %r\n", Bufio->PATH);		raise "fail:bad module";	}	stdin = bufio->fopen(sys->fildes(0), Sys->OREAD);	stdout = bufio->fopen(sys->fildes(1), Sys->OWRITE);	start := end := END;	if (len argv < 3)		usage();	argv = tl argv;	if (hd argv != "end")		start = int hd argv;	argv = tl argv;	if (hd argv != "end")		end = int hd argv;	if (end < start) {		sys->fprint(stderr, "bytes: out of order range\n");		raise "fail:bad range";	}	argv = tl argv;	if (argv == nil)		showbytes(start, end);	else {		if (tl argv != nil)			usage();		b := s2bytes(hd argv);		setbytes(start, end, b);	}	stdout.close();} showbytes(start, end: int){	buf := array[Sys->ATOMICIO] of byte;	hold := array[Sys->UTFmax] of byte;	tot := 0;	nhold := 0;	while (tot < end && (n := stdin.read(buf[nhold:], len buf - nhold)) > 0) {		sys->fprint(stderr, "bytes: read %d bytes\n", n);		if (tot + n < start)			continue;		sb := 0;		eb := n;		if (start > tot)			sb = start - tot;		if (tot + n > end)			eb = end - tot;		nhold = putbytes(buf[sb:eb], hold);		buf[0:] = hold[0:nhold];		tot += n - nhold;	}	sys->fprint(stderr, "out of loop\n");	flushbytes(hold[0:nhold]);} setbytes(start, end: int, d: array of byte){	buf := array[Sys->ATOMICIO] of byte;	tot := 0;	while ((n := stdin.read(buf, len buf)) > 0) {		if (tot + n < start || tot >= end) {			stdout.write(buf, n);			continue;		}		if (tot <= start) {			stdout.write(buf[0:start-tot], start-tot);			stdout.write(d, len d);			if (end == END)				return;		}		if (tot + n >= end)			stdout.write(buf[end - tot:], n - (end - tot));		tot += n;	}	if (tot == start || start == END)		stdout.write(d, len d);} putbytes(d: array of byte, hold: array of byte): int{	i := 0;	while (i < len d) {		(c, n, ok) := sys->byte2char(d, i);		if (ok && n > 0) {			if (c == '\\')				stdout.putc('\\');			stdout.putc(c);		} else {			if (n == 0) {				hold[0:] = d[i:];				return len d - i;			} else {				putbyte(d[i]);				n = 1;			}		}		i += n;	}	return 0;} flushbytes(hold: array of byte){	for (i := 0; i < len hold; i++)		putbyte(hold[i]);} putbyte(b: byte){	stdout.puts(sys->sprint("\\%2.2X", int b));} isbschar(c: int): int{	case c {	'n' or 'r' or 't' or 'v' =>		return 1;	}	return 0;} s2bytes(s: string): array of byte{	d := array[len s + 2] of byte;	j := 0;	for (i := 0; i < len s; i++) {		if (s[i] == '\\') {			if (i >= len s - 1 || (!isbschar(s[i+1]) && i >= len s - 2)) {				sys->fprint(stderr, "bytes: invalid backslash sequence\n");				raise "fail:bad args";			}			d = assure(d, j + 1);			if (isbschar(s[i+1])) {				case s[i+1] {				'n' =>	d[j++] = byte '\n';				'r' =>		d[j++] = byte '\r';				't' =>		d[j++] = byte '\t';				'v' =>	d[j++] = byte '\v';				'\\' =>	d[j++] = byte '\\';				* =>					sys->fprint(stderr, "bytes: invalid backslash sequence\n");					raise "fail:bad args";				}				i++;			} else if (!ishex(s[i+1]) || !ishex(s[i+2])) {				sys->fprint(stderr, "bytes: invalid backslash sequence\n");				raise "fail:bad args";			} else {				d[j++] = byte ((hex(s[i+1]) << 4) + hex(s[i+2]));				i += 2;			}		} else {			d = assure(d, j + 3);			j += sys->char2byte(s[i], d, j);		}	}	return d[0:j];} assure(d: array of byte, n: int): array of byte{	if (len d >= n)		return d;	nd := array[n] of byte;	nd[0:] = d;	return nd;} ishex(c: int): int{	return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');} hex(c: int): int{	case c {	'0' to '9' =>		return c - '0';	'a' to 'f' =>		return c - 'a' + 10;	'A' to 'F' =>		return c-  'A' + 10;	}	return 0;}