137da2899SCharles.Forsythimplement Stackv; 237da2899SCharles.Forsyth 337da2899SCharles.Forsythinclude "sys.m"; 437da2899SCharles.Forsyth sys: Sys; 537da2899SCharles.Forsythinclude "draw.m"; 637da2899SCharles.Forsythinclude "debug.m"; 737da2899SCharles.Forsyth debug: Debug; 837da2899SCharles.Forsyth Prog, Module, Exp: import debug; 937da2899SCharles.Forsyth Tadt, Tarray, Tbig, Tbyte, Treal, 1037da2899SCharles.Forsyth Tfn, Tint, Tlist, 1137da2899SCharles.Forsyth Tref, Tstring, Tslice: import Debug; 1237da2899SCharles.Forsythinclude "arg.m"; 1337da2899SCharles.Forsythinclude "bufio.m"; 1437da2899SCharles.Forsyth bufio: Bufio; 1537da2899SCharles.Forsyth Iobuf: import bufio; 1637da2899SCharles.Forsyth 1737da2899SCharles.Forsythstderr: ref Sys->FD; 1837da2899SCharles.Forsythstdout: ref Iobuf; 1966f5808bSforsyth 2066f5808bSforsythhasht := array[97] of (int, array of int); 2137da2899SCharles.Forsyth 2237da2899SCharles.ForsythStackv: module { 2337da2899SCharles.Forsyth init: fn(ctxt: ref Draw->Context, argv: list of string); 2437da2899SCharles.Forsyth}; 2537da2899SCharles.Forsyth 2637da2899SCharles.Forsythmaxrecur := 16r7ffffffe; 2737da2899SCharles.Forsyth 2837da2899SCharles.Forsythbadmodule(p: string) 2937da2899SCharles.Forsyth{ 3037da2899SCharles.Forsyth sys->fprint(stderr, "stackv: cannot load %q: %r\n", p); 3137da2899SCharles.Forsyth raise "fail:bad module"; 3237da2899SCharles.Forsyth} 3337da2899SCharles.Forsyth 3437da2899SCharles.Forsythcurrp: ref Prog; 3537da2899SCharles.Forsythshowtypes := 1; 3637da2899SCharles.Forsythshowsource := 0; 3766f5808bSforsythshowmodule := 0; 3837da2899SCharles.Forsyth 3937da2899SCharles.Forsythinit(nil: ref Draw->Context, argv: list of string) 4037da2899SCharles.Forsyth{ 4137da2899SCharles.Forsyth 4237da2899SCharles.Forsyth sys = load Sys Sys->PATH; 4337da2899SCharles.Forsyth stderr = sys->fildes(2); 4437da2899SCharles.Forsyth debug = load Debug Debug->PATH; 4537da2899SCharles.Forsyth if(debug == nil) 4637da2899SCharles.Forsyth badmodule(Debug->PATH); 4737da2899SCharles.Forsyth bufio = load Bufio Bufio->PATH; 4837da2899SCharles.Forsyth if (bufio == nil) 4937da2899SCharles.Forsyth badmodule(Bufio->PATH); 5037da2899SCharles.Forsyth arg := load Arg Arg->PATH; 5137da2899SCharles.Forsyth if (arg == nil) 5237da2899SCharles.Forsyth badmodule(Arg->PATH); 5337da2899SCharles.Forsyth stdout = bufio->fopen(sys->fildes(1), Sys->OWRITE); 5437da2899SCharles.Forsyth 5537da2899SCharles.Forsyth arg->init(argv); 5666f5808bSforsyth arg->setusage("stackv [-Tlm] [-r maxdepth] [-s dis sbl]... [pid[.sym]...] ..."); 5737da2899SCharles.Forsyth sblfile := ""; 5837da2899SCharles.Forsyth while((opt := arg->opt()) != 0){ 5937da2899SCharles.Forsyth case opt { 6037da2899SCharles.Forsyth 's' => 6137da2899SCharles.Forsyth arg->earg(); # XXX make it a list of maps from dis to sbl later 6237da2899SCharles.Forsyth sblfile = arg->earg(); 6337da2899SCharles.Forsyth 'l' => 6437da2899SCharles.Forsyth showsource = 1; 6566f5808bSforsyth 'm' => 6666f5808bSforsyth showmodule = 1; 6737da2899SCharles.Forsyth 'r' => 6837da2899SCharles.Forsyth maxrecur = int arg->earg(); 6937da2899SCharles.Forsyth 'T' => 7037da2899SCharles.Forsyth showtypes = 0; 7137da2899SCharles.Forsyth * => 7237da2899SCharles.Forsyth arg->usage(); 7337da2899SCharles.Forsyth } 7437da2899SCharles.Forsyth } 7537da2899SCharles.Forsyth debug->init(); 7637da2899SCharles.Forsyth argv = arg->argv(); 7737da2899SCharles.Forsyth printpids := len argv > 1; 7837da2899SCharles.Forsyth if(printpids) 7937da2899SCharles.Forsyth maxrecur++; 8037da2899SCharles.Forsyth for(; argv != nil; argv = tl argv) 8137da2899SCharles.Forsyth db(sys->tokenize(hd argv, ".").t1, printpids); 8237da2899SCharles.Forsyth} 8337da2899SCharles.Forsyth 8437da2899SCharles.Forsythdb(toks: list of string, printpid: int): int 8537da2899SCharles.Forsyth{ 8637da2899SCharles.Forsyth if(toks == nil){ 8737da2899SCharles.Forsyth sys->fprint(stderr, "stackv: bad pid\n"); 8837da2899SCharles.Forsyth return -1; 8937da2899SCharles.Forsyth } 9037da2899SCharles.Forsyth if((pid := int hd toks) <= 0){ 9137da2899SCharles.Forsyth sys->fprint(stderr, "stackv: bad pid %q\n", hd toks); 9237da2899SCharles.Forsyth return -1; 9337da2899SCharles.Forsyth } 9437da2899SCharles.Forsyth err: string; 9537da2899SCharles.Forsyth p: ref Prog; 9637da2899SCharles.Forsyth 9737da2899SCharles.Forsyth # reuse process if possible 9837da2899SCharles.Forsyth if(currp == nil || currp.id != pid){ 9937da2899SCharles.Forsyth (currp, err) = debug->prog(pid); 10037da2899SCharles.Forsyth if(err != nil){ 10137da2899SCharles.Forsyth sys->fprint(stderr, "stackv: %s\n", err); 10237da2899SCharles.Forsyth return -1; 10337da2899SCharles.Forsyth } 10437da2899SCharles.Forsyth if(currp == nil){ 10537da2899SCharles.Forsyth sys->fprint(stderr, "stackv: nil prog from pid %d\n", pid); 10637da2899SCharles.Forsyth return -1; 10737da2899SCharles.Forsyth } 10837da2899SCharles.Forsyth } 10937da2899SCharles.Forsyth p = currp; 11037da2899SCharles.Forsyth stk: array of ref Exp; 11137da2899SCharles.Forsyth (stk, err) = p.stack(); 11237da2899SCharles.Forsyth if(err != nil){ 11337da2899SCharles.Forsyth sys->fprint(stderr, "stackv: %s\n", err); 11437da2899SCharles.Forsyth return -1; 11537da2899SCharles.Forsyth } 11637da2899SCharles.Forsyth for (i := 0; i < len stk; i++) { 11737da2899SCharles.Forsyth stk[i].m.stdsym(); 11837da2899SCharles.Forsyth stk[i].findsym(); 11937da2899SCharles.Forsyth } 12037da2899SCharles.Forsyth depth := 0; 12137da2899SCharles.Forsyth if(printpid){ 12237da2899SCharles.Forsyth stdout.puts(sys->sprint("prog %d {\n", pid)); # } 12337da2899SCharles.Forsyth depth++; 12437da2899SCharles.Forsyth } 12537da2899SCharles.Forsyth pexp(stk, tl toks, depth); 12637da2899SCharles.Forsyth if(printpid) 12737da2899SCharles.Forsyth stdout.puts("}\n"); 12837da2899SCharles.Forsyth stdout.flush(); 12937da2899SCharles.Forsyth return 0; 13037da2899SCharles.Forsyth} 13137da2899SCharles.Forsyth 13237da2899SCharles.Forsythpexp(stk: array of ref Exp, toks: list of string, depth: int) 13337da2899SCharles.Forsyth{ 13437da2899SCharles.Forsyth if(toks == nil){ 13537da2899SCharles.Forsyth for (i := 0; i < len stk; i++) 13637da2899SCharles.Forsyth pfn(stk[i], depth); 13737da2899SCharles.Forsyth }else{ 13837da2899SCharles.Forsyth exp := stackfindsym(stk, toks, depth); 13937da2899SCharles.Forsyth if(exp == nil) 14037da2899SCharles.Forsyth return; 14166f5808bSforsyth pname(exp, depth, nil); 14237da2899SCharles.Forsyth stdout.putc('\n'); 14337da2899SCharles.Forsyth } 14437da2899SCharles.Forsyth} 14537da2899SCharles.Forsyth 14637da2899SCharles.Forsythstackfindsym(stk: array of ref Exp, toks: list of string, depth: int): ref Exp 14737da2899SCharles.Forsyth{ 14837da2899SCharles.Forsyth fname := hd toks; 14937da2899SCharles.Forsyth toks = tl toks; 15037da2899SCharles.Forsyth for(i := 0; i < len stk; i++){ 15137da2899SCharles.Forsyth s := stk[i].name; 15237da2899SCharles.Forsyth if(s == fname) 15337da2899SCharles.Forsyth break; 15437da2899SCharles.Forsyth if(hasdot(s) && toks != nil && s == fname+"."+hd toks){ 15537da2899SCharles.Forsyth fname += "."+hd toks; 15637da2899SCharles.Forsyth toks = tl toks; 15737da2899SCharles.Forsyth break; 15837da2899SCharles.Forsyth } 15937da2899SCharles.Forsyth } 16037da2899SCharles.Forsyth if(i == len stk){ 16137da2899SCharles.Forsyth indent(depth); 16237da2899SCharles.Forsyth stdout.puts("function not found\n"); 16337da2899SCharles.Forsyth return nil; 16437da2899SCharles.Forsyth } 16537da2899SCharles.Forsyth if(toks == nil) 16637da2899SCharles.Forsyth return stk[i]; 16737da2899SCharles.Forsyth stk = stk[i].expand(); 16837da2899SCharles.Forsyth if(hd toks == "module"){ 16937da2899SCharles.Forsyth if((e := getname(stk, "module")) == nil){ 17037da2899SCharles.Forsyth indent(depth); 17137da2899SCharles.Forsyth stdout.puts(sys->sprint("no module declarations in function %q\n", fname)); 17237da2899SCharles.Forsyth }else if((e = symfindsym(e, tl toks, depth)) != nil) 17337da2899SCharles.Forsyth return e; 17437da2899SCharles.Forsyth return nil; 17537da2899SCharles.Forsyth } 17637da2899SCharles.Forsyth for(t := "locals" :: "args" :: "module" :: nil; t != nil; t = tl t){ 17737da2899SCharles.Forsyth if((e := getname(stk, hd t)) == nil) 17837da2899SCharles.Forsyth continue; 17937da2899SCharles.Forsyth if((e = symfindsym(e, toks, depth)) != nil) 18037da2899SCharles.Forsyth return e; 18137da2899SCharles.Forsyth } 18237da2899SCharles.Forsyth indent(depth); 18337da2899SCharles.Forsyth stdout.puts(sys->sprint("symbol %q not found in function %q\n", hd toks, fname)); 18437da2899SCharles.Forsyth return nil; 18537da2899SCharles.Forsyth} 18637da2899SCharles.Forsyth 18737da2899SCharles.Forsythhasdot(s: string): int 18837da2899SCharles.Forsyth{ 18937da2899SCharles.Forsyth for(i := 0; i < len s; i++) 19037da2899SCharles.Forsyth if(s[i] == '.') 19137da2899SCharles.Forsyth return 1; 19237da2899SCharles.Forsyth return 0; 19337da2899SCharles.Forsyth} 19437da2899SCharles.Forsyth 19537da2899SCharles.Forsythsymfindsym(e: ref Exp, toks: list of string, depth: int): ref Exp 19637da2899SCharles.Forsyth{ 19737da2899SCharles.Forsyth if(toks == nil) 19837da2899SCharles.Forsyth return e; 19937da2899SCharles.Forsyth exps := e.expand(); 20037da2899SCharles.Forsyth for(i := 0; i < len exps; i++) 20137da2899SCharles.Forsyth if(exps[i].name == hd toks) 20237da2899SCharles.Forsyth return symfindsym(exps[i], tl toks, depth); 20337da2899SCharles.Forsyth return nil; 20437da2899SCharles.Forsyth} 20537da2899SCharles.Forsyth 20637da2899SCharles.Forsythpfn(exp: ref Exp, depth: int) 20737da2899SCharles.Forsyth{ 20837da2899SCharles.Forsyth (v, w) := exp.val(); 20937da2899SCharles.Forsyth if(!w || v == nil){ 21037da2899SCharles.Forsyth indent(depth); 21137da2899SCharles.Forsyth stdout.puts(sys->sprint("no value for fn %q\n", exp.name)); 21237da2899SCharles.Forsyth return; 21337da2899SCharles.Forsyth } 21437da2899SCharles.Forsyth exps := exp.expand(); 21537da2899SCharles.Forsyth indent(depth); 21637da2899SCharles.Forsyth stdout.puts("["+exp.srcstr()+"]\n"); 21737da2899SCharles.Forsyth indent(depth); 21837da2899SCharles.Forsyth stdout.puts(symname(exp)+"("); 21937da2899SCharles.Forsyth if((e := getname(exps, "args")) != nil){ 22037da2899SCharles.Forsyth args := e.expand(); 22137da2899SCharles.Forsyth for(i := 0; i < len args; i++){ 22266f5808bSforsyth pname(args[i], depth+1, nil); 22337da2899SCharles.Forsyth if(i != len args - 1) 22437da2899SCharles.Forsyth stdout.puts(", "); 22537da2899SCharles.Forsyth } 22637da2899SCharles.Forsyth } 22737da2899SCharles.Forsyth stdout.puts(")\n"); 22837da2899SCharles.Forsyth indent(depth); 22937da2899SCharles.Forsyth stdout.puts("{\n"); # } 23037da2899SCharles.Forsyth if((e = getname(exps, "locals")) != nil){ 23137da2899SCharles.Forsyth locals := e.expand(); 23237da2899SCharles.Forsyth for(i := 0; i < len locals; i++){ 23337da2899SCharles.Forsyth indent(depth+1); 23466f5808bSforsyth pname(locals[i], depth+1, nil); 23566f5808bSforsyth stdout.puts("\n"); 23666f5808bSforsyth } 23766f5808bSforsyth } 23866f5808bSforsyth if(showmodule && (e = getname(exps, "module")) != nil){ 23966f5808bSforsyth mvars := e.expand(); 24066f5808bSforsyth for(i := 0; i < len mvars; i++){ 24166f5808bSforsyth indent(depth+1); 24266f5808bSforsyth pname(mvars[i], depth+1, "module."); 24337da2899SCharles.Forsyth stdout.puts("\n"); 24437da2899SCharles.Forsyth } 24537da2899SCharles.Forsyth } 24637da2899SCharles.Forsyth indent(depth); 24737da2899SCharles.Forsyth stdout.puts("}\n"); 24837da2899SCharles.Forsyth} 24937da2899SCharles.Forsyth 25037da2899SCharles.Forsythgetname(exps: array of ref Exp, name: string): ref Exp 25137da2899SCharles.Forsyth{ 25237da2899SCharles.Forsyth for(i := 0; i < len exps; i++) 25337da2899SCharles.Forsyth if(exps[i].name == name) 25437da2899SCharles.Forsyth return exps[i]; 25537da2899SCharles.Forsyth return nil; 25637da2899SCharles.Forsyth} 25737da2899SCharles.Forsyth 25837da2899SCharles.Forsythstrval(v: string): string 25937da2899SCharles.Forsyth{ 26037da2899SCharles.Forsyth for(i := 0; i < len v; i++) 26137da2899SCharles.Forsyth if(v[i] == '"') 26237da2899SCharles.Forsyth break; 26337da2899SCharles.Forsyth if(i < len v) 26437da2899SCharles.Forsyth v = v[i:]; 26537da2899SCharles.Forsyth return v; 26637da2899SCharles.Forsyth} 26737da2899SCharles.Forsyth 26866f5808bSforsythpname(exp: ref Exp, depth: int, prefix: string) 26937da2899SCharles.Forsyth{ 27066f5808bSforsyth name := prefix+symname(exp); 27137da2899SCharles.Forsyth (v, w) := exp.val(); 27237da2899SCharles.Forsyth if (!w && v == nil) { 27337da2899SCharles.Forsyth stdout.puts(sys->sprint("%s: %s = novalue", symname(exp), exp.typename())); 27437da2899SCharles.Forsyth return; 27537da2899SCharles.Forsyth } 27637da2899SCharles.Forsyth case exp.kind() { 27737da2899SCharles.Forsyth Tfn => 27837da2899SCharles.Forsyth pfn(exp, depth); 27937da2899SCharles.Forsyth Tint => 28066f5808bSforsyth stdout.puts(sys->sprint("%s := %s", name, v)); 28137da2899SCharles.Forsyth Tstring => 28266f5808bSforsyth stdout.puts(sys->sprint("%s := %s", name, strval(v))); 28337da2899SCharles.Forsyth Tbyte or 28437da2899SCharles.Forsyth Tbig or 28537da2899SCharles.Forsyth Treal => 28666f5808bSforsyth stdout.puts(sys->sprint("%s := %s %s", name, exp.typename(), v)); 28737da2899SCharles.Forsyth * => 28837da2899SCharles.Forsyth if(showtypes) 28966f5808bSforsyth stdout.puts(sys->sprint("%s: %s = ", name, exp.typename())); 29037da2899SCharles.Forsyth else 29166f5808bSforsyth stdout.puts(sys->sprint("%s := ", name)); 29237da2899SCharles.Forsyth pval(exp, v, w, depth); 29337da2899SCharles.Forsyth } 29437da2899SCharles.Forsyth} 29537da2899SCharles.Forsyth 29637da2899SCharles.Forsythsrcstr(src: ref Debug->Src): string 29737da2899SCharles.Forsyth{ 29837da2899SCharles.Forsyth if(src == nil) 29937da2899SCharles.Forsyth return nil; 30037da2899SCharles.Forsyth if(src.start.file != src.stop.file) 30137da2899SCharles.Forsyth return sys->sprint("%q:%d.%d,%q:%d.%d", src.start.file, src.start.line, src.start.pos, src.stop.file, src.stop.line, src.stop.pos); 30237da2899SCharles.Forsyth if(src.start.line != src.stop.line) 30337da2899SCharles.Forsyth return sys->sprint("%q:%d.%d,%d.%d", src.start.file, src.start.line, src.start.pos, src.stop.line, src.stop.pos); 30437da2899SCharles.Forsyth return sys->sprint("%q:%d.%d,%d", src.start.file, src.start.line, src.start.pos, src.stop.pos); 30537da2899SCharles.Forsyth} 30637da2899SCharles.Forsyth 30737da2899SCharles.Forsythpval(exp: ref Exp, v: string, w: int, depth: int) 30837da2899SCharles.Forsyth{ 30937da2899SCharles.Forsyth if(depth >= maxrecur){ 31037da2899SCharles.Forsyth stdout.puts(v); 31137da2899SCharles.Forsyth return; 31237da2899SCharles.Forsyth } 31337da2899SCharles.Forsyth case exp.kind() { 31437da2899SCharles.Forsyth Tarray => 31537da2899SCharles.Forsyth if(pref(v)){ 31637da2899SCharles.Forsyth if(depth+1 >= maxrecur) 31737da2899SCharles.Forsyth stdout.puts(v+"{...}"); 31837da2899SCharles.Forsyth else{ 31937da2899SCharles.Forsyth stdout.puts(v+"{\n"); 32037da2899SCharles.Forsyth indent(depth+1); 32137da2899SCharles.Forsyth parray(exp, depth+1); 32237da2899SCharles.Forsyth stdout.puts("\n"); 32337da2899SCharles.Forsyth indent(depth); 32437da2899SCharles.Forsyth stdout.puts("}"); 32537da2899SCharles.Forsyth } 32637da2899SCharles.Forsyth } 32737da2899SCharles.Forsyth Tlist => 32837da2899SCharles.Forsyth if(v == "nil") 32937da2899SCharles.Forsyth stdout.puts("nil"); 33037da2899SCharles.Forsyth else 33137da2899SCharles.Forsyth if(depth+1 >= maxrecur) 33237da2899SCharles.Forsyth stdout.puts(v+"{...}"); 33337da2899SCharles.Forsyth else{ 33437da2899SCharles.Forsyth stdout.puts("{\n"); 33537da2899SCharles.Forsyth indent(depth+1); 33637da2899SCharles.Forsyth plist(exp, v, w, depth+1); 33737da2899SCharles.Forsyth stdout.puts("\n"); 33837da2899SCharles.Forsyth indent(depth); 33937da2899SCharles.Forsyth stdout.puts("}"); 34037da2899SCharles.Forsyth } 34137da2899SCharles.Forsyth Tadt => 34237da2899SCharles.Forsyth pgenval(exp, nil, w, depth); 34337da2899SCharles.Forsyth Tref => 34437da2899SCharles.Forsyth if(pref(v)) 34537da2899SCharles.Forsyth pgenval(exp, v, w, depth); 34637da2899SCharles.Forsyth Tstring => 34737da2899SCharles.Forsyth stdout.puts(strval(v)); 34837da2899SCharles.Forsyth * => 34937da2899SCharles.Forsyth pgenval(exp, v, w, depth); 35037da2899SCharles.Forsyth } 35137da2899SCharles.Forsyth} 35237da2899SCharles.Forsyth 35337da2899SCharles.Forsythparray(exp: ref Exp, depth: int) 35437da2899SCharles.Forsyth{ 35537da2899SCharles.Forsyth exps := exp.expand(); 35637da2899SCharles.Forsyth for(i := 0; i < len exps; i++){ 35737da2899SCharles.Forsyth e := exps[i]; 35837da2899SCharles.Forsyth (v, w) := e.val(); 35937da2899SCharles.Forsyth if(e.kind() == Tslice) 36037da2899SCharles.Forsyth parray(e, depth); 36137da2899SCharles.Forsyth else{ 36237da2899SCharles.Forsyth pval(e, v, w, depth); 36337da2899SCharles.Forsyth stdout.puts(", "); 36437da2899SCharles.Forsyth } 36537da2899SCharles.Forsyth } 36637da2899SCharles.Forsyth} 36737da2899SCharles.Forsyth 36837da2899SCharles.Forsythplist(exp: ref Exp, v: string, w: int, depth: int) 36937da2899SCharles.Forsyth{ 37037da2899SCharles.Forsyth while(w && v != "nil"){ 37137da2899SCharles.Forsyth exps := exp.expand(); 37237da2899SCharles.Forsyth h := getname(exps, "hd"); 3733f1f06c5SCharles.Forsyth if(h == nil) 3743f1f06c5SCharles.Forsyth break; 37537da2899SCharles.Forsyth (hv, vw) := h.val(); 37637da2899SCharles.Forsyth if(pref(v) == 0) 37737da2899SCharles.Forsyth return; 37837da2899SCharles.Forsyth stdout.puts(v+"("); 37937da2899SCharles.Forsyth pval(h, hv, vw, depth); 38037da2899SCharles.Forsyth stdout.puts(") :: "); 38137da2899SCharles.Forsyth h = nil; 38237da2899SCharles.Forsyth exp = getname(exps, "tl"); 38337da2899SCharles.Forsyth (v, w) = exp.val(); 38437da2899SCharles.Forsyth } 38537da2899SCharles.Forsyth stdout.puts("nil"); 38637da2899SCharles.Forsyth} 38737da2899SCharles.Forsyth 38837da2899SCharles.Forsythpgenval(exp: ref Exp, v: string, w: int, depth: int) 38937da2899SCharles.Forsyth{ 39037da2899SCharles.Forsyth if(w){ 39137da2899SCharles.Forsyth exps := exp.expand(); 39237da2899SCharles.Forsyth if(len exps == 0) 39337da2899SCharles.Forsyth stdout.puts(v); 39437da2899SCharles.Forsyth else{ 39537da2899SCharles.Forsyth stdout.puts(v+"{\n"); # } 39637da2899SCharles.Forsyth if (len exps > 0){ 39737da2899SCharles.Forsyth if(depth >= maxrecur){ 39837da2899SCharles.Forsyth indent(depth); 39937da2899SCharles.Forsyth stdout.puts(sys->sprint("...[%d]\n", len exps)); 40037da2899SCharles.Forsyth }else{ 40137da2899SCharles.Forsyth for (i := 0; i < len exps; i++){ 40237da2899SCharles.Forsyth indent(depth+1); 40366f5808bSforsyth pname(exps[i], depth+1, nil); 40437da2899SCharles.Forsyth stdout.puts("\n"); 40537da2899SCharles.Forsyth } 40637da2899SCharles.Forsyth } 40737da2899SCharles.Forsyth } 40837da2899SCharles.Forsyth indent(depth); # { 40937da2899SCharles.Forsyth stdout.puts("}"); 41037da2899SCharles.Forsyth } 41137da2899SCharles.Forsyth }else 41237da2899SCharles.Forsyth stdout.puts(v); 41337da2899SCharles.Forsyth} 41437da2899SCharles.Forsyth 41537da2899SCharles.Forsythsymname(exp: ref Exp): string 41637da2899SCharles.Forsyth{ 41737da2899SCharles.Forsyth if(showsource == 0) 41837da2899SCharles.Forsyth return exp.name; 41937da2899SCharles.Forsyth return exp.name+"["+srcstr(exp.src())+"]"; 42037da2899SCharles.Forsyth} 42137da2899SCharles.Forsyth 42237da2899SCharles.Forsythindent(n: int) 42337da2899SCharles.Forsyth{ 42437da2899SCharles.Forsyth while(n-- > 0) 42566f5808bSforsyth stdout.putc('\t'); 42666f5808bSforsyth} 42766f5808bSforsyth 42866f5808bSforsythref2int(v: string): int 42966f5808bSforsyth{ 43066f5808bSforsyth if(v == nil) 43166f5808bSforsyth error("bad empty value for ref"); 43266f5808bSforsyth i := 0; 43366f5808bSforsyth n := len v; 43466f5808bSforsyth if(v[0] == '@') 43566f5808bSforsyth i = 1; 43666f5808bSforsyth else{ 43766f5808bSforsyth # skip array bounds 43866f5808bSforsyth if(v[0] == '['){ 43966f5808bSforsyth for(; i < n && v[i] != ']'; i++) 44066f5808bSforsyth ; 44166f5808bSforsyth if(i >= n - 2 || v[i+1] != ' ' || v[i+2] != '@') 44266f5808bSforsyth error("bad value for ref: "+v); 44366f5808bSforsyth i += 3; 44466f5808bSforsyth } 44566f5808bSforsyth } 44666f5808bSforsyth if(n - i > 8) 44766f5808bSforsyth error("64-bit pointers?"); 44866f5808bSforsyth p := 0; 44966f5808bSforsyth for(; i < n; i++){ 45066f5808bSforsyth c := v[i]; 45166f5808bSforsyth case c { 45266f5808bSforsyth '0' to '9' => 45366f5808bSforsyth p = (p << 4) + (c - '0'); 45466f5808bSforsyth 'a' to 'f' => 45566f5808bSforsyth p = (p << 4) + (c - 'a' + 10); 45666f5808bSforsyth * => 45766f5808bSforsyth error("bad value for ref: "+v); 45866f5808bSforsyth } 45966f5808bSforsyth } 46066f5808bSforsyth return p; 46137da2899SCharles.Forsyth} 46237da2899SCharles.Forsyth 46337da2899SCharles.Forsythpref(v: string): int 46437da2899SCharles.Forsyth{ 46566f5808bSforsyth if(v == "nil"){ 46666f5808bSforsyth stdout.puts("nil"); 46766f5808bSforsyth return 0; 46866f5808bSforsyth } 46966f5808bSforsyth if(addref(ref2int(v)) == 0){ 47037da2899SCharles.Forsyth stdout.puts(v); 47137da2899SCharles.Forsyth stdout.puts("(qv)"); 47237da2899SCharles.Forsyth return 0; 47337da2899SCharles.Forsyth } 47437da2899SCharles.Forsyth return 1; 47537da2899SCharles.Forsyth} 47637da2899SCharles.Forsyth 47766f5808bSforsyth# hash table implementation that tries to be reasonably 47866f5808bSforsyth# parsimonious on memory usage. 47966f5808bSforsythaddref(v: int): int 48037da2899SCharles.Forsyth{ 48166f5808bSforsyth slot := (v & 16r7fffffff) % len hasht; 48266f5808bSforsyth (n, a) := hasht[slot]; 48366f5808bSforsyth for(i := 0; i < n; i++) 48466f5808bSforsyth if(a[i] == v) 48537da2899SCharles.Forsyth return 0; 48666f5808bSforsyth if(n == len a){ 48766f5808bSforsyth if(n == 0) 48866f5808bSforsyth n = 3; 48966f5808bSforsyth t := array[n*3/2] of int; 49066f5808bSforsyth t[0:] = a; 49166f5808bSforsyth hasht[slot].t1 = t; 492*99c84fefSforsyth a = t; 49366f5808bSforsyth } 49466f5808bSforsyth a[hasht[slot].t0++] = v; 49537da2899SCharles.Forsyth return 1; 49637da2899SCharles.Forsyth} 49737da2899SCharles.Forsyth 49866f5808bSforsytherror(e: string) 49937da2899SCharles.Forsyth{ 50066f5808bSforsyth sys->fprint(sys->fildes(2), "stackv: error: %s\n", e); 50166f5808bSforsyth raise "fail:error"; 50237da2899SCharles.Forsyth} 503