Mechiel Lukkienvarious improvements.5a19a3617 years agoHistory
362 lines · 6.4 KB · Brainfuck
RawDownload
implement Sshfmt; include "sys.m";	sys: Sys;	sprint: import sys;include "util0.m";	util: Util0;	prefix, suffix, rev, l2a, max, min, warn, join, eq, g32, g32i, g64, p32, p32i, p64: import util;include "keyring.m";	kr: Keyring;	IPint: import kr;include "sshfmt.m";  init(){	sys = load Sys Sys->PATH;	kr = load Keyring Keyring->PATH;	util = load Util0 Util0->PATH;	util->init();} pack(v: array of ref Val, withlength: int): array of byte{	lensize := 0;	if(withlength)		lensize = 4; 	size := 0;	for(i := 0; i < len v; i++)		size += v[i].size(); 	buf := array[lensize+size] of byte;	if(withlength)		p32i(buf, 0, size); 	o := lensize;	for(i = 0; i < len v; i++)		o += v[i].packbuf(buf[o:]);	if(o != len buf)		raise "packerror";	return buf;} parseall(buf: array of byte, l: list of int): (array of ref Val, string){	(v, o, err) := parse(buf, l);	if(err != nil)		return (nil, err);	if(o != len buf)		return (nil, sprint("leftover bytes, %d of %d used", o, len buf));	return (v, nil);} parse(buf: array of byte, l: list of int): (array of ref Val, int, string){	{		(v, o) := xparse(buf, l);		return (v, o, nil);	} exception x {	"parse:*" =>		return (nil, 0, x[len "parse:":]);	}} parseerror(s: string){	raise "parse:"+s;} xparse(buf: array of byte, l: list of int): (array of ref Val, int){	r: list of ref Val;	o := 0;	i := 0;	for(; l != nil; l = tl l) {		#say(sprint("parse, %d elems left, %d bytes left", len l, len buf-o));		t := hd l;		case t {		Tbyte =>			if(o+1 > len buf)				parseerror("short buffer for byte");			r = ref Val.Byte (buf[o++])::r;		Tbool =>			if(o+1 > len buf)				parseerror("short buffer for byte");			r = ref Val.Bool (int buf[o++])::r;		Tint =>			if(o+4 > len buf)				parseerror("short buffer for int");			e := ref Val.Int;			(e.v, o) = g32(buf, o);			r = e::r;		Tbig =>			if(o+8 > len buf)				parseerror("short buffer for big");			e := ref Val.Big;			(e.v, o) = g64(buf, o);			r = e::r;		Tnames or		Tstr or		Tmpint =>			if(o+4 > len buf)				parseerror("short buffer for int for length");			length: int;			(length, o) = g32i(buf, o);			if(o+length > len buf)				parseerror("short buffer for name-list/string/mpint");			case t {			Tnames =>				# xxx disallow non-printable?				# xxx better verify tokens				r = ref Val.Names (sys->tokenize(string buf[o:o+length], ",").t1)::r;			Tstr =>				r = ref Val.Str (buf[o:o+length])::r;			Tmpint =>				#say(sprint("read mpint of length %d", length));				if(length == 0) {					r = valmpint(IPint.strtoip("0", 10))::r;				} else {					neg := 0;					if(int buf[o] & 16r80) {						raise "negative incoming";						neg = 1;						buf[o] &= byte 16r7f;					}					v := IPint.bebytestoip(buf[o:o+length]);					if(neg) {						buf[o] |= byte 16r80;						v = v.neg();					}					r = valmpint(v)::r;					#say(sprint("new mpint %s", (hd r).text()));				}			}			o += length;		* =>			if(t < 0)				parseerror(sprint("unknown type %d requested", t));			if(o+t > len buf)				parseerror("short buffer for byte-array");			r = ref Val.Str (buf[o:o+t])::r;			o += t;		}		#say(sprint("new val, size %d, text %s", (hd r).size(), (hd r).text()));		i++;	}	return (l2a(rev(r)), o);}  Val.getbyte(v: self ref Val): byte{	pick vv := v {	Byte =>	return byte vv.v;	}	raise "not byte";} Val.getbool(v: self ref Val): int{	pick vv := v {	Bool =>	return vv.v;	}	raise "not bool";} Val.getint(v: self ref Val): int{	pick vv := v {	Int =>	return int vv.v;	}	raise "not int";} Val.getintb(v: self ref Val): big{	pick vv := v {	Int =>	return vv.v;	}	raise "not int";} Val.getbig(v: self ref Val): big{	pick vv := v {	Big =>	return vv.v;	}	raise "not big";} Val.getnames(v: self ref Val): list of string{	pick vv := v {	Names =>	return vv.l;	}	raise "not names";} Val.getipint(v: self ref Val): ref IPint{	pick vv := v {	Mpint =>	return vv.v;	}	raise "not mpint";} Val.getstr(v: self ref Val): string{	pick vv := v {	Str =>	return string vv.buf;	}	raise "not string";} Val.getbytes(v: self ref Val): array of byte{	pick vv := v {	Str =>	return vv.buf;	}	raise "not string (bytes)";}  Val.pack(v: self ref Val): array of byte{	n := v.size();	d := array[n] of byte;	v.packbuf(d);	return d;} Val.text(vv: self ref Val): string{	pick v := vv {	Byte =>	return string v.v;	Bool =>		if(v.v)			return "true";		return "false";	Int =>	return string v.v;	Big =>	return string v.v;	Names =>	return join(v.l, ",");	Str =>	return "string "+string v.buf;	Mpint =>		return "ipint "+v.v.iptostr(16);	Buf =>	return "buf "+string v.buf;	}} Val.size(vv: self ref Val): int{	pick v := vv {	Byte =>	return 1;	Bool =>	return 1;	Int =>	return 4;	Big =>	return 8;	Names =>	return 4+len join(v.l, ",");	Str =>	return 4+len v.buf;	Mpint =>	return len packmpint(v.v);	Buf =>	return len v.buf;	}} packmpint(v: ref IPint): array of byte{	zero := IPint.strtoip("0", 10);	cmp := zero.cmp(v);	if(cmp == 0) {		d := array[4] of byte;		p32i(d, 0, 0);		return d;	}	if(v.cmp(zero) < 0)		raise "negative";	buf := v.iptobebytes();	if(int buf[0] & 16r80) {		nbuf := array[len buf+1] of byte;		nbuf[0] = byte 0;		nbuf[1:] = buf;		buf = nbuf;	}	d := array[4+len buf] of byte;	p32i(d, 0, len buf);	d[4:] = buf;	#say(sprint("Val.Mpint.pack, hex %s", hex(d)));	return d;} Val.packbuf(vv: self ref Val, d: array of byte): int{	pick v := vv {	Byte =>		d[0] = v.v;		return 1;	Bool =>		d[0] = byte v.v;		return 1;	Int =>		return p32(d, 0, v.v);	Big =>		return p64(d, 0, v.v);	Names =>		s := array of byte join(v.l, ",");		p32i(d, 0, len s);		d[4:] = s;		return 4+len s;	Str =>		p32i(d, 0, len v.buf);		d[4:] = v.buf;		return 4+len v.buf;	Mpint =>		buf := packmpint(v.v);		d[:] = buf;		return len buf;	Buf =>		d[:] = v.buf;		return len v.buf;	};}  valbyte(v: byte): ref Val{	return ref Val.Byte (v);}valbool(v: int): ref Val{	return ref Val.Bool (v);}valint(v: int): ref Val{	return ref Val.Int (big v);}valintb(v: big): ref Val{	return ref Val.Int (v);}valbig(v: big): ref Val{	return ref Val.Big (v);}valmpint(v: ref IPint): ref Val{	return ref Val.Mpint (v);}valnames(v: list of string): ref Val{	return ref Val.Names (v);}valstr(v: string): ref Val{	return ref Val.Str (array of byte v);}valbytes(v: array of byte): ref Val{	return ref Val.Str (v);}valbuf(v: array of byte): ref Val{	return ref Val.Buf (v);}