Charles.Forsyth20060303a828770d19 years agoHistory
1493 lines · 30.1 KB · Brainfuck
RawDownload
implement Debug; include "sys.m";sys: Sys;sprint, FD: import sys; include "string.m";str: String; include "draw.m"; include "debug.m"; include "dis.m";	dism: Dis; Command: module{	init:	fn(ctxt: ref Draw->Context, argv: list of string);}; Spin: adt{	spin:	int;	pspin:	int;}; SrcState: adt{	files:	array of string;	lastf:	int;	lastl:	int;	vers:	int;			# version number					# 11 => more source states}; typenames := array[] of {	Terror => "error",	Tid => "id",	Tadt => "adt",	Tadtpick => "adtpick",	Tarray => "array",	Tbig => "big",	Tbyte => "byte",	Tchan => "chan",	Treal => "real",	Tfn => "fn",	Targ => "arg",	Tlocal => "local",	Tglobal => "global",	Tint => "int",	Tlist => "list",	Tmodule => "module",	Tnil => "nil",	Tnone => "none",	Tref => "ref",	Tstring => "string",	Ttuple => "tuple",	Tend => "end",	Targs => "args",	Tslice => "slice",	Tpoly => "poly",}; tnone:		ref Type;tnil:		ref Type;tint:		ref Type;tbyte:		ref Type;tbig:		ref Type;treal:		ref Type;tstring:	ref Type;tpoly:	ref Type; IBY2WD:		con 4;IBY2LG:		con 8;H:		con int 16rffffffff; ModHash:	con 32;SymHash:	con 32;mods:=		array[ModHash] of list of ref Module;syms:=		array[SymHash] of list of ref Sym; sblpath :=	array[] of{	("/dis/",	"/appl/cmd/"),	("/dis/",	"/appl/"),}; init(): int{	sys = load Sys Sys->PATH;	str = load String String->PATH;	if(sys == nil || str == nil)		return 0;	tnone = ref Type(nil, Tnone, 0, "", nil, nil, nil);	tnil = ref Type(nil, Tnil, IBY2WD, "nil", nil, nil, nil);	tint = ref Type(nil, Tint, IBY2WD, "int", nil, nil, nil);	tbyte = ref Type(nil, Tbyte, 1, "byte", nil, nil, nil);	tbig = ref Type(nil, Tbig, IBY2LG, "big", nil, nil, nil);	treal = ref Type(nil, Treal, IBY2LG, "real", nil, nil, nil);	tstring = ref Type(nil, Tstring, IBY2WD, "string", nil, nil, nil);	tpoly = ref Type(nil, Tpoly, IBY2WD, "polymorphic", nil, nil, nil);	return 1;} prog(pid: int): (ref Prog, string){	spid := string pid;	h := sys->open("/prog/"+spid+"/heap", sys->ORDWR);	if(h == nil)		return (nil, sprint("can't open heap file: %r"));	c := sys->open("/prog/"+spid+"/ctl", sys->OWRITE);	if(c == nil)		return (nil, sprint("can't open ctl file: %r"));	d := sys->open("/prog/"+spid+"/dbgctl", sys->ORDWR);	if(d == nil)		return (nil, sprint("can't open debug ctl file: %r"));	s := sys->open("/prog/"+spid+"/stack", sys->OREAD);	if(s == nil)		return (nil, sprint("can't open stack file: %r"));	return (ref Prog(pid, h, c, d, s), "");} startprog(dis, dir: string, ctxt: ref Draw->Context, argv: list of string): (ref Prog, string){	c := load Command dis;	if(c == nil)		return (nil, "module not loaded"); 	ack := chan of int;	spin := ref Spin(1, 1);	end := chan of int;	spawn execer(ack, dir, c, ctxt, argv, spin, end);	kid := <-ack; 	fd := sys->open("/prog/"+string kid+"/dbgctl", sys->ORDWR);	if(fd == nil){		spin.spin = -1;		<- end;		return (nil, sprint("can't open debug ctl file: %r"));	}	done := chan of string;	spawn stepper(done, fd, spin); wait:	for(;;){		alt{		<-ack =>			sys->sleep(0);		err := <-done =>			if(err != ""){				<- end;				return(nil, err);			}			break wait;		}	} 	b := array[20] of byte;	n := sys->read(fd, b, len b);	if(n <= 0){		<- end;		return(nil, sprint("%r"));	}	msg := string b[:n];	if(!str->prefix("new ", msg)){		<- end;		return (nil, msg);	} 	kid = int msg[len "new ":]; 	# clean up the execer slave	b = array of byte "start";	sys->write(fd, b, len b); 	<- end;	return prog(kid);} stepper(done: chan of string, ctl: ref FD, spin: ref Spin){	b := array of byte "step1";	while(spin.pspin){		if(sys->write(ctl, b, len b) != len b)			done <-= sprint("can't start new thread: %r");		spin.spin = 0;	}	done <-= "";} execer(ack: chan of int, dir: string, c: Command, ctxt: ref Draw->Context, args: list of string, spin: ref Spin, end: chan of int){	pid := sys->pctl(Sys->NEWPGRP|Sys->FORKNS|Sys->NEWFD, 0::1::2::nil);	sys->chdir(dir);	while(spin.spin == 1)		ack <-= pid;	if(spin.spin == -1){		end <-= 0;		exit;	}	spawn c->init(ctxt, args);	spin.pspin = 0;	end <-= 0;	exit;} # format of each line is# fp pc mp prog compiled path# fp, pc, mp, and prog are %.8lux# compile is  or 1# path is a stringProg.stack(p: self ref Prog): (array of ref Exp, string){	buf := array[8192] of byte;	sys->seek(p.stk, big 0, 0);	n := sys->read(p.stk, buf, len buf - 1);	if(n < 0)		return (nil, sprint("can't read stack file: %r"));	buf[n] = byte 0; 	t := 0;	nf := 0;	for(s := 0; s < n; s = t+1){		t = strchr(buf, s, '\n');		if(buf[t] != byte '\n' || t-s < 40)			continue;		nf++;	} 	e := array[nf] of ref Exp;	nf = 0;	for(s = 0; s < n; s = t+1){		t = strchr(buf, s, '\n');		if(buf[t] != byte '\n' || t-s < 40)			continue;		e[nf] = ref Exp("unknown fn",				hex(buf[s+0:s+8]), 				hex(buf[s+9:s+17]),				mkmod(hex(buf[s+18:s+26]), hex(buf[s+27:s+35]), buf[36] != byte '0', string buf[s+38:t]),				p,				nil);		nf++;	} 	return (e, "");} Prog.step(p: self ref Prog, how: int): string{	(stack, nil) := p.stack();	if(stack == nil)		return "can't find initial pc";	src := stack[0].srcstr();	stmt := ftostmt(stack[0]); 	if(stack[0].m.sym == nil)		how = -1; 	buf := array of byte("step1");	if(how == StepOut)		buf = array of byte("toret");	while(sys->write(p.dbgctl, buf, len buf) == len buf){		(stk, err) := p.stack();		if(err != nil)			return "";		case how{		StepExp =>			if(src != stk[0].srcstr())				return "";		StepStmt =>			if(stmt != ftostmt(stk[0]))				return "";			if(stk[0].offset != stack[0].offset)				return "";		StepOut =>			if(returned(stack, stk))				return "";		StepOver =>			if(stk[0].offset == stack[0].offset){				if(stmt != ftostmt(stk[0]))					return "";				buf = array of byte("step1");				break;			}			if(returned(stack, stk))				return "";			buf = array of byte("toret");		* =>			return "";		}	}	return sprint("%r");} Prog.stop(p: self ref Prog): string{	return dbgctl(p, "stop");} Prog.unstop(p: self ref Prog): string{	return dbgctl(p, "unstop");} Prog.grab(p: self ref Prog): string{	return dbgctl(p, "step0");} Prog.start(p: self ref Prog): string{	return dbgctl(p, "start");} Prog.cont(p: self ref Prog): string{	return dbgctl(p, "cont");} dbgctl(p: ref Prog, msg: string): string{	b := array of byte msg;	while(sys->write(p.dbgctl, b, len b) != len b)		return sprint("%r");	return "";} returned(old, new: array of ref Exp): int{	n := len old;	if(n > len new)		return 1;	return 0;} Prog.setbpt(p: self ref Prog, dis: string, pc:int): string{	b := array of byte("bpt set "+dis+" "+string pc);	if(sys->write(p.dbgctl, b, len b) != len b)		return sprint("can't set breakpoint: %r");	return "";} Prog.delbpt(p: self ref Prog, dis: string, pc:int): string{	b := array of byte("bpt del "+dis+" "+string pc);	if(sys->write(p.dbgctl, b, len b) != len b)		return sprint("can't del breakpoint: %r");	return "";} Prog.kill(p: self ref Prog): string{	b := array of byte "kill";	if(sys->write(p.ctl, b, len b) != len b)		return sprint("can't kill process: %r");	return "";} Prog.event(p: self ref Prog): string{	b := array[100] of byte;	n := sys->read(p.dbgctl, b, len b);	if(n < 0)		return sprint("error: %r");	return string b[:n];} ftostmt(e: ref Exp): int{	m := e.m;	if(!m.comp && m.sym != nil && e.pc < len m.sym.srcstmt)		return m.sym.srcstmt[e.pc];	return -1;} Exp.srcstr(e: self ref Exp): string{	m := e.m;	if(!m.comp && m.sym != nil && e.pc < len m.sym.src){		src := m.sym.src[e.pc];		ss := src.start.file+":"+string src.start.line+"."+string src.start.pos+", ";		if(src.stop.file != src.start.file)			ss += src.stop.file+":"+string src.stop.line+".";		else if(src.stop.line != src.start.line)			ss += string src.stop.line+".";		return ss+string src.stop.pos;	}	return sprint("Module %s PC %d", e.m.path, e.pc);} Exp.findsym(e: self ref Exp): string{	m := e.m;	if(m.comp)		return "compiled module";	if(m.sym != nil){		n := e.pc;		fns := m.sym.fns;		for(i := 0; i < len fns; i++){			if(n >= fns[i].offset && n < fns[i].stoppc){				e.name = fns[i].name;				e.id = fns[i];				return "";			}		}		return "pc out of bounds";	}	return "no symbol file";} Exp.src(e: self ref Exp): ref Src{	m := e.m;	if(e.id == nil || m.sym == nil)		return nil;	src := e.id.src;	if(src != nil)		return src;	if(e.id.t.kind == Tfn && !m.comp && e.pc < len m.sym.src && e.pc >= 0)		return m.sym.src[e.pc];	return nil;} Type.getkind(t: self ref Type, sym: ref Sym): int{	if(t == nil)		return -1;	if(t.kind == Tid)		return sym.adts[int t.name].getkind(sym);	return t.kind;} Type.text(t: self ref Type, sym: ref Sym): string{	if (t == nil)		return "no type";	s := typenames[t.kind];	case t.kind {	Tadt or	Tadtpick or	Tmodule =>		s = t.name;	Tid =>		return sym.adts[int t.name].text(sym);	Tarray or	Tlist or	Tchan or	Tslice =>		s += " of " + t.Of.text(sym);	Tref =>		s += " " + t.Of.text(sym);	Tfn =>		s += "(";			for(i := 0; i < len t.ids; i++)			s += t.ids[i].name + ": " + t.ids[i].t.text(sym);		s += "): " + t.Of.text(sym);	Ttuple or	Tlocal or	Tglobal or	Targ =>		if(t.kind == Ttuple)			s = "";		s += "(";		for (i := 0; i < len t.ids; i++) {			s += t.ids[i].t.text(sym);			if (i < len t.ids - 1)				s += ", ";		}		s += ")";	}	return s;} Exp.typename(e: self ref Exp): string{	if (e.id == nil)		return "no info";	return e.id.t.text(e.m.sym);} Exp.kind(e: self ref Exp): int{	if(e.id == nil)		return -1;	return e.id.t.getkind(e.m.sym);} EXPLISTMAX : con	32;	# what's a good value for this ? Exp.expand(e: self ref Exp): array of ref Exp{	if(e.id == nil)		return nil; 	t := e.id.t;	if(t.kind == Tid)		t = e.m.sym.adts[int t.name]; 	off := e.offset;

Lines 1–500 of 1493.