summaryrefslogtreecommitdiff
path: root/appl/cmd/stack.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/stack.b')
-rw-r--r--appl/cmd/stack.b184
1 files changed, 184 insertions, 0 deletions
diff --git a/appl/cmd/stack.b b/appl/cmd/stack.b
new file mode 100644
index 00000000..7b90a0b5
--- /dev/null
+++ b/appl/cmd/stack.b
@@ -0,0 +1,184 @@
+implement Command;
+
+include "sys.m";
+ sys: Sys;
+ print, fprint, FD: import sys;
+ stderr: ref FD;
+
+include "draw.m";
+
+include "debug.m";
+ debug: Debug;
+ Prog, Module, Exp: import debug;
+
+include "arg.m";
+include "bufio.m";
+ bufio: Bufio;
+ Iobuf: import bufio;
+
+include "env.m";
+ env: Env;
+
+include "string.m";
+ str: String;
+
+include "dis.m";
+ dism: Dis;
+
+Command: module
+{
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+usage()
+{
+ sys->fprint(stderr, "usage: stack [-v] pid\n");
+ raise "fail:usage";
+}
+
+badmodule(p: string)
+{
+ sys->fprint(stderr, "stack: cannot load %s: %r\n", p);
+ raise "fail:bad module";
+}
+
+sbldirs: list of (string, string);
+
+init(nil: ref Draw->Context, argv: list of string)
+{
+
+ sys = load Sys Sys->PATH;
+ stderr = sys->fildes(2);
+ arg := load Arg Arg->PATH;
+ if (arg == nil)
+ badmodule(Arg->PATH);
+ bufio = load Bufio Bufio->PATH;
+ if (bufio == nil)
+ badmodule(Bufio->PATH);
+ debug = load Debug Debug->PATH;
+ if(debug == nil)
+ badmodule(Debug->PATH);
+ env = load Env Env->PATH;
+ if (env != nil) {
+ str = load String String->PATH;
+ if (str == nil)
+ badmodule(String->PATH);
+ }
+ bout := bufio->fopen(sys->fildes(1), Sys->OWRITE);
+
+ arg->init(argv);
+ verbose := 0;
+ while ((opt := arg->opt()) != 0) {
+ case opt {
+ 'v' =>
+ verbose = 1;
+ 'p' =>
+ dispath := arg->arg();
+ sblpath := arg->arg();
+ if (dispath == nil || sblpath == nil)
+ usage();
+ sbldirs = (addslash(dispath), addslash(sblpath)) :: sbldirs;
+ * =>
+ usage();
+ }
+ }
+ if (env != nil && (pathl := env->getenv("sblpath")) != nil) {
+ toks := str->unquoted(pathl);
+ for (; toks != nil && tl toks != nil; toks = tl tl toks)
+ sbldirs = (addslash(hd toks), addslash(hd tl toks)) :: sbldirs;
+ }
+ t: list of (string, string);
+ for (; sbldirs != nil; sbldirs = tl sbldirs)
+ t = hd sbldirs :: t;
+ sbldirs = t;
+
+ argv = arg->argv();
+ if(argv == nil)
+ usage();
+
+ debug->init();
+
+ (p, err) := debug->prog(int hd argv);
+ if(err != nil){
+ fprint(stderr, "stack: %s\n", err);
+ return;
+ }
+ stk: array of ref Exp;
+ (stk, err) = p.stack();
+
+ if(err != nil){
+ fprint(stderr, "stack: %s\n", err);
+ return;
+ }
+
+ for(i := 0; i < len stk; i++){
+ stdsym(stk[i].m);
+ stk[i].m.stdsym();
+ stk[i].findsym();
+ bout.puts(stk[i].name + "(");
+ vs := stk[i].expand();
+ if(verbose && vs != nil){
+ for(j := 0; j < len vs; j++){
+ if(vs[j].name == "args"){
+ d := vs[j].expand();
+ s := "";
+ for(j = 0; j < len d; j++) {
+ bout.puts(sys->sprint("%s%s=%s", s, d[j].name, d[j].val().t0));
+ s = ", ";
+ }
+ break;
+ }
+ }
+ }
+ bout.puts(sys->sprint(") %s\n", stk[i].srcstr()));
+ if(verbose && vs != nil){
+ for(j := 0; j < len vs; j++){
+ if(vs[j].name == "locals"){
+ d := vs[j].expand();
+ for(j = 0; j < len d; j++)
+ bout.puts("\t" + d[j].name + "=" + d[j].val().t0 + "\n");
+ break;
+ }
+ }
+ }
+ }
+ bout.flush();
+}
+
+stdsym(m: ref Module)
+{
+ dis := m.dis();
+ if(dism == nil){
+ dism = load Dis Dis->PATH;
+ if(dism != nil)
+ dism->init();
+ }
+ if(dism != nil && (sp := dism->src(dis)) != nil){
+ sp = sp[0: len sp - 1] + "sbl";
+ (sym, err) := debug->sym(sp);
+ if (sym != nil) {
+ m.addsym(sym);
+ return;
+ }
+ }
+ for (sbl := sbldirs; sbl != nil; sbl = tl sbl) {
+ (dispath, sblpath) := hd sbl;
+ if (len dis > len dispath && dis[0:len dispath] == dispath) {
+ sblpath = sblpath + dis[len dispath:];
+ if (len sblpath > 4 && sblpath[len sblpath - 4:] == ".dis")
+ sblpath = sblpath[0:len sblpath - 4] + ".sbl";
+ (sym, err) := debug->sym(sblpath);
+ if (sym != nil) {
+ m.addsym(sym);
+ return;
+ }
+ }
+ }
+}
+
+addslash(p: string): string
+{
+ if (p != nil && p[len p - 1] != '/')
+ p[len p] = '/';
+ return p;
+}