137da2899SCharles.Forsythimplement Debug; 237da2899SCharles.Forsyth 337da2899SCharles.Forsythinclude "sys.m"; 437da2899SCharles.Forsythsys: Sys; 537da2899SCharles.Forsythsprint, FD: import sys; 637da2899SCharles.Forsyth 737da2899SCharles.Forsythinclude "string.m"; 837da2899SCharles.Forsythstr: String; 937da2899SCharles.Forsyth 1037da2899SCharles.Forsythinclude "draw.m"; 1137da2899SCharles.Forsyth 1237da2899SCharles.Forsythinclude "debug.m"; 1337da2899SCharles.Forsyth 1437da2899SCharles.Forsythinclude "dis.m"; 1537da2899SCharles.Forsyth dism: Dis; 1637da2899SCharles.Forsyth 1737da2899SCharles.ForsythCommand: module 1837da2899SCharles.Forsyth{ 1937da2899SCharles.Forsyth init: fn(ctxt: ref Draw->Context, argv: list of string); 2037da2899SCharles.Forsyth}; 2137da2899SCharles.Forsyth 2237da2899SCharles.ForsythSpin: adt 2337da2899SCharles.Forsyth{ 2437da2899SCharles.Forsyth spin: int; 2537da2899SCharles.Forsyth pspin: int; 2637da2899SCharles.Forsyth}; 2737da2899SCharles.Forsyth 2837da2899SCharles.ForsythSrcState: adt 2937da2899SCharles.Forsyth{ 3037da2899SCharles.Forsyth files: array of string; 3137da2899SCharles.Forsyth lastf: int; 3237da2899SCharles.Forsyth lastl: int; 3337da2899SCharles.Forsyth vers: int; # version number 3437da2899SCharles.Forsyth # 11 => more source states 3537da2899SCharles.Forsyth}; 3637da2899SCharles.Forsyth 3737da2899SCharles.Forsythtypenames := array[] of { 3837da2899SCharles.Forsyth Terror => "error", 3937da2899SCharles.Forsyth Tid => "id", 4037da2899SCharles.Forsyth Tadt => "adt", 4137da2899SCharles.Forsyth Tadtpick => "adtpick", 4237da2899SCharles.Forsyth Tarray => "array", 4337da2899SCharles.Forsyth Tbig => "big", 4437da2899SCharles.Forsyth Tbyte => "byte", 4537da2899SCharles.Forsyth Tchan => "chan", 4637da2899SCharles.Forsyth Treal => "real", 4737da2899SCharles.Forsyth Tfn => "fn", 4837da2899SCharles.Forsyth Targ => "arg", 4937da2899SCharles.Forsyth Tlocal => "local", 5037da2899SCharles.Forsyth Tglobal => "global", 5137da2899SCharles.Forsyth Tint => "int", 5237da2899SCharles.Forsyth Tlist => "list", 5337da2899SCharles.Forsyth Tmodule => "module", 5437da2899SCharles.Forsyth Tnil => "nil", 5537da2899SCharles.Forsyth Tnone => "none", 5637da2899SCharles.Forsyth Tref => "ref", 5737da2899SCharles.Forsyth Tstring => "string", 5837da2899SCharles.Forsyth Ttuple => "tuple", 5937da2899SCharles.Forsyth Tend => "end", 6037da2899SCharles.Forsyth Targs => "args", 6137da2899SCharles.Forsyth Tslice => "slice", 6237da2899SCharles.Forsyth Tpoly => "poly", 6337da2899SCharles.Forsyth}; 6437da2899SCharles.Forsyth 6537da2899SCharles.Forsythtnone: ref Type; 6637da2899SCharles.Forsythtnil: ref Type; 6737da2899SCharles.Forsythtint: ref Type; 6837da2899SCharles.Forsythtbyte: ref Type; 6937da2899SCharles.Forsythtbig: ref Type; 7037da2899SCharles.Forsythtreal: ref Type; 7137da2899SCharles.Forsythtstring: ref Type; 7237da2899SCharles.Forsythtpoly: ref Type; 7337da2899SCharles.Forsyth 7437da2899SCharles.ForsythIBY2WD: con 4; 7537da2899SCharles.ForsythIBY2LG: con 8; 7637da2899SCharles.ForsythH: con int 16rffffffff; 7737da2899SCharles.Forsyth 7837da2899SCharles.ForsythModHash: con 32; 7937da2899SCharles.ForsythSymHash: con 32; 8037da2899SCharles.Forsythmods:= array[ModHash] of list of ref Module; 8137da2899SCharles.Forsythsyms:= array[SymHash] of list of ref Sym; 8237da2899SCharles.Forsyth 8337da2899SCharles.Forsythsblpath := array[] of 8437da2899SCharles.Forsyth{ 8537da2899SCharles.Forsyth ("/dis/", "/appl/cmd/"), 8637da2899SCharles.Forsyth ("/dis/", "/appl/"), 8737da2899SCharles.Forsyth}; 8837da2899SCharles.Forsyth 8937da2899SCharles.Forsythinit(): int 9037da2899SCharles.Forsyth{ 9137da2899SCharles.Forsyth sys = load Sys Sys->PATH; 9237da2899SCharles.Forsyth str = load String String->PATH; 9337da2899SCharles.Forsyth if(sys == nil || str == nil) 9437da2899SCharles.Forsyth return 0; 9537da2899SCharles.Forsyth tnone = ref Type(nil, Tnone, 0, "", nil, nil, nil); 9637da2899SCharles.Forsyth tnil = ref Type(nil, Tnil, IBY2WD, "nil", nil, nil, nil); 9737da2899SCharles.Forsyth tint = ref Type(nil, Tint, IBY2WD, "int", nil, nil, nil); 9837da2899SCharles.Forsyth tbyte = ref Type(nil, Tbyte, 1, "byte", nil, nil, nil); 9937da2899SCharles.Forsyth tbig = ref Type(nil, Tbig, IBY2LG, "big", nil, nil, nil); 10037da2899SCharles.Forsyth treal = ref Type(nil, Treal, IBY2LG, "real", nil, nil, nil); 10137da2899SCharles.Forsyth tstring = ref Type(nil, Tstring, IBY2WD, "string", nil, nil, nil); 10237da2899SCharles.Forsyth tpoly = ref Type(nil, Tpoly, IBY2WD, "polymorphic", nil, nil, nil); 10337da2899SCharles.Forsyth return 1; 10437da2899SCharles.Forsyth} 10537da2899SCharles.Forsyth 10637da2899SCharles.Forsythprog(pid: int): (ref Prog, string) 10737da2899SCharles.Forsyth{ 10837da2899SCharles.Forsyth spid := string pid; 10937da2899SCharles.Forsyth h := sys->open("/prog/"+spid+"/heap", sys->ORDWR); 11037da2899SCharles.Forsyth if(h == nil) 11137da2899SCharles.Forsyth return (nil, sprint("can't open heap file: %r")); 11237da2899SCharles.Forsyth c := sys->open("/prog/"+spid+"/ctl", sys->OWRITE); 11337da2899SCharles.Forsyth if(c == nil) 11437da2899SCharles.Forsyth return (nil, sprint("can't open ctl file: %r")); 11537da2899SCharles.Forsyth d := sys->open("/prog/"+spid+"/dbgctl", sys->ORDWR); 11637da2899SCharles.Forsyth if(d == nil) 11737da2899SCharles.Forsyth return (nil, sprint("can't open debug ctl file: %r")); 11837da2899SCharles.Forsyth s := sys->open("/prog/"+spid+"/stack", sys->OREAD); 11937da2899SCharles.Forsyth if(s == nil) 12037da2899SCharles.Forsyth return (nil, sprint("can't open stack file: %r")); 12137da2899SCharles.Forsyth return (ref Prog(pid, h, c, d, s), ""); 12237da2899SCharles.Forsyth} 12337da2899SCharles.Forsyth 12437da2899SCharles.Forsythstartprog(dis, dir: string, ctxt: ref Draw->Context, argv: list of string): (ref Prog, string) 12537da2899SCharles.Forsyth{ 12637da2899SCharles.Forsyth c := load Command dis; 12737da2899SCharles.Forsyth if(c == nil) 12837da2899SCharles.Forsyth return (nil, "module not loaded"); 12937da2899SCharles.Forsyth 13037da2899SCharles.Forsyth ack := chan of int; 13137da2899SCharles.Forsyth spin := ref Spin(1, 1); 13237da2899SCharles.Forsyth end := chan of int; 13337da2899SCharles.Forsyth spawn execer(ack, dir, c, ctxt, argv, spin, end); 13437da2899SCharles.Forsyth kid := <-ack; 13537da2899SCharles.Forsyth 13637da2899SCharles.Forsyth fd := sys->open("/prog/"+string kid+"/dbgctl", sys->ORDWR); 13737da2899SCharles.Forsyth if(fd == nil){ 13837da2899SCharles.Forsyth spin.spin = -1; 13937da2899SCharles.Forsyth <- end; 14037da2899SCharles.Forsyth return (nil, sprint("can't open debug ctl file: %r")); 14137da2899SCharles.Forsyth } 14237da2899SCharles.Forsyth done := chan of string; 14337da2899SCharles.Forsyth spawn stepper(done, fd, spin); 14437da2899SCharles.Forsyth 14537da2899SCharles.Forsythwait: for(;;){ 14637da2899SCharles.Forsyth alt{ 14737da2899SCharles.Forsyth <-ack => 14837da2899SCharles.Forsyth sys->sleep(0); 14937da2899SCharles.Forsyth err := <-done => 15037da2899SCharles.Forsyth if(err != ""){ 15137da2899SCharles.Forsyth <- end; 15237da2899SCharles.Forsyth return(nil, err); 15337da2899SCharles.Forsyth } 15437da2899SCharles.Forsyth break wait; 15537da2899SCharles.Forsyth } 15637da2899SCharles.Forsyth } 15737da2899SCharles.Forsyth 15837da2899SCharles.Forsyth b := array[20] of byte; 15937da2899SCharles.Forsyth n := sys->read(fd, b, len b); 16037da2899SCharles.Forsyth if(n <= 0){ 16137da2899SCharles.Forsyth <- end; 16237da2899SCharles.Forsyth return(nil, sprint("%r")); 16337da2899SCharles.Forsyth } 16437da2899SCharles.Forsyth msg := string b[:n]; 16537da2899SCharles.Forsyth if(!str->prefix("new ", msg)){ 16637da2899SCharles.Forsyth <- end; 16737da2899SCharles.Forsyth return (nil, msg); 16837da2899SCharles.Forsyth } 16937da2899SCharles.Forsyth 17037da2899SCharles.Forsyth kid = int msg[len "new ":]; 17137da2899SCharles.Forsyth 17237da2899SCharles.Forsyth # clean up the execer slave 17337da2899SCharles.Forsyth b = array of byte "start"; 17437da2899SCharles.Forsyth sys->write(fd, b, len b); 17537da2899SCharles.Forsyth 17637da2899SCharles.Forsyth <- end; 17737da2899SCharles.Forsyth return prog(kid); 17837da2899SCharles.Forsyth} 17937da2899SCharles.Forsyth 18037da2899SCharles.Forsythstepper(done: chan of string, ctl: ref FD, spin: ref Spin) 18137da2899SCharles.Forsyth{ 18237da2899SCharles.Forsyth b := array of byte "step1"; 18337da2899SCharles.Forsyth while(spin.pspin){ 18437da2899SCharles.Forsyth if(sys->write(ctl, b, len b) != len b) 18537da2899SCharles.Forsyth done <-= sprint("can't start new thread: %r"); 18637da2899SCharles.Forsyth spin.spin = 0; 18737da2899SCharles.Forsyth } 18837da2899SCharles.Forsyth done <-= ""; 18937da2899SCharles.Forsyth} 19037da2899SCharles.Forsyth 19137da2899SCharles.Forsythexecer(ack: chan of int, dir: string, c: Command, ctxt: ref Draw->Context, args: list of string, spin: ref Spin, end: chan of int) 19237da2899SCharles.Forsyth{ 19337da2899SCharles.Forsyth pid := sys->pctl(Sys->NEWPGRP|Sys->FORKNS|Sys->NEWFD, 0::1::2::nil); 19437da2899SCharles.Forsyth sys->chdir(dir); 19537da2899SCharles.Forsyth while(spin.spin == 1) 19637da2899SCharles.Forsyth ack <-= pid; 19737da2899SCharles.Forsyth if(spin.spin == -1){ 19837da2899SCharles.Forsyth end <-= 0; 19937da2899SCharles.Forsyth exit; 20037da2899SCharles.Forsyth } 20137da2899SCharles.Forsyth spawn c->init(ctxt, args); 20237da2899SCharles.Forsyth spin.pspin = 0; 20337da2899SCharles.Forsyth end <-= 0; 20437da2899SCharles.Forsyth exit; 20537da2899SCharles.Forsyth} 20637da2899SCharles.Forsyth 20737da2899SCharles.Forsyth# format of each line is 20837da2899SCharles.Forsyth# fp pc mp prog compiled path 20937da2899SCharles.Forsyth# fp, pc, mp, and prog are %.8lux 21037da2899SCharles.Forsyth# compile is or 1 21137da2899SCharles.Forsyth# path is a string 21237da2899SCharles.ForsythProg.stack(p: self ref Prog): (array of ref Exp, string) 21337da2899SCharles.Forsyth{ 21437da2899SCharles.Forsyth buf := array[8192] of byte; 21537da2899SCharles.Forsyth sys->seek(p.stk, big 0, 0); 21637da2899SCharles.Forsyth n := sys->read(p.stk, buf, len buf - 1); 21737da2899SCharles.Forsyth if(n < 0) 21837da2899SCharles.Forsyth return (nil, sprint("can't read stack file: %r")); 21937da2899SCharles.Forsyth buf[n] = byte 0; 22037da2899SCharles.Forsyth 22137da2899SCharles.Forsyth t := 0; 22237da2899SCharles.Forsyth nf := 0; 22337da2899SCharles.Forsyth for(s := 0; s < n; s = t+1){ 22437da2899SCharles.Forsyth t = strchr(buf, s, '\n'); 22537da2899SCharles.Forsyth if(buf[t] != byte '\n' || t-s < 40) 22637da2899SCharles.Forsyth continue; 22737da2899SCharles.Forsyth nf++; 22837da2899SCharles.Forsyth } 22937da2899SCharles.Forsyth 23037da2899SCharles.Forsyth e := array[nf] of ref Exp; 23137da2899SCharles.Forsyth nf = 0; 23237da2899SCharles.Forsyth for(s = 0; s < n; s = t+1){ 23337da2899SCharles.Forsyth t = strchr(buf, s, '\n'); 23437da2899SCharles.Forsyth if(buf[t] != byte '\n' || t-s < 40) 23537da2899SCharles.Forsyth continue; 23637da2899SCharles.Forsyth e[nf] = ref Exp("unknown fn", 23737da2899SCharles.Forsyth hex(buf[s+0:s+8]), 23837da2899SCharles.Forsyth hex(buf[s+9:s+17]), 23937da2899SCharles.Forsyth mkmod(hex(buf[s+18:s+26]), hex(buf[s+27:s+35]), buf[36] != byte '0', string buf[s+38:t]), 24037da2899SCharles.Forsyth p, 24137da2899SCharles.Forsyth nil); 24237da2899SCharles.Forsyth nf++; 24337da2899SCharles.Forsyth } 24437da2899SCharles.Forsyth 24537da2899SCharles.Forsyth return (e, ""); 24637da2899SCharles.Forsyth} 24737da2899SCharles.Forsyth 24837da2899SCharles.ForsythProg.step(p: self ref Prog, how: int): string 24937da2899SCharles.Forsyth{ 25037da2899SCharles.Forsyth (stack, nil) := p.stack(); 25137da2899SCharles.Forsyth if(stack == nil) 25237da2899SCharles.Forsyth return "can't find initial pc"; 25337da2899SCharles.Forsyth src := stack[0].srcstr(); 25437da2899SCharles.Forsyth stmt := ftostmt(stack[0]); 25537da2899SCharles.Forsyth 25637da2899SCharles.Forsyth if(stack[0].m.sym == nil) 25737da2899SCharles.Forsyth how = -1; 25837da2899SCharles.Forsyth 25937da2899SCharles.Forsyth buf := array of byte("step1"); 26037da2899SCharles.Forsyth if(how == StepOut) 26137da2899SCharles.Forsyth buf = array of byte("toret"); 26237da2899SCharles.Forsyth while(sys->write(p.dbgctl, buf, len buf) == len buf){ 26337da2899SCharles.Forsyth (stk, err) := p.stack(); 26437da2899SCharles.Forsyth if(err != nil) 26537da2899SCharles.Forsyth return ""; 26637da2899SCharles.Forsyth case how{ 26737da2899SCharles.Forsyth StepExp => 26837da2899SCharles.Forsyth if(src != stk[0].srcstr()) 26937da2899SCharles.Forsyth return ""; 27037da2899SCharles.Forsyth StepStmt => 27137da2899SCharles.Forsyth if(stmt != ftostmt(stk[0])) 27237da2899SCharles.Forsyth return ""; 27337da2899SCharles.Forsyth if(stk[0].offset != stack[0].offset) 27437da2899SCharles.Forsyth return ""; 27537da2899SCharles.Forsyth StepOut => 27637da2899SCharles.Forsyth if(returned(stack, stk)) 27737da2899SCharles.Forsyth return ""; 27837da2899SCharles.Forsyth StepOver => 27937da2899SCharles.Forsyth if(stk[0].offset == stack[0].offset){ 28037da2899SCharles.Forsyth if(stmt != ftostmt(stk[0])) 28137da2899SCharles.Forsyth return ""; 28237da2899SCharles.Forsyth buf = array of byte("step1"); 28337da2899SCharles.Forsyth break; 28437da2899SCharles.Forsyth } 28537da2899SCharles.Forsyth if(returned(stack, stk)) 28637da2899SCharles.Forsyth return ""; 28737da2899SCharles.Forsyth buf = array of byte("toret"); 28837da2899SCharles.Forsyth * => 28937da2899SCharles.Forsyth return ""; 29037da2899SCharles.Forsyth } 29137da2899SCharles.Forsyth } 29237da2899SCharles.Forsyth return sprint("%r"); 29337da2899SCharles.Forsyth} 29437da2899SCharles.Forsyth 29537da2899SCharles.ForsythProg.stop(p: self ref Prog): string 29637da2899SCharles.Forsyth{ 29737da2899SCharles.Forsyth return dbgctl(p, "stop"); 29837da2899SCharles.Forsyth} 29937da2899SCharles.Forsyth 30037da2899SCharles.ForsythProg.unstop(p: self ref Prog): string 30137da2899SCharles.Forsyth{ 30237da2899SCharles.Forsyth return dbgctl(p, "unstop"); 30337da2899SCharles.Forsyth} 30437da2899SCharles.Forsyth 30537da2899SCharles.ForsythProg.grab(p: self ref Prog): string 30637da2899SCharles.Forsyth{ 30737da2899SCharles.Forsyth return dbgctl(p, "step0"); 30837da2899SCharles.Forsyth} 30937da2899SCharles.Forsyth 31037da2899SCharles.ForsythProg.start(p: self ref Prog): string 31137da2899SCharles.Forsyth{ 31237da2899SCharles.Forsyth return dbgctl(p, "start"); 31337da2899SCharles.Forsyth} 31437da2899SCharles.Forsyth 31537da2899SCharles.ForsythProg.cont(p: self ref Prog): string 31637da2899SCharles.Forsyth{ 31737da2899SCharles.Forsyth return dbgctl(p, "cont"); 31837da2899SCharles.Forsyth} 31937da2899SCharles.Forsyth 32037da2899SCharles.Forsythdbgctl(p: ref Prog, msg: string): string 32137da2899SCharles.Forsyth{ 32237da2899SCharles.Forsyth b := array of byte msg; 32337da2899SCharles.Forsyth while(sys->write(p.dbgctl, b, len b) != len b) 32437da2899SCharles.Forsyth return sprint("%r"); 32537da2899SCharles.Forsyth return ""; 32637da2899SCharles.Forsyth} 32737da2899SCharles.Forsyth 32837da2899SCharles.Forsythreturned(old, new: array of ref Exp): int 32937da2899SCharles.Forsyth{ 33037da2899SCharles.Forsyth n := len old; 33137da2899SCharles.Forsyth if(n > len new) 33237da2899SCharles.Forsyth return 1; 33337da2899SCharles.Forsyth return 0; 33437da2899SCharles.Forsyth} 33537da2899SCharles.Forsyth 33637da2899SCharles.ForsythProg.setbpt(p: self ref Prog, dis: string, pc:int): string 33737da2899SCharles.Forsyth{ 33837da2899SCharles.Forsyth b := array of byte("bpt set "+dis+" "+string pc); 33937da2899SCharles.Forsyth if(sys->write(p.dbgctl, b, len b) != len b) 34037da2899SCharles.Forsyth return sprint("can't set breakpoint: %r"); 34137da2899SCharles.Forsyth return ""; 34237da2899SCharles.Forsyth} 34337da2899SCharles.Forsyth 34437da2899SCharles.ForsythProg.delbpt(p: self ref Prog, dis: string, pc:int): string 34537da2899SCharles.Forsyth{ 34637da2899SCharles.Forsyth b := array of byte("bpt del "+dis+" "+string pc); 34737da2899SCharles.Forsyth if(sys->write(p.dbgctl, b, len b) != len b) 34837da2899SCharles.Forsyth return sprint("can't del breakpoint: %r"); 34937da2899SCharles.Forsyth return ""; 35037da2899SCharles.Forsyth} 35137da2899SCharles.Forsyth 35237da2899SCharles.ForsythProg.kill(p: self ref Prog): string 35337da2899SCharles.Forsyth{ 35437da2899SCharles.Forsyth b := array of byte "kill"; 35537da2899SCharles.Forsyth if(sys->write(p.ctl, b, len b) != len b) 35637da2899SCharles.Forsyth return sprint("can't kill process: %r"); 35737da2899SCharles.Forsyth return ""; 35837da2899SCharles.Forsyth} 35937da2899SCharles.Forsyth 36037da2899SCharles.ForsythProg.event(p: self ref Prog): string 36137da2899SCharles.Forsyth{ 36237da2899SCharles.Forsyth b := array[100] of byte; 36337da2899SCharles.Forsyth n := sys->read(p.dbgctl, b, len b); 36437da2899SCharles.Forsyth if(n < 0) 36537da2899SCharles.Forsyth return sprint("error: %r"); 36637da2899SCharles.Forsyth return string b[:n]; 36737da2899SCharles.Forsyth} 36837da2899SCharles.Forsyth 36937da2899SCharles.Forsythftostmt(e: ref Exp): int 37037da2899SCharles.Forsyth{ 37137da2899SCharles.Forsyth m := e.m; 37237da2899SCharles.Forsyth if(!m.comp && m.sym != nil && e.pc < len m.sym.srcstmt) 37337da2899SCharles.Forsyth return m.sym.srcstmt[e.pc]; 37437da2899SCharles.Forsyth return -1; 37537da2899SCharles.Forsyth} 37637da2899SCharles.Forsyth 37737da2899SCharles.ForsythExp.srcstr(e: self ref Exp): string 37837da2899SCharles.Forsyth{ 37937da2899SCharles.Forsyth m := e.m; 38037da2899SCharles.Forsyth if(!m.comp && m.sym != nil && e.pc < len m.sym.src){ 38137da2899SCharles.Forsyth src := m.sym.src[e.pc]; 38237da2899SCharles.Forsyth ss := src.start.file+":"+string src.start.line+"."+string src.start.pos+", "; 38337da2899SCharles.Forsyth if(src.stop.file != src.start.file) 38437da2899SCharles.Forsyth ss += src.stop.file+":"+string src.stop.line+"."; 38537da2899SCharles.Forsyth else if(src.stop.line != src.start.line) 38637da2899SCharles.Forsyth ss += string src.stop.line+"."; 38737da2899SCharles.Forsyth return ss+string src.stop.pos; 38837da2899SCharles.Forsyth } 38937da2899SCharles.Forsyth return sprint("Module %s PC %d", e.m.path, e.pc); 39037da2899SCharles.Forsyth} 39137da2899SCharles.Forsyth 39237da2899SCharles.ForsythExp.findsym(e: self ref Exp): string 39337da2899SCharles.Forsyth{ 39437da2899SCharles.Forsyth m := e.m; 39537da2899SCharles.Forsyth if(m.comp) 39637da2899SCharles.Forsyth return "compiled module"; 39737da2899SCharles.Forsyth if(m.sym != nil){ 39837da2899SCharles.Forsyth n := e.pc; 39937da2899SCharles.Forsyth fns := m.sym.fns; 40037da2899SCharles.Forsyth for(i := 0; i < len fns; i++){ 40137da2899SCharles.Forsyth if(n >= fns[i].offset && n < fns[i].stoppc){ 40237da2899SCharles.Forsyth e.name = fns[i].name; 40337da2899SCharles.Forsyth e.id = fns[i]; 40437da2899SCharles.Forsyth return ""; 40537da2899SCharles.Forsyth } 40637da2899SCharles.Forsyth } 40737da2899SCharles.Forsyth return "pc out of bounds"; 40837da2899SCharles.Forsyth } 40937da2899SCharles.Forsyth return "no symbol file"; 41037da2899SCharles.Forsyth} 41137da2899SCharles.Forsyth 41237da2899SCharles.ForsythExp.src(e: self ref Exp): ref Src 41337da2899SCharles.Forsyth{ 41437da2899SCharles.Forsyth m := e.m; 41537da2899SCharles.Forsyth if(e.id == nil || m.sym == nil) 41637da2899SCharles.Forsyth return nil; 41737da2899SCharles.Forsyth src := e.id.src; 41837da2899SCharles.Forsyth if(src != nil) 41937da2899SCharles.Forsyth return src; 42037da2899SCharles.Forsyth if(e.id.t.kind == Tfn && !m.comp && e.pc < len m.sym.src && e.pc >= 0) 42137da2899SCharles.Forsyth return m.sym.src[e.pc]; 42237da2899SCharles.Forsyth return nil; 42337da2899SCharles.Forsyth} 42437da2899SCharles.Forsyth 42537da2899SCharles.ForsythType.getkind(t: self ref Type, sym: ref Sym): int 42637da2899SCharles.Forsyth{ 42737da2899SCharles.Forsyth if(t == nil) 42837da2899SCharles.Forsyth return -1; 42937da2899SCharles.Forsyth if(t.kind == Tid) 43037da2899SCharles.Forsyth return sym.adts[int t.name].getkind(sym); 43137da2899SCharles.Forsyth return t.kind; 43237da2899SCharles.Forsyth} 43337da2899SCharles.Forsyth 43437da2899SCharles.ForsythType.text(t: self ref Type, sym: ref Sym): string 43537da2899SCharles.Forsyth{ 43637da2899SCharles.Forsyth if (t == nil) 43737da2899SCharles.Forsyth return "no type"; 43837da2899SCharles.Forsyth s := typenames[t.kind]; 43937da2899SCharles.Forsyth case t.kind { 44037da2899SCharles.Forsyth Tadt or 44137da2899SCharles.Forsyth Tadtpick or 44237da2899SCharles.Forsyth Tmodule => 44337da2899SCharles.Forsyth s = t.name; 44437da2899SCharles.Forsyth Tid => 44537da2899SCharles.Forsyth return sym.adts[int t.name].text(sym); 44637da2899SCharles.Forsyth Tarray or 44737da2899SCharles.Forsyth Tlist or 44837da2899SCharles.Forsyth Tchan or 44937da2899SCharles.Forsyth Tslice => 45037da2899SCharles.Forsyth s += " of " + t.Of.text(sym); 45137da2899SCharles.Forsyth Tref => 45237da2899SCharles.Forsyth s += " " + t.Of.text(sym); 45337da2899SCharles.Forsyth Tfn => 45437da2899SCharles.Forsyth s += "("; 45537da2899SCharles.Forsyth for(i := 0; i < len t.ids; i++) 45637da2899SCharles.Forsyth s += t.ids[i].name + ": " + t.ids[i].t.text(sym); 45737da2899SCharles.Forsyth s += "): " + t.Of.text(sym); 45837da2899SCharles.Forsyth Ttuple or 45937da2899SCharles.Forsyth Tlocal or 46037da2899SCharles.Forsyth Tglobal or 46137da2899SCharles.Forsyth Targ => 46237da2899SCharles.Forsyth if(t.kind == Ttuple) 46337da2899SCharles.Forsyth s = ""; 46437da2899SCharles.Forsyth s += "("; 46537da2899SCharles.Forsyth for (i := 0; i < len t.ids; i++) { 46637da2899SCharles.Forsyth s += t.ids[i].t.text(sym); 46737da2899SCharles.Forsyth if (i < len t.ids - 1) 46837da2899SCharles.Forsyth s += ", "; 46937da2899SCharles.Forsyth } 47037da2899SCharles.Forsyth s += ")"; 47137da2899SCharles.Forsyth } 47237da2899SCharles.Forsyth return s; 47337da2899SCharles.Forsyth} 47437da2899SCharles.Forsyth 47537da2899SCharles.ForsythExp.typename(e: self ref Exp): string 47637da2899SCharles.Forsyth{ 47737da2899SCharles.Forsyth if (e.id == nil) 47837da2899SCharles.Forsyth return "no info"; 47937da2899SCharles.Forsyth return e.id.t.text(e.m.sym); 48037da2899SCharles.Forsyth} 48137da2899SCharles.Forsyth 48237da2899SCharles.ForsythExp.kind(e: self ref Exp): int 48337da2899SCharles.Forsyth{ 48437da2899SCharles.Forsyth if(e.id == nil) 48537da2899SCharles.Forsyth return -1; 48637da2899SCharles.Forsyth return e.id.t.getkind(e.m.sym); 48737da2899SCharles.Forsyth} 48837da2899SCharles.Forsyth 48937da2899SCharles.ForsythEXPLISTMAX : con 32; # what's a good value for this ? 49037da2899SCharles.Forsyth 49137da2899SCharles.ForsythExp.expand(e: self ref Exp): array of ref Exp 49237da2899SCharles.Forsyth{ 49337da2899SCharles.Forsyth if(e.id == nil) 49437da2899SCharles.Forsyth return nil; 49537da2899SCharles.Forsyth 49637da2899SCharles.Forsyth t := e.id.t; 49737da2899SCharles.Forsyth if(t.kind == Tid) 49837da2899SCharles.Forsyth t = e.m.sym.adts[int t.name]; 49937da2899SCharles.Forsyth 50037da2899SCharles.Forsyth off := e.offset; 50137da2899SCharles.Forsyth ids := t.ids; 50237da2899SCharles.Forsyth case t.kind{ 50337da2899SCharles.Forsyth Tadt or Tfn or Targ or Tlocal or Ttuple => 50437da2899SCharles.Forsyth break; 50537da2899SCharles.Forsyth Tadtpick => 50637da2899SCharles.Forsyth break; 50737da2899SCharles.Forsyth Tglobal => 50837da2899SCharles.Forsyth ids = e.m.sym.vars; 50937da2899SCharles.Forsyth off = e.m.data; 51037da2899SCharles.Forsyth Tmodule => 51137da2899SCharles.Forsyth (s, err) := pdata(e.p, off, "M"); 51237da2899SCharles.Forsyth if(s == "nil" || err != "") 51337da2899SCharles.Forsyth return nil; 51437da2899SCharles.Forsyth off = hex(array of byte s); 51537da2899SCharles.Forsyth Tref => 51637da2899SCharles.Forsyth (s, err) := pdata(e.p, off, "P"); 51737da2899SCharles.Forsyth if(s == "nil" || err != "") 51837da2899SCharles.Forsyth return nil; 51937da2899SCharles.Forsyth off = hex(array of byte s); 52037da2899SCharles.Forsyth et := t.Of; 52137da2899SCharles.Forsyth if(et.kind == Tid) 52237da2899SCharles.Forsyth et = e.m.sym.adts[int et.name]; 52337da2899SCharles.Forsyth ids = et.ids; 52437da2899SCharles.Forsyth if(et.kind == Tadtpick){ 52537da2899SCharles.Forsyth (s, err) = pdata(e.p, off, "W"); 52637da2899SCharles.Forsyth tg := int s; 52737da2899SCharles.Forsyth if(tg < 0 || tg > len et.tags || err != "" ) 52837da2899SCharles.Forsyth return nil; 52937da2899SCharles.Forsyth k := array[1 + len ids + len et.tags[tg].ids] of ref Exp; 53037da2899SCharles.Forsyth k[0] = ref Exp(et.tags[tg].name, off+0, e.pc, e.m, e.p, ref Id(et.src, et.tags[tg].name, 0, 0, tint)); 53137da2899SCharles.Forsyth x := 1; 53237da2899SCharles.Forsyth for(i := 0; i < len ids; i++){ 53337da2899SCharles.Forsyth id := ids[i]; 53437da2899SCharles.Forsyth k[i+x] = ref Exp(id.name, off+id.offset, e.pc, e.m, e.p, id); 53537da2899SCharles.Forsyth } 53637da2899SCharles.Forsyth x += len ids; 53737da2899SCharles.Forsyth ids = et.tags[tg].ids; 53837da2899SCharles.Forsyth for(i = 0; i < len ids; i++){ 53937da2899SCharles.Forsyth id := ids[i]; 54037da2899SCharles.Forsyth k[i+x] = ref Exp(id.name, off+id.offset, e.pc, e.m, e.p, id); 54137da2899SCharles.Forsyth } 54237da2899SCharles.Forsyth return k; 54337da2899SCharles.Forsyth } 54437da2899SCharles.Forsyth Tlist => 54537da2899SCharles.Forsyth (s, err) := pdata(e.p, off, "L"); 54637da2899SCharles.Forsyth if(err != "") 54737da2899SCharles.Forsyth return nil; 54837da2899SCharles.Forsyth (tloff, hdoff) := str->splitl(s, "."); 54937da2899SCharles.Forsyth hdoff = hdoff[1:]; 55037da2899SCharles.Forsyth k := array[2] of ref Exp; 55137da2899SCharles.Forsyth k[0] = ref Exp("hd", hex(array of byte hdoff), e.pc, e.m, e.p, ref Id(nil, "hd", H, H, t.Of)); 55237da2899SCharles.Forsyth k[1] = ref Exp("tl", hex(array of byte tloff), e.pc, e.m, e.p, ref Id(nil, "tl", H, H, t)); 55337da2899SCharles.Forsyth return k; 55437da2899SCharles.Forsyth Tarray => 5559b29ac7eSCharles.Forsyth (s, nil) := pdata(e.p, e.offset, "A"); 55637da2899SCharles.Forsyth if(s == "nil") 55737da2899SCharles.Forsyth return nil; 55837da2899SCharles.Forsyth (sn, sa) := str->splitl(s, "."); 55937da2899SCharles.Forsyth n := int sn; 56037da2899SCharles.Forsyth if(sa == "" || n <= 0) 56137da2899SCharles.Forsyth return nil; 56237da2899SCharles.Forsyth (off, nil) = str->toint(sa[1:], 16); 56337da2899SCharles.Forsyth et := t.Of; 56437da2899SCharles.Forsyth if(et.kind == Tid) 56537da2899SCharles.Forsyth et = e.m.sym.adts[int et.name]; 56637da2899SCharles.Forsyth esize := et.size; 56737da2899SCharles.Forsyth if (n <= EXPLISTMAX || EXPLISTMAX == 0) { 56837da2899SCharles.Forsyth k := array[n] of ref Exp; 56937da2899SCharles.Forsyth for(i := 0; i < n; i++){ 57037da2899SCharles.Forsyth name := string i; 57137da2899SCharles.Forsyth k[i] = ref Exp(name, off+i*esize, e.pc, e.m, e.p, ref Id(nil, name, H, H, et)); 57237da2899SCharles.Forsyth } 57337da2899SCharles.Forsyth return k; 57437da2899SCharles.Forsyth } 57537da2899SCharles.Forsyth else { 57637da2899SCharles.Forsyth # slice it 57737da2899SCharles.Forsyth (p, q, r) := partition(n, EXPLISTMAX); 57837da2899SCharles.Forsyth lb := 0; 57937da2899SCharles.Forsyth k := array[p] of ref Exp; 58037da2899SCharles.Forsyth st := ref Type(et.src, Tslice, 0, nil, et, nil, nil); 58137da2899SCharles.Forsyth for (i := 0; i < p; i++){ 58237da2899SCharles.Forsyth ub := lb+q-1; 58337da2899SCharles.Forsyth if (--r >= 0) 58437da2899SCharles.Forsyth ub++; 58537da2899SCharles.Forsyth name := string lb + ".." + string ub; 58637da2899SCharles.Forsyth k[i] = ref Exp(name, off+lb*esize, e.pc, e.m, e.p, ref Id(nil, name, H, H, st)); 58737da2899SCharles.Forsyth lb = ub+1; 58837da2899SCharles.Forsyth } 58937da2899SCharles.Forsyth return k; 59037da2899SCharles.Forsyth } 59137da2899SCharles.Forsyth Tslice => 59237da2899SCharles.Forsyth (lb, ub) := bounds(e.name); 59337da2899SCharles.Forsyth if (lb > ub) 59437da2899SCharles.Forsyth return nil; 59537da2899SCharles.Forsyth n := ub-lb+1; 59637da2899SCharles.Forsyth et := t.Of; 59737da2899SCharles.Forsyth if(et.kind == Tid) 59837da2899SCharles.Forsyth et = e.m.sym.adts[int et.name]; 59937da2899SCharles.Forsyth esize := et.size; 60037da2899SCharles.Forsyth if (n <= EXPLISTMAX || EXPLISTMAX == 0) { 60137da2899SCharles.Forsyth k := array[n] of ref Exp; 60237da2899SCharles.Forsyth for(i := 0; i < n; i++){ 60337da2899SCharles.Forsyth name := string (i+lb); 60437da2899SCharles.Forsyth k[i] = ref Exp(name, off+i*esize, e.pc, e.m, e.p, ref Id(nil, name, H, H, et)); 60537da2899SCharles.Forsyth } 60637da2899SCharles.Forsyth return k; 60737da2899SCharles.Forsyth } 60837da2899SCharles.Forsyth else { 60937da2899SCharles.Forsyth # slice it again 61037da2899SCharles.Forsyth (p, q, r) := partition(n, EXPLISTMAX); 61137da2899SCharles.Forsyth lb0 := lb; 61237da2899SCharles.Forsyth k := array[p] of ref Exp; 61337da2899SCharles.Forsyth st := ref Type(et.src, Tslice, 0, nil, et, nil, nil); 61437da2899SCharles.Forsyth for (i := 0; i < p; i++){ 61537da2899SCharles.Forsyth ub = lb+q-1; 61637da2899SCharles.Forsyth if (--r >= 0) 61737da2899SCharles.Forsyth ub++; 61837da2899SCharles.Forsyth name := string lb + ".." + string ub; 61937da2899SCharles.Forsyth k[i] = ref Exp(name, off+(lb-lb0)*esize, e.pc, e.m, e.p, ref Id(nil, name, H, H, st)); 62037da2899SCharles.Forsyth lb = ub+1; 62137da2899SCharles.Forsyth } 62237da2899SCharles.Forsyth return k; 62337da2899SCharles.Forsyth } 62437da2899SCharles.Forsyth Tchan => 6259b29ac7eSCharles.Forsyth (s, nil) := pdata(e.p, e.offset, "c"); 62637da2899SCharles.Forsyth if(s == "nil") 62737da2899SCharles.Forsyth return nil; 62837da2899SCharles.Forsyth (sn, sa) := str->splitl(s, "."); 62937da2899SCharles.Forsyth n := int sn; 63037da2899SCharles.Forsyth if(sa == "" || n <= 0) 63137da2899SCharles.Forsyth return nil; 63237da2899SCharles.Forsyth (off, nil) = str->toint(sa[1:], 16); 63337da2899SCharles.Forsyth (nil, sa) = str->splitl(sa[1:], "."); 63437da2899SCharles.Forsyth (sn, sa) = str->splitl(sa[1:], "."); 63537da2899SCharles.Forsyth f := int sn; 63637da2899SCharles.Forsyth sz := int sa[1:]; 63737da2899SCharles.Forsyth et := t.Of; 63837da2899SCharles.Forsyth if(et.kind == Tid) 63937da2899SCharles.Forsyth et = e.m.sym.adts[int et.name]; 64037da2899SCharles.Forsyth esize := et.size; 64137da2899SCharles.Forsyth k := array[sz] of ref Exp; 64237da2899SCharles.Forsyth for(i := 0; i < sz; i++){ 64337da2899SCharles.Forsyth name := string i; 64437da2899SCharles.Forsyth j := (f+i)%n; 64537da2899SCharles.Forsyth k[i] = ref Exp(name, off+j*esize, e.pc, e.m, e.p, ref Id(nil, name, H, H, et)); 64637da2899SCharles.Forsyth } 64737da2899SCharles.Forsyth return k; 64837da2899SCharles.Forsyth * => 64937da2899SCharles.Forsyth return nil; 65037da2899SCharles.Forsyth } 65137da2899SCharles.Forsyth k := array[len ids] of ref Exp; 65237da2899SCharles.Forsyth for(i := 0; i < len k; i++){ 65337da2899SCharles.Forsyth id := ids[i]; 65437da2899SCharles.Forsyth k[i] = ref Exp(id.name, off+id.offset, e.pc, e.m, e.p, id); 65537da2899SCharles.Forsyth } 65637da2899SCharles.Forsyth return k; 65737da2899SCharles.Forsyth} 65837da2899SCharles.Forsyth 65937da2899SCharles.ForsythExp.val(e: self ref Exp): (string, int) 66037da2899SCharles.Forsyth{ 66137da2899SCharles.Forsyth if(e.id == nil) 66237da2899SCharles.Forsyth return (e.m.path+" unknown fn", 0); 66337da2899SCharles.Forsyth t := e.id.t; 66437da2899SCharles.Forsyth if(t.kind == Tid) 66537da2899SCharles.Forsyth t = e.m.sym.adts[int t.name]; 66637da2899SCharles.Forsyth 66737da2899SCharles.Forsyth w := 0; 66837da2899SCharles.Forsyth s := ""; 66937da2899SCharles.Forsyth err := ""; 67037da2899SCharles.Forsyth p := e.p; 67137da2899SCharles.Forsyth case t.kind{ 67237da2899SCharles.Forsyth Tfn => 67337da2899SCharles.Forsyth if(t.ids != nil) 67437da2899SCharles.Forsyth w = 1; 67537da2899SCharles.Forsyth src := e.m.sym.src[e.pc]; 67637da2899SCharles.Forsyth ss := src.start.file+":"+string src.start.line+"."+string src.start.pos+", "; 67737da2899SCharles.Forsyth if(src.stop.file != src.start.file) 67837da2899SCharles.Forsyth ss += src.stop.file+":"+string src.stop.line+"."; 67937da2899SCharles.Forsyth else if(src.stop.line != src.start.line) 68037da2899SCharles.Forsyth ss += string src.stop.line+"."; 68137da2899SCharles.Forsyth return (ss+string src.stop.pos, w); 68237da2899SCharles.Forsyth Targ or Tlocal or Tglobal or Tadtpick or Ttuple => 68337da2899SCharles.Forsyth return ("", 1); 68437da2899SCharles.Forsyth Tadt => 68537da2899SCharles.Forsyth return ("#" + string e.offset, 1); 68637da2899SCharles.Forsyth Tnil => 68737da2899SCharles.Forsyth s = "nil"; 68837da2899SCharles.Forsyth Tbyte => 68937da2899SCharles.Forsyth (s, err) = pdata(p, e.offset, "B"); 69037da2899SCharles.Forsyth Tint => 69137da2899SCharles.Forsyth (s, err) = pdata(p, e.offset, "W"); 69237da2899SCharles.Forsyth Tbig => 69337da2899SCharles.Forsyth (s, err) = pdata(p, e.offset, "V"); 69437da2899SCharles.Forsyth Treal => 69537da2899SCharles.Forsyth (s, err) = pdata(p, e.offset, "R"); 69637da2899SCharles.Forsyth Tarray => 69737da2899SCharles.Forsyth (s, err) = pdata(p, e.offset, "A"); 69837da2899SCharles.Forsyth if(s == "nil") 69937da2899SCharles.Forsyth break; 70037da2899SCharles.Forsyth (n, a) := str->splitl(s, "."); 70137da2899SCharles.Forsyth if(a == "") 70237da2899SCharles.Forsyth return ("", 0); 70337da2899SCharles.Forsyth s = "["+n+"] @"+a[1:]; 70437da2899SCharles.Forsyth w = 1; 70537da2899SCharles.Forsyth Tslice => 70637da2899SCharles.Forsyth (lb, ub) := bounds(e.name); 70737da2899SCharles.Forsyth s = sys->sprint("[:%d] @ %x", ub-lb+1, e.offset); 70837da2899SCharles.Forsyth w = 1; 70937da2899SCharles.Forsyth Tstring => 71037da2899SCharles.Forsyth n : int; 71137da2899SCharles.Forsyth (n, s, err) = pstring(p, e.offset); 71237da2899SCharles.Forsyth if(err != "") 71337da2899SCharles.Forsyth return ("", 0); 71437da2899SCharles.Forsyth for(i := 0; i < len s; i++) 71537da2899SCharles.Forsyth if(s[i] == '\n') 71637da2899SCharles.Forsyth s[i] = '\u008a'; 71737da2899SCharles.Forsyth s = "["+string n+"] \""+s+"\""; 71837da2899SCharles.Forsyth Tref or Tlist or Tmodule or Tpoly=> 71937da2899SCharles.Forsyth (s, err) = pdata(p, e.offset, "P"); 72037da2899SCharles.Forsyth if(s == "nil") 72137da2899SCharles.Forsyth break; 72237da2899SCharles.Forsyth s = "@" + s; 72337da2899SCharles.Forsyth w = 1; 72437da2899SCharles.Forsyth Tchan => 72537da2899SCharles.Forsyth (s, err) = pdata(p, e.offset, "c"); 72637da2899SCharles.Forsyth if(s == "nil") 72737da2899SCharles.Forsyth break; 72837da2899SCharles.Forsyth (n, a) := str->splitl(s, "."); 72937da2899SCharles.Forsyth if(a == "") 73037da2899SCharles.Forsyth return ("", 0); 73137da2899SCharles.Forsyth if(n == "0"){ 73237da2899SCharles.Forsyth s = "@" + a[1:]; 73337da2899SCharles.Forsyth w = 0; 73437da2899SCharles.Forsyth } 73537da2899SCharles.Forsyth else{ 73637da2899SCharles.Forsyth (a, nil) = str->splitl(a[1:], "."); 73737da2899SCharles.Forsyth s = "["+n+"] @"+a; 73837da2899SCharles.Forsyth w = 1; 73937da2899SCharles.Forsyth } 74037da2899SCharles.Forsyth } 74137da2899SCharles.Forsyth if(err != "") 74237da2899SCharles.Forsyth return ("", 0); 74337da2899SCharles.Forsyth return (s, w); 74437da2899SCharles.Forsyth} 74537da2899SCharles.Forsyth 74637da2899SCharles.ForsythSym.srctopc(s: self ref Sym, src: ref Src): int 74737da2899SCharles.Forsyth{ 74837da2899SCharles.Forsyth srcs := s.src; 74937da2899SCharles.Forsyth line := src.start.line; 75037da2899SCharles.Forsyth pos := src.start.pos; 75137da2899SCharles.Forsyth (nil, file) := str->splitr(src.start.file, "/"); 75237da2899SCharles.Forsyth backup := -1; 75337da2899SCharles.Forsyth delta := 80; 75437da2899SCharles.Forsyth for(i := 0; i < len srcs; i++){ 75537da2899SCharles.Forsyth ss := srcs[i]; 75637da2899SCharles.Forsyth if(ss.start.file != file) 75737da2899SCharles.Forsyth continue; 75837da2899SCharles.Forsyth if(ss.start.line <= line && ss.start.pos <= pos 75937da2899SCharles.Forsyth && ss.stop.line >= line && ss.stop.pos >= pos) 76037da2899SCharles.Forsyth return i; 76137da2899SCharles.Forsyth d := ss.start.line - line; 76237da2899SCharles.Forsyth if(d >= 0 && d < delta){ 76337da2899SCharles.Forsyth delta = d; 76437da2899SCharles.Forsyth backup = i; 76537da2899SCharles.Forsyth } 76637da2899SCharles.Forsyth } 76737da2899SCharles.Forsyth return backup; 76837da2899SCharles.Forsyth} 76937da2899SCharles.Forsyth 77037da2899SCharles.ForsythSym.pctosrc(s: self ref Sym, pc: int): ref Src 77137da2899SCharles.Forsyth{ 77237da2899SCharles.Forsyth if(pc < 0 || pc >= len s.src) 77337da2899SCharles.Forsyth return nil; 77437da2899SCharles.Forsyth return s.src[pc]; 77537da2899SCharles.Forsyth} 77637da2899SCharles.Forsyth 77737da2899SCharles.Forsythsym(sbl: string): (ref Sym, string) 77837da2899SCharles.Forsyth{ 77937da2899SCharles.Forsyth h := 0; 78037da2899SCharles.Forsyth for(i := 0; i < len sbl; i++) 78137da2899SCharles.Forsyth h = (h << 1) + sbl[i]; 78237da2899SCharles.Forsyth h &= SymHash - 1; 78337da2899SCharles.Forsyth for(sl := syms[h]; sl != nil; sl = tl sl){ 78437da2899SCharles.Forsyth s := hd sl; 78537da2899SCharles.Forsyth if(sbl == s.path) 78637da2899SCharles.Forsyth return (s, ""); 78737da2899SCharles.Forsyth } 78837da2899SCharles.Forsyth (sy, err) := loadsyms(sbl); 78937da2899SCharles.Forsyth if(err != "") 79037da2899SCharles.Forsyth return (nil, err); 79137da2899SCharles.Forsyth syms[h] = sy :: syms[h]; 79237da2899SCharles.Forsyth return (sy, ""); 79337da2899SCharles.Forsyth} 79437da2899SCharles.Forsyth 79537da2899SCharles.ForsythModule.addsym(m: self ref Module, sym: ref Sym) 79637da2899SCharles.Forsyth{ 79737da2899SCharles.Forsyth m.sym = sym; 79837da2899SCharles.Forsyth} 79937da2899SCharles.Forsyth 80037da2899SCharles.ForsythModule.sbl(m: self ref Module): string 80137da2899SCharles.Forsyth{ 80237da2899SCharles.Forsyth if(m.sym != nil) 80337da2899SCharles.Forsyth return m.sym.path; 80437da2899SCharles.Forsyth return ""; 80537da2899SCharles.Forsyth} 80637da2899SCharles.Forsyth 80737da2899SCharles.ForsythModule.dis(m: self ref Module): string 80837da2899SCharles.Forsyth{ 80937da2899SCharles.Forsyth return m.path; 81037da2899SCharles.Forsyth} 81137da2899SCharles.Forsyth 81237da2899SCharles.Forsythfindsbl(dis: string): string 81337da2899SCharles.Forsyth{ 81437da2899SCharles.Forsyth n := len dis; 81537da2899SCharles.Forsyth if(n <= 4 || dis[n-4: n] != ".dis") 81637da2899SCharles.Forsyth dis += ".dis"; 81737da2899SCharles.Forsyth if(dism == nil){ 81837da2899SCharles.Forsyth dism = load Dis Dis->PATH; 81937da2899SCharles.Forsyth if(dism != nil) 82037da2899SCharles.Forsyth dism->init(); 82137da2899SCharles.Forsyth } 82237da2899SCharles.Forsyth if(dism != nil && (b := dism->src(dis)) != nil){ 82337da2899SCharles.Forsyth n = len b; 82437da2899SCharles.Forsyth if(n > 2 && b[n-2: n] == ".b"){ 82537da2899SCharles.Forsyth sbl := b[0: n-2] + ".sbl"; 82637da2899SCharles.Forsyth if(sys->open(sbl, Sys->OREAD) != nil) 82737da2899SCharles.Forsyth return sbl; 82837da2899SCharles.Forsyth } 82937da2899SCharles.Forsyth } 83037da2899SCharles.Forsyth return nil; 83137da2899SCharles.Forsyth} 83237da2899SCharles.Forsyth 83337da2899SCharles.ForsythModule.stdsym(m: self ref Module) 83437da2899SCharles.Forsyth{ 83537da2899SCharles.Forsyth if(m.sym != nil) 83637da2899SCharles.Forsyth return; 83737da2899SCharles.Forsyth if((sbl := findsbl(m.path)) != nil){ 83837da2899SCharles.Forsyth (m.sym, nil) = sym(sbl); 83937da2899SCharles.Forsyth return; 84037da2899SCharles.Forsyth } 84137da2899SCharles.Forsyth sbl = m.path; 84237da2899SCharles.Forsyth n := len sbl; 84337da2899SCharles.Forsyth if(n > 4 && sbl[n-4:n] == ".dis") 84437da2899SCharles.Forsyth sbl = sbl[:n-4]+".sbl"; 84537da2899SCharles.Forsyth else 84637da2899SCharles.Forsyth sbl = sbl+".sbl"; 84737da2899SCharles.Forsyth path := sbl; 84837da2899SCharles.Forsyth fd := sys->open(sbl, sys->OREAD); 84937da2899SCharles.Forsyth for(i := 0; fd == nil && i < len sblpath; i++){ 85037da2899SCharles.Forsyth (dis, src) := sblpath[i]; 85137da2899SCharles.Forsyth nd := len dis; 85237da2899SCharles.Forsyth if(len sbl > nd && sbl[:nd] == dis){ 85337da2899SCharles.Forsyth path = src + sbl[nd:]; 85437da2899SCharles.Forsyth fd = sys->open(path, sys->OREAD); 85537da2899SCharles.Forsyth } 85637da2899SCharles.Forsyth } 85737da2899SCharles.Forsyth if(fd == nil) 85837da2899SCharles.Forsyth return; 85937da2899SCharles.Forsyth (m.sym, nil) = sym(path); 86037da2899SCharles.Forsyth} 86137da2899SCharles.Forsyth 86237da2899SCharles.Forsythmkmod(data, code, comp: int, dis: string): ref Module 86337da2899SCharles.Forsyth{ 86437da2899SCharles.Forsyth h := 0; 86537da2899SCharles.Forsyth for(i := 0; i < len dis; i++) 86637da2899SCharles.Forsyth h = (h << 1) + dis[i]; 86737da2899SCharles.Forsyth h &= ModHash - 1; 86837da2899SCharles.Forsyth sym : ref Sym; 86937da2899SCharles.Forsyth for(ml := mods[h]; ml != nil; ml = tl ml){ 87037da2899SCharles.Forsyth m := hd ml; 87137da2899SCharles.Forsyth if(m.path == dis && m.code == code && m.comp == comp){ 87237da2899SCharles.Forsyth sym = m.sym; 87337da2899SCharles.Forsyth if(m.data == data) 87437da2899SCharles.Forsyth return m; 87537da2899SCharles.Forsyth } 87637da2899SCharles.Forsyth } 87737da2899SCharles.Forsyth m := ref Module(dis, code, data, comp, sym); 87837da2899SCharles.Forsyth mods[h] = m :: mods[h]; 87937da2899SCharles.Forsyth return m; 88037da2899SCharles.Forsyth} 88137da2899SCharles.Forsyth 88237da2899SCharles.Forsythpdata(p: ref Prog, a: int, fmt: string): (string, string) 88337da2899SCharles.Forsyth{ 88437da2899SCharles.Forsyth b := array of byte sprint("0x%ux.%s1", a, fmt); 88537da2899SCharles.Forsyth if(sys->write(p.heap, b, len b) != len b) 88637da2899SCharles.Forsyth return ("", sprint("can't write heap: %r")); 88737da2899SCharles.Forsyth 88837da2899SCharles.Forsyth buf := array[64] of byte; 88937da2899SCharles.Forsyth sys->seek(p.heap, big 0, 0); 89037da2899SCharles.Forsyth n := sys->read(p.heap, buf, len buf); 89137da2899SCharles.Forsyth if(n <= 1) 89237da2899SCharles.Forsyth return ("", sprint("can't read heap: %r")); 89337da2899SCharles.Forsyth return (string buf[:n-1], ""); 89437da2899SCharles.Forsyth} 89537da2899SCharles.Forsyth 89637da2899SCharles.Forsythpstring0(p: ref Prog, a: int, blen: int): (int, string, string) 89737da2899SCharles.Forsyth{ 89837da2899SCharles.Forsyth b := array of byte sprint("0x%ux.C1", a); 89937da2899SCharles.Forsyth if(sys->write(p.heap, b, len b) != len b) 90037da2899SCharles.Forsyth return (-1, "", sprint("can't write heap: %r")); 90137da2899SCharles.Forsyth 90237da2899SCharles.Forsyth buf := array[blen] of byte; 90337da2899SCharles.Forsyth sys->seek(p.heap, big 0, 0); 90437da2899SCharles.Forsyth n := sys->read(p.heap, buf, len buf-1); 90537da2899SCharles.Forsyth if(n <= 1) 90637da2899SCharles.Forsyth return (-1, "", sprint("can't read heap: %r")); 90737da2899SCharles.Forsyth buf[n] = byte 0; 90837da2899SCharles.Forsyth m := strchr(buf, 0, '.'); 90937da2899SCharles.Forsyth if(buf[m++] != byte '.') 91037da2899SCharles.Forsyth m = 0; 91137da2899SCharles.Forsyth return (int string buf[0:m], string buf[m:n], ""); 91237da2899SCharles.Forsyth} 91337da2899SCharles.Forsyth 91437da2899SCharles.Forsythpstring(p: ref Prog, a: int): (int, string, string) 91537da2899SCharles.Forsyth{ 91637da2899SCharles.Forsyth m, n: int; 91737da2899SCharles.Forsyth s, err: string; 91837da2899SCharles.Forsyth 91937da2899SCharles.Forsyth m = 64; 92037da2899SCharles.Forsyth for(;;){ 92137da2899SCharles.Forsyth (n, s, err) = pstring0(p, a, m); 92237da2899SCharles.Forsyth if(err != "" || n <= len s) 92337da2899SCharles.Forsyth break; 924*82697248SCharles.Forsyth # guard against broken devprog 925*82697248SCharles.Forsyth if(m >= 3 * n) 926*82697248SCharles.Forsyth return (-1, nil, "bad string"); 92737da2899SCharles.Forsyth m *= 2; 92837da2899SCharles.Forsyth } 92937da2899SCharles.Forsyth return (n, s, err); 93037da2899SCharles.Forsyth} 93137da2899SCharles.Forsyth 93237da2899SCharles.ForsythProg.status(p: self ref Prog): (int, string, string, string) 93337da2899SCharles.Forsyth{ 93437da2899SCharles.Forsyth fd := sys->open(sprint("/prog/%d/status", p.id), sys->OREAD); 93537da2899SCharles.Forsyth if(fd == nil) 93637da2899SCharles.Forsyth return (-1, "", sprint("can't open status file: %r"), ""); 93737da2899SCharles.Forsyth buf := array[256] of byte; 93837da2899SCharles.Forsyth n := sys->read(fd, buf, len buf); 93937da2899SCharles.Forsyth if(n <= 0) 94037da2899SCharles.Forsyth return (-1, "", sprint("can't read status file: %r"), ""); 94137da2899SCharles.Forsyth (ni, info) := sys->tokenize(string buf[:n], " \t"); 94237da2899SCharles.Forsyth if(ni != 6 && ni != 7) 94337da2899SCharles.Forsyth return (-1, "", "can't parse status file", ""); 94437da2899SCharles.Forsyth info = tl info; 94537da2899SCharles.Forsyth if(ni == 6) 94637da2899SCharles.Forsyth return (int hd info, hd tl info, hd tl tl info, hd tl tl tl tl info); 94737da2899SCharles.Forsyth return (int hd info, hd tl info, hd tl tl tl info, hd tl tl tl tl tl info); 94837da2899SCharles.Forsyth} 94937da2899SCharles.Forsyth 95037da2899SCharles.Forsythloadsyms(sbl: string): (ref Sym, string) 95137da2899SCharles.Forsyth{ 95237da2899SCharles.Forsyth fd := sys->open(sbl, sys->OREAD); 95337da2899SCharles.Forsyth if(fd == nil) 95437da2899SCharles.Forsyth return (nil, sprint("Can't open symbol file '%s': %r", sbl)); 95537da2899SCharles.Forsyth 95637da2899SCharles.Forsyth (ok, dir) := sys->fstat(fd); 95737da2899SCharles.Forsyth if(ok < 0) 95837da2899SCharles.Forsyth return (nil, sprint("Can't read symbol file '%s': %r", sbl)); 95937da2899SCharles.Forsyth n := int dir.length; 96037da2899SCharles.Forsyth buf := array[n+1] of byte; 96137da2899SCharles.Forsyth if(sys->read(fd, buf, n) != n) 96237da2899SCharles.Forsyth return (nil, sprint("Can't read symbol file '%s': %r", sbl)); 96337da2899SCharles.Forsyth fd = nil; 96437da2899SCharles.Forsyth buf[n] = byte 0; 96537da2899SCharles.Forsyth 96637da2899SCharles.Forsyth s := ref Sym; 96737da2899SCharles.Forsyth s.path = sbl; 96837da2899SCharles.Forsyth 96937da2899SCharles.Forsyth n = strchr(buf, 0, '\n'); 97037da2899SCharles.Forsyth vers := 0; 97137da2899SCharles.Forsyth if(string buf[:n] == "limbo .sbl 1.") 97237da2899SCharles.Forsyth vers = 10; 97337da2899SCharles.Forsyth else if(string buf[:n] == "limbo .sbl 1.1") 97437da2899SCharles.Forsyth vers = 11; 97537da2899SCharles.Forsyth else if(string buf[:n] == "limbo .sbl 2.0") 97637da2899SCharles.Forsyth vers = 20; 97737da2899SCharles.Forsyth else if(string buf[:n] == "limbo .sbl 2.1") 97837da2899SCharles.Forsyth vers = 21; 97937da2899SCharles.Forsyth else 98037da2899SCharles.Forsyth return (nil, "Symbol file "+sbl+" out of date"); 98137da2899SCharles.Forsyth o := n += 1; 98237da2899SCharles.Forsyth n = strchr(buf, o, '\n'); 98337da2899SCharles.Forsyth if(buf[n] != byte '\n') 98437da2899SCharles.Forsyth return (nil, "Corrupted symbol file "+sbl); 98537da2899SCharles.Forsyth s.name = string buf[o:n++]; 98637da2899SCharles.Forsyth ss := ref SrcState(nil, 0, 0, vers); 98737da2899SCharles.Forsyth err : string; 98837da2899SCharles.Forsyth if(n >= 0){ 98937da2899SCharles.Forsyth err = "file"; 99037da2899SCharles.Forsyth n = debugfiles(ss, buf, n); 99137da2899SCharles.Forsyth } 99237da2899SCharles.Forsyth if(n >= 0){ 99337da2899SCharles.Forsyth err = "pc"; 99437da2899SCharles.Forsyth n = debugpc(ss, s, buf, n); 99537da2899SCharles.Forsyth } 99637da2899SCharles.Forsyth if(n >= 0){ 99737da2899SCharles.Forsyth err = "types"; 99837da2899SCharles.Forsyth n = debugtys(ss, s, buf, n); 99937da2899SCharles.Forsyth } 100037da2899SCharles.Forsyth if(n >= 0){ 100137da2899SCharles.Forsyth err = "fn"; 100237da2899SCharles.Forsyth n = debugfns(ss, s, buf, n); 100337da2899SCharles.Forsyth } 100437da2899SCharles.Forsyth vs: array of ref Id; 100537da2899SCharles.Forsyth if(n >= 0){ 100637da2899SCharles.Forsyth err = "global"; 100737da2899SCharles.Forsyth (vs, n) = debugid(ss, buf, n); 100837da2899SCharles.Forsyth } 100937da2899SCharles.Forsyth if(n < 0) 101037da2899SCharles.Forsyth return (nil, "Corrupted "+err+" symbol table in "+sbl); 101137da2899SCharles.Forsyth s.vars = vs; 101237da2899SCharles.Forsyth return (s, ""); 101337da2899SCharles.Forsyth} 101437da2899SCharles.Forsyth 101537da2899SCharles.Forsyth# 101637da2899SCharles.Forsyth# parse a source location 101737da2899SCharles.Forsyth# format[file:][line.]pos,[file:][line.]pos' ' 101837da2899SCharles.Forsyth# 101937da2899SCharles.Forsythdebugsrc(ss: ref SrcState, buf: array of byte, p: int): (ref Src, int) 102037da2899SCharles.Forsyth{ 102137da2899SCharles.Forsyth n: int; 102237da2899SCharles.Forsyth src: ref Src; 102337da2899SCharles.Forsyth 102437da2899SCharles.Forsyth (n, p) = strtoi(buf, p); 102537da2899SCharles.Forsyth if(buf[p] == byte ':'){ 102637da2899SCharles.Forsyth ss.lastf = n; 102737da2899SCharles.Forsyth (n, p) = strtoi(buf, p + 1); 102837da2899SCharles.Forsyth } 102937da2899SCharles.Forsyth if(buf[p] == byte '.'){ 103037da2899SCharles.Forsyth ss.lastl = n; 103137da2899SCharles.Forsyth (n, p) = strtoi(buf, p + 1); 103237da2899SCharles.Forsyth } 103337da2899SCharles.Forsyth if(buf[p++] != byte ',' || ss.lastf >= len ss.files || ss.lastf < 0) 103437da2899SCharles.Forsyth return (nil, -1); 103537da2899SCharles.Forsyth src = ref Src; 103637da2899SCharles.Forsyth src.start.file = ss.files[ss.lastf]; 103737da2899SCharles.Forsyth src.start.line = ss.lastl; 103837da2899SCharles.Forsyth src.start.pos = n; 103937da2899SCharles.Forsyth 104037da2899SCharles.Forsyth (n, p) = strtoi(buf, p); 104137da2899SCharles.Forsyth if(buf[p] == byte ':'){ 104237da2899SCharles.Forsyth ss.lastf = n; 104337da2899SCharles.Forsyth (n, p) = strtoi(buf, p+1); 104437da2899SCharles.Forsyth } 104537da2899SCharles.Forsyth if(buf[p] == byte '.'){ 104637da2899SCharles.Forsyth ss.lastl = n; 104737da2899SCharles.Forsyth (n, p) = strtoi(buf, p + 1); 104837da2899SCharles.Forsyth } 104937da2899SCharles.Forsyth if(buf[p++] != byte ' ' || ss.lastf >= len ss.files || ss.lastf < 0) 105037da2899SCharles.Forsyth return (nil, -1); 105137da2899SCharles.Forsyth src.stop.file = ss.files[ss.lastf]; 105237da2899SCharles.Forsyth src.stop.line = ss.lastl; 105337da2899SCharles.Forsyth src.stop.pos = n; 105437da2899SCharles.Forsyth return (src, p); 105537da2899SCharles.Forsyth} 105637da2899SCharles.Forsyth 105737da2899SCharles.Forsyth# 105837da2899SCharles.Forsyth# parse the file table 105937da2899SCharles.Forsyth# item format: file: string 106037da2899SCharles.Forsyth# 106137da2899SCharles.Forsythdebugfiles(ss: ref SrcState, buf: array of byte, p: int): int 106237da2899SCharles.Forsyth{ 106337da2899SCharles.Forsyth n, q: int; 106437da2899SCharles.Forsyth 106537da2899SCharles.Forsyth (n, p) = strtoi(buf, p); 106637da2899SCharles.Forsyth if(buf[p++] != byte '\n') 106737da2899SCharles.Forsyth return -1; 106837da2899SCharles.Forsyth ss.files = array[n] of string; 106937da2899SCharles.Forsyth for(i := 0; i < n; i++){ 107037da2899SCharles.Forsyth q = strchr(buf, p, '\n'); 107137da2899SCharles.Forsyth ss.files[i] = string buf[p:q]; 107237da2899SCharles.Forsyth p = q + 1; 107337da2899SCharles.Forsyth } 107437da2899SCharles.Forsyth return p; 107537da2899SCharles.Forsyth} 107637da2899SCharles.Forsyth 107737da2899SCharles.Forsyth# 107837da2899SCharles.Forsyth# parse the pc to source table 107937da2899SCharles.Forsyth# item format: Source stmt 108037da2899SCharles.Forsyth# 108137da2899SCharles.Forsythdebugpc(ss: ref SrcState, s: ref Sym, buf: array of byte, p: int): int 108237da2899SCharles.Forsyth{ 108337da2899SCharles.Forsyth ns: int; 108437da2899SCharles.Forsyth 108537da2899SCharles.Forsyth (ns, p) = strtoi(buf, p); 108637da2899SCharles.Forsyth if(buf[p++] != byte '\n') 108737da2899SCharles.Forsyth return -1; 108837da2899SCharles.Forsyth s.src = array[ns] of ref Src; 108937da2899SCharles.Forsyth s.srcstmt = array[ns] of int; 109037da2899SCharles.Forsyth for(i := 0; i < ns; i++){ 109137da2899SCharles.Forsyth (s.src[i], p) = debugsrc(ss, buf, p); 109237da2899SCharles.Forsyth if(p < 0) 109337da2899SCharles.Forsyth return -1; 109437da2899SCharles.Forsyth (s.srcstmt[i], p) = strtoi(buf, p); 109537da2899SCharles.Forsyth if(buf[p++] != byte '\n') 109637da2899SCharles.Forsyth return -1; 109737da2899SCharles.Forsyth } 109837da2899SCharles.Forsyth return p; 109937da2899SCharles.Forsyth} 110037da2899SCharles.Forsyth 110137da2899SCharles.Forsyth# 110237da2899SCharles.Forsyth# parse the type table 110337da2899SCharles.Forsyth# format: linear list of types 110437da2899SCharles.Forsyth# 110537da2899SCharles.Forsythdebugtys(ss: ref SrcState, s: ref Sym, buf: array of byte, p: int): int 110637da2899SCharles.Forsyth{ 110737da2899SCharles.Forsyth na: int; 110837da2899SCharles.Forsyth 110937da2899SCharles.Forsyth (na, p) = strtoi(buf, p); 111037da2899SCharles.Forsyth if(buf[p++] != byte '\n') 111137da2899SCharles.Forsyth return -1; 111237da2899SCharles.Forsyth s.adts = array[na] of ref Type; 111337da2899SCharles.Forsyth adts := s.adts; 111437da2899SCharles.Forsyth for(i := 0; i < na; i++){ 111537da2899SCharles.Forsyth if(ss.vers < 20) 111637da2899SCharles.Forsyth (adts[i], p) = debugadt(ss, buf, p); 111737da2899SCharles.Forsyth else 111837da2899SCharles.Forsyth (adts[i], p) = debugtype(ss, buf, p); 111937da2899SCharles.Forsyth if(p < 0) 112037da2899SCharles.Forsyth return -1; 112137da2899SCharles.Forsyth } 112237da2899SCharles.Forsyth return p; 112337da2899SCharles.Forsyth} 112437da2899SCharles.Forsyth 112537da2899SCharles.Forsyth# 112637da2899SCharles.Forsyth# parse the function table 112737da2899SCharles.Forsyth# format: pc:name:argids localids rettype 112837da2899SCharles.Forsyth# 112937da2899SCharles.Forsythdebugfns(ss: ref SrcState, s: ref Sym, buf: array of byte, p: int): int 113037da2899SCharles.Forsyth{ 113137da2899SCharles.Forsyth t: ref Type; 113237da2899SCharles.Forsyth args, locals: array of ref Id; 113337da2899SCharles.Forsyth nf, pc, q: int; 113437da2899SCharles.Forsyth 113537da2899SCharles.Forsyth (nf, p) = strtoi(buf, p); 113637da2899SCharles.Forsyth if(buf[p++] != byte '\n') 113737da2899SCharles.Forsyth return -1; 113837da2899SCharles.Forsyth s.fns = array[nf] of ref Id; 113937da2899SCharles.Forsyth fns := s.fns; 114037da2899SCharles.Forsyth for(i := 0; i < nf; i++){ 114137da2899SCharles.Forsyth (pc, p) = strtoi(buf, p); 114237da2899SCharles.Forsyth if(buf[p++] != byte ':') 114337da2899SCharles.Forsyth return -2; 114437da2899SCharles.Forsyth q = strchr(buf, p, '\n'); 114537da2899SCharles.Forsyth if(buf[q] != byte '\n') 114637da2899SCharles.Forsyth return -3; 114737da2899SCharles.Forsyth name := string buf[p:q]; 114837da2899SCharles.Forsyth (args, p) = debugid(ss, buf, q + 1); 114937da2899SCharles.Forsyth if(p == -1) 115037da2899SCharles.Forsyth return -4; 115137da2899SCharles.Forsyth (locals, p) = debugid(ss, buf, p); 115237da2899SCharles.Forsyth if(p == -1) 115337da2899SCharles.Forsyth return -5; 115437da2899SCharles.Forsyth (t, p) = debugtype(ss, buf, p); 115537da2899SCharles.Forsyth if(p == -1) 115637da2899SCharles.Forsyth return -6; 115737da2899SCharles.Forsyth nk := 1 + (len args != 0) + (len locals != 0); 115837da2899SCharles.Forsyth kids := array[nk] of ref Id; 115937da2899SCharles.Forsyth nk = 0; 116037da2899SCharles.Forsyth if(len locals != 0) 116137da2899SCharles.Forsyth kids[nk++] = ref Id(nil, "locals", 0, 0, ref Type(nil, Tlocal, 0, nil, nil, locals, nil)); 116237da2899SCharles.Forsyth if(len args != 0) 116337da2899SCharles.Forsyth kids[nk++] = ref Id(nil, "args", 0, 0, ref Type(nil, Targ, 0, nil, nil, args, nil)); 116437da2899SCharles.Forsyth kids[nk++] = ref Id(nil, "module", 0, 0, ref Type(nil, Tglobal, 0, nil, nil, nil, nil)); 116537da2899SCharles.Forsyth args = nil; 116637da2899SCharles.Forsyth locals = nil; 116737da2899SCharles.Forsyth fns[i] = ref Id(nil, name, pc, 0, ref Type(nil, Tfn, 0, name, t, kids, nil)); 116837da2899SCharles.Forsyth } 116937da2899SCharles.Forsyth for(i = 1; i < nf; i++) 117037da2899SCharles.Forsyth fns[i-1].stoppc = fns[i].offset; 117137da2899SCharles.Forsyth fns[i-1].stoppc = len s.src; 117237da2899SCharles.Forsyth return p; 117337da2899SCharles.Forsyth} 117437da2899SCharles.Forsyth 117537da2899SCharles.Forsyth# 117637da2899SCharles.Forsyth# parse a list of ids 117737da2899SCharles.Forsyth# format: offset ':' name ':' src type '\n' 117837da2899SCharles.Forsyth# 117937da2899SCharles.Forsythdebugid(ss: ref SrcState, buf: array of byte, p: int): (array of ref Id, int) 118037da2899SCharles.Forsyth{ 118137da2899SCharles.Forsyth t: ref Type; 118237da2899SCharles.Forsyth off, nd, q, qq, tq: int; 118337da2899SCharles.Forsyth src: ref Src; 118437da2899SCharles.Forsyth 118537da2899SCharles.Forsyth (nd, p) = strtoi(buf, p); 118637da2899SCharles.Forsyth if(buf[p++] != byte '\n') 118737da2899SCharles.Forsyth return (nil, -1); 118837da2899SCharles.Forsyth d := array[nd] of ref Id; 118937da2899SCharles.Forsyth for(i := 0; i < nd; i++){ 119037da2899SCharles.Forsyth (off, q) = strtoi(buf, p); 119137da2899SCharles.Forsyth if(buf[q++] != byte ':') 119237da2899SCharles.Forsyth return (nil, -1); 119337da2899SCharles.Forsyth qq = strchr(buf, q, ':'); 119437da2899SCharles.Forsyth if(buf[qq] != byte ':') 119537da2899SCharles.Forsyth return (nil, -1); 119637da2899SCharles.Forsyth tq = qq + 1; 119737da2899SCharles.Forsyth if(ss.vers > 10){ 119837da2899SCharles.Forsyth (src, tq) = debugsrc(ss, buf, tq); 119937da2899SCharles.Forsyth if(tq < 0) 120037da2899SCharles.Forsyth return (nil, -1); 120137da2899SCharles.Forsyth } 120237da2899SCharles.Forsyth (t, p) = debugtype(ss, buf, tq); 120337da2899SCharles.Forsyth if(p == -1 || buf[p++] != byte '\n') 120437da2899SCharles.Forsyth return (nil, -1); 120537da2899SCharles.Forsyth d[i] = ref Id(src, string buf[q:qq], off, 0, t); 120637da2899SCharles.Forsyth } 120737da2899SCharles.Forsyth return (d, p); 120837da2899SCharles.Forsyth} 120937da2899SCharles.Forsyth 121037da2899SCharles.Forsythidlist(a: array of ref Id): list of ref Id 121137da2899SCharles.Forsyth{ 121237da2899SCharles.Forsyth n := len a; 121337da2899SCharles.Forsyth ids : list of ref Id = nil; 121437da2899SCharles.Forsyth while(n-- > 0) 121537da2899SCharles.Forsyth ids = a[n] :: ids; 121637da2899SCharles.Forsyth return ids; 121737da2899SCharles.Forsyth} 121837da2899SCharles.Forsyth 121937da2899SCharles.Forsyth# 122037da2899SCharles.Forsyth# parse a type description 122137da2899SCharles.Forsyth# 122237da2899SCharles.Forsythdebugtype(ss: ref SrcState, buf: array of byte, p: int): (ref Type, int) 122337da2899SCharles.Forsyth{ 122437da2899SCharles.Forsyth t: ref Type; 122537da2899SCharles.Forsyth d: array of ref Id; 122637da2899SCharles.Forsyth q, k: int; 122737da2899SCharles.Forsyth src: ref Src; 122837da2899SCharles.Forsyth 122937da2899SCharles.Forsyth size := 0; 123037da2899SCharles.Forsyth case int buf[p++]{ 123137da2899SCharles.Forsyth '@' => 123237da2899SCharles.Forsyth k = Tid; 123337da2899SCharles.Forsyth 'A' => 123437da2899SCharles.Forsyth k = Tarray; 123537da2899SCharles.Forsyth size = IBY2WD; 123637da2899SCharles.Forsyth 'B' => 123737da2899SCharles.Forsyth return (tbig, p); 123837da2899SCharles.Forsyth 'C' => k = Tchan; 123937da2899SCharles.Forsyth size = IBY2WD; 124037da2899SCharles.Forsyth 'L' => 124137da2899SCharles.Forsyth k = Tlist; 124237da2899SCharles.Forsyth size = IBY2WD; 124337da2899SCharles.Forsyth 'N' => 124437da2899SCharles.Forsyth return (tnil, p); 124537da2899SCharles.Forsyth 'R' => 124637da2899SCharles.Forsyth k = Tref; 124737da2899SCharles.Forsyth size = IBY2WD; 124837da2899SCharles.Forsyth 'a' => 124937da2899SCharles.Forsyth k = Tadt; 125037da2899SCharles.Forsyth if(ss.vers < 20) 125137da2899SCharles.Forsyth size = -1; 125237da2899SCharles.Forsyth 'b' => 125337da2899SCharles.Forsyth return (tbyte, p); 125437da2899SCharles.Forsyth 'f' => 125537da2899SCharles.Forsyth return (treal, p); 125637da2899SCharles.Forsyth 'i' => 125737da2899SCharles.Forsyth return (tint, p); 125837da2899SCharles.Forsyth 'm' => 125937da2899SCharles.Forsyth k = Tmodule; 126037da2899SCharles.Forsyth size = IBY2WD; 126137da2899SCharles.Forsyth 'n' => 126237da2899SCharles.Forsyth return (tnone, p); 126337da2899SCharles.Forsyth 'p' => 126437da2899SCharles.Forsyth k = Tadtpick; 126537da2899SCharles.Forsyth 's' => 126637da2899SCharles.Forsyth return (tstring, p); 126737da2899SCharles.Forsyth 't' => 126837da2899SCharles.Forsyth k = Ttuple; 126937da2899SCharles.Forsyth size = -1; 127037da2899SCharles.Forsyth 'F' => 127137da2899SCharles.Forsyth k = Tfn; 127237da2899SCharles.Forsyth size = IBY2WD; 127337da2899SCharles.Forsyth 'P' => 127437da2899SCharles.Forsyth return (tpoly, p); 127537da2899SCharles.Forsyth * => 127637da2899SCharles.Forsyth k = Terror; 127737da2899SCharles.Forsyth } 127837da2899SCharles.Forsyth 127937da2899SCharles.Forsyth if(size == -1){ 128037da2899SCharles.Forsyth q = strchr(buf, p, '.'); 128137da2899SCharles.Forsyth if(buf[q] == byte '.'){ 128237da2899SCharles.Forsyth size = int string buf[p:q]; 128337da2899SCharles.Forsyth p = q+1; 128437da2899SCharles.Forsyth } 128537da2899SCharles.Forsyth } 128637da2899SCharles.Forsyth 128737da2899SCharles.Forsyth case k{ 128837da2899SCharles.Forsyth Tid => 128937da2899SCharles.Forsyth q = strchr(buf, p, '\n'); 129037da2899SCharles.Forsyth if(buf[q] != byte '\n') 129137da2899SCharles.Forsyth return (nil, -1); 129237da2899SCharles.Forsyth t = ref Type(nil, Tid, -1, string buf[p:q], nil, nil, nil); 129337da2899SCharles.Forsyth p = q + 1; 129437da2899SCharles.Forsyth Tadt => 129537da2899SCharles.Forsyth if(ss.vers < 20){ 129637da2899SCharles.Forsyth q = strchr(buf, p, '\n'); 129737da2899SCharles.Forsyth if(buf[q] != byte '\n') 129837da2899SCharles.Forsyth return (nil, -1); 129937da2899SCharles.Forsyth t = ref Type(nil, Tid, size, string buf[p:q], nil, nil, nil); 130037da2899SCharles.Forsyth p = q + 1; 130137da2899SCharles.Forsyth }else 130237da2899SCharles.Forsyth (t, p) = debugadt(ss, buf, p); 130337da2899SCharles.Forsyth Tadtpick => 130437da2899SCharles.Forsyth (t, p) = debugadt(ss, buf, p); 130537da2899SCharles.Forsyth t.kind = Tadtpick; 130637da2899SCharles.Forsyth (t.tags, p) = debugtag(ss, buf, p); 130737da2899SCharles.Forsyth Tmodule => 130837da2899SCharles.Forsyth q = strchr(buf, p, '\n'); 130937da2899SCharles.Forsyth if(buf[q] != byte '\n') 131037da2899SCharles.Forsyth return (nil, -1); 131137da2899SCharles.Forsyth t = ref Type(nil, k, size, string buf[p:q], nil, nil, nil); 131237da2899SCharles.Forsyth p = q + 1; 131337da2899SCharles.Forsyth if(ss.vers > 10){ 131437da2899SCharles.Forsyth (src, p) = debugsrc(ss, buf, p); 131537da2899SCharles.Forsyth t.src = src; 131637da2899SCharles.Forsyth } 131737da2899SCharles.Forsyth if(ss.vers > 20) 131837da2899SCharles.Forsyth (t.ids, p) = debugid(ss, buf, p); 131937da2899SCharles.Forsyth Tref or Tarray or Tlist or Tchan => # ref, array, list, chan 132037da2899SCharles.Forsyth (t, p) = debugtype(ss, buf, p); 132137da2899SCharles.Forsyth t = ref Type(nil, k, size, "", t, nil, nil); 132237da2899SCharles.Forsyth 132337da2899SCharles.Forsyth Ttuple => # tuple 132437da2899SCharles.Forsyth (d, p) = debugid(ss, buf, p); 132537da2899SCharles.Forsyth t = ref Type(nil, k, size, "", nil, d, nil); 132637da2899SCharles.Forsyth 132737da2899SCharles.Forsyth Tfn => # fn 132837da2899SCharles.Forsyth (d, p) = debugid(ss, buf, p); 132937da2899SCharles.Forsyth (t, p) = debugtype(ss, buf, p); 133037da2899SCharles.Forsyth t = ref Type(nil, k, size, "", t, d, nil); 133137da2899SCharles.Forsyth 133237da2899SCharles.Forsyth * => 133337da2899SCharles.Forsyth p = -1; 133437da2899SCharles.Forsyth } 133537da2899SCharles.Forsyth return (t, p); 133637da2899SCharles.Forsyth} 133737da2899SCharles.Forsyth 133837da2899SCharles.Forsyth# 133937da2899SCharles.Forsyth# parse an adt type spec 134037da2899SCharles.Forsyth# format: name ' ' src size '\n' ids 134137da2899SCharles.Forsyth# 134237da2899SCharles.Forsythdebugadt(ss: ref SrcState, buf: array of byte, p: int): (ref Type, int) 134337da2899SCharles.Forsyth{ 134437da2899SCharles.Forsyth src: ref Src; 134537da2899SCharles.Forsyth 134637da2899SCharles.Forsyth q := strchr(buf, p, ' '); 134737da2899SCharles.Forsyth if(buf[q] != byte ' ') 134837da2899SCharles.Forsyth return (nil, -1); 134937da2899SCharles.Forsyth sq := q + 1; 135037da2899SCharles.Forsyth if(ss.vers > 10){ 135137da2899SCharles.Forsyth (src, sq) = debugsrc(ss, buf, sq); 135237da2899SCharles.Forsyth if(sq < 0) 135337da2899SCharles.Forsyth return (nil, -1); 135437da2899SCharles.Forsyth } 135537da2899SCharles.Forsyth qq := strchr(buf, sq, '\n'); 135637da2899SCharles.Forsyth if(buf[qq] != byte '\n') 135737da2899SCharles.Forsyth return (nil, -1); 135837da2899SCharles.Forsyth (d, pp) := debugid(ss, buf, qq + 1); 135937da2899SCharles.Forsyth if(pp == -1) 136037da2899SCharles.Forsyth return (nil, -1); 136137da2899SCharles.Forsyth t := ref Type(src, Tadt, int string buf[sq:qq], string buf[p:q], nil, d, nil); 136237da2899SCharles.Forsyth return (t, pp); 136337da2899SCharles.Forsyth} 136437da2899SCharles.Forsyth 136537da2899SCharles.Forsyth# 136637da2899SCharles.Forsyth# parse a list of tags 136737da2899SCharles.Forsyth# format: 136837da2899SCharles.Forsyth# name ':' src size '\n' ids 136937da2899SCharles.Forsyth# or 137037da2899SCharles.Forsyth# name ':' src '\n' 137137da2899SCharles.Forsyth# 137237da2899SCharles.Forsythdebugtag(ss: ref SrcState, buf: array of byte, p: int): (array of ref Type, int) 137337da2899SCharles.Forsyth{ 137437da2899SCharles.Forsyth d: array of ref Id; 137537da2899SCharles.Forsyth ntg, q, pp, np: int; 137637da2899SCharles.Forsyth src: ref Src; 137737da2899SCharles.Forsyth 137837da2899SCharles.Forsyth (ntg, p) = strtoi(buf, p); 137937da2899SCharles.Forsyth if(buf[p++] != byte '\n') 138037da2899SCharles.Forsyth return (nil, -1); 138137da2899SCharles.Forsyth tg := array[ntg] of ref Type; 138237da2899SCharles.Forsyth for(i := 0; i < ntg; i++){ 138337da2899SCharles.Forsyth pp = strchr(buf, p, ':'); 138437da2899SCharles.Forsyth if(buf[pp] != byte ':') 138537da2899SCharles.Forsyth return (nil, -1); 138637da2899SCharles.Forsyth q = pp + 1; 138737da2899SCharles.Forsyth (src, q) = debugsrc(ss, buf, q); 138837da2899SCharles.Forsyth if(q < 0) 138937da2899SCharles.Forsyth return (nil, -1); 139037da2899SCharles.Forsyth if(buf[q] == byte '\n'){ 139137da2899SCharles.Forsyth np = q + 1; 139237da2899SCharles.Forsyth if(i <= 0) 139337da2899SCharles.Forsyth return (nil, -1); 139437da2899SCharles.Forsyth tg[i] = ref Type(src, Tadt, tg[i-1].size, string buf[p:pp], nil, tg[i-1].ids, nil); 139537da2899SCharles.Forsyth }else{ 139637da2899SCharles.Forsyth np = strchr(buf, q, '\n'); 139737da2899SCharles.Forsyth if(buf[np] != byte '\n') 139837da2899SCharles.Forsyth return (nil, -1); 139937da2899SCharles.Forsyth size := int string buf[q:np]; 140037da2899SCharles.Forsyth (d, np) = debugid(ss, buf, np+1); 140137da2899SCharles.Forsyth if(np == -1) 140237da2899SCharles.Forsyth return (nil, -1); 140337da2899SCharles.Forsyth tg[i] = ref Type(src, Tadt, size, string buf[p:pp], nil, d, nil); 140437da2899SCharles.Forsyth } 140537da2899SCharles.Forsyth p = np; 140637da2899SCharles.Forsyth } 140737da2899SCharles.Forsyth return (tg, p); 140837da2899SCharles.Forsyth} 140937da2899SCharles.Forsyth 141037da2899SCharles.Forsythstrchr(a: array of byte, p, c: int): int 141137da2899SCharles.Forsyth{ 141237da2899SCharles.Forsyth bc := byte c; 141337da2899SCharles.Forsyth while((b := a[p]) != byte 0 && b != bc) 141437da2899SCharles.Forsyth p++; 141537da2899SCharles.Forsyth return p; 141637da2899SCharles.Forsyth} 141737da2899SCharles.Forsyth 141837da2899SCharles.Forsythstrtoi(a: array of byte, start: int): (int, int) 141937da2899SCharles.Forsyth{ 142037da2899SCharles.Forsyth p := start; 142137da2899SCharles.Forsyth for(; c := int a[p]; p++){ 142237da2899SCharles.Forsyth case c{ 142337da2899SCharles.Forsyth ' ' or '\t' or '\n' or '\r' => 142437da2899SCharles.Forsyth continue; 142537da2899SCharles.Forsyth } 142637da2899SCharles.Forsyth break; 142737da2899SCharles.Forsyth } 142837da2899SCharles.Forsyth 142937da2899SCharles.Forsyth # sign 143037da2899SCharles.Forsyth neg := c == '-'; 143137da2899SCharles.Forsyth if(neg || c == '+') 143237da2899SCharles.Forsyth p++; 143337da2899SCharles.Forsyth 143437da2899SCharles.Forsyth # digits 143537da2899SCharles.Forsyth n := 0; 143637da2899SCharles.Forsyth nn := 0; 143737da2899SCharles.Forsyth ndig := 0; 143837da2899SCharles.Forsyth over := 0; 143937da2899SCharles.Forsyth for(; c = int a[p]; p++){ 144037da2899SCharles.Forsyth if(c < '0' || c > '9') 144137da2899SCharles.Forsyth break; 144237da2899SCharles.Forsyth ndig++; 144337da2899SCharles.Forsyth nn = n * 10 + (c - '0'); 144437da2899SCharles.Forsyth if(nn < n) 144537da2899SCharles.Forsyth over = 1; 144637da2899SCharles.Forsyth n = nn; 144737da2899SCharles.Forsyth } 144837da2899SCharles.Forsyth if(ndig == 0) 144937da2899SCharles.Forsyth return (0, start); 145037da2899SCharles.Forsyth if(neg) 145137da2899SCharles.Forsyth n = -n; 145237da2899SCharles.Forsyth if(over) 145337da2899SCharles.Forsyth if(neg) 145437da2899SCharles.Forsyth n = 2147483647; 145537da2899SCharles.Forsyth else 145637da2899SCharles.Forsyth n = int -2147483648; 145737da2899SCharles.Forsyth return (n, p); 145837da2899SCharles.Forsyth} 145937da2899SCharles.Forsyth 146037da2899SCharles.Forsythhex(a: array of byte): int 146137da2899SCharles.Forsyth{ 146237da2899SCharles.Forsyth n := 0; 146337da2899SCharles.Forsyth for(i := 0; i < len a; i++){ 146437da2899SCharles.Forsyth c := int a[i]; 146537da2899SCharles.Forsyth if(c >= '0' && c <= '9') 146637da2899SCharles.Forsyth c -= '0'; 146737da2899SCharles.Forsyth else 146837da2899SCharles.Forsyth c -= 'a' - 10; 146937da2899SCharles.Forsyth n = (n << 4) + (c & 15); 147037da2899SCharles.Forsyth } 147137da2899SCharles.Forsyth return n; 147237da2899SCharles.Forsyth} 147337da2899SCharles.Forsyth 147437da2899SCharles.Forsythpartition(n : int, max : int) : (int, int, int) 147537da2899SCharles.Forsyth{ 147637da2899SCharles.Forsyth p := n/max; 147737da2899SCharles.Forsyth if (n%max != 0) 147837da2899SCharles.Forsyth p++; 147937da2899SCharles.Forsyth if (p > max) 148037da2899SCharles.Forsyth p = max; 148137da2899SCharles.Forsyth q := n/p; 148237da2899SCharles.Forsyth r := n-p*q; 148337da2899SCharles.Forsyth return (p, q, r); 148437da2899SCharles.Forsyth} 148537da2899SCharles.Forsyth 148637da2899SCharles.Forsythbounds(s : string) : (int, int) 148737da2899SCharles.Forsyth{ 148837da2899SCharles.Forsyth lb := int s; 148937da2899SCharles.Forsyth for (i := 0; i < len s; i++) 149037da2899SCharles.Forsyth if (s[i] == '.') 149137da2899SCharles.Forsyth break; 149237da2899SCharles.Forsyth if (i+1 >= len s || s[i] != '.' || s[i+1] != '.') 149337da2899SCharles.Forsyth return (1, 0); 149437da2899SCharles.Forsyth ub := int s[i+2:]; 149537da2899SCharles.Forsyth return (lb, ub); 149637da2899SCharles.Forsyth} 1497