121601Sdist /* 221601Sdist * Copyright (c) 1983 Regents of the University of California. 321601Sdist * All rights reserved. The Berkeley software License Agreement 421601Sdist * specifies the terms and conditions for redistribution. 521601Sdist */ 69662Slinton 721601Sdist #ifndef lint 8*33315Sdonn static char sccsid[] = "@(#)eval.c 5.5 (Berkeley) 01/12/88"; 921601Sdist #endif not lint 109662Slinton 11*33315Sdonn static char rcsid[] = "$Header: eval.c,v 1.2 87/03/25 19:48:33 donn Exp $"; 1218217Slinton 139662Slinton /* 149662Slinton * Tree evaluation. 159662Slinton */ 169662Slinton 179662Slinton #include "defs.h" 189662Slinton #include "tree.h" 199662Slinton #include "operators.h" 2018217Slinton #include "debug.h" 219662Slinton #include "eval.h" 229662Slinton #include "events.h" 239662Slinton #include "symbols.h" 249662Slinton #include "scanner.h" 259662Slinton #include "source.h" 269662Slinton #include "object.h" 279662Slinton #include "mappings.h" 289662Slinton #include "process.h" 2916608Ssam #include "runtime.h" 309662Slinton #include "machine.h" 319662Slinton #include <signal.h> 329662Slinton 339662Slinton #ifndef public 349662Slinton 359662Slinton #include "machine.h" 369662Slinton 3712538Scsvaf #define STACKSIZE 20000 389662Slinton 399662Slinton typedef Char Stack; 409662Slinton 419662Slinton #define push(type, value) { \ 429662Slinton ((type *) (sp += sizeof(type)))[-1] = (value); \ 439662Slinton } 449662Slinton 459662Slinton #define pop(type) ( \ 469662Slinton (*((type *) (sp -= sizeof(type)))) \ 479662Slinton ) 489662Slinton 4916608Ssam #define popn(n, dest) { \ 5016608Ssam sp -= n; \ 5116608Ssam bcopy(sp, dest, n); \ 5216608Ssam } 5316608Ssam 549662Slinton #define alignstack() { \ 559662Slinton sp = (Stack *) (( ((int) sp) + sizeof(int) - 1)&~(sizeof(int) - 1)); \ 569662Slinton } 579662Slinton 589662Slinton #endif 599662Slinton 609662Slinton public Stack stack[STACKSIZE]; 619662Slinton public Stack *sp = &stack[0]; 6214674Slinton public Boolean useInstLoc = false; 639662Slinton 649662Slinton #define chksp() \ 659662Slinton { \ 669662Slinton if (sp < &stack[0]) { \ 679662Slinton panic("stack underflow"); \ 689662Slinton } \ 699662Slinton } 709662Slinton 719662Slinton #define poparg(n, r, fr) { \ 729662Slinton eval(p->value.arg[n]); \ 739662Slinton if (isreal(p->op)) { \ 7416608Ssam if (size(p->value.arg[n]->nodetype) == sizeof(float)) { \ 7516608Ssam fr = pop(float); \ 7616608Ssam } else { \ 7716608Ssam fr = pop(double); \ 7816608Ssam } \ 799662Slinton } else if (isint(p->op)) { \ 809662Slinton r = popsmall(p->value.arg[n]->nodetype); \ 819662Slinton } \ 829662Slinton } 839662Slinton 849662Slinton #define Boolrep char /* underlying representation type for booleans */ 859662Slinton 869662Slinton /* 8718217Slinton * Command-level evaluation. 8818217Slinton */ 8918217Slinton 9018217Slinton public Node topnode; 9118217Slinton 9218217Slinton public topeval (p) 9318217Slinton Node p; 9418217Slinton { 9518217Slinton if (traceeval) { 9618217Slinton fprintf(stderr, "topeval("); 9718217Slinton prtree(stderr, p); 9818217Slinton fprintf(stderr, ")\n"); 9918217Slinton fflush(stderr); 10018217Slinton } 10118217Slinton topnode = p; 10218217Slinton eval(p); 10318217Slinton } 10418217Slinton 10518217Slinton /* 1069662Slinton * Evaluate a parse tree leaving the value on the top of the stack. 1079662Slinton */ 1089662Slinton 1099662Slinton public eval(p) 1109662Slinton register Node p; 1119662Slinton { 1129662Slinton long r0, r1; 1139662Slinton double fr0, fr1; 1149662Slinton Address addr; 1159662Slinton long i, n; 1169662Slinton int len; 11718217Slinton Symbol s; 1189662Slinton Node n1, n2; 11918217Slinton boolean b; 1209662Slinton File file; 12118217Slinton String str; 1229662Slinton 1239662Slinton checkref(p); 12418217Slinton if (traceeval) { 12518217Slinton fprintf(stderr, "begin eval %s\n", opname(p->op)); 12612538Scsvaf } 1279662Slinton switch (degree(p->op)) { 1289662Slinton case BINARY: 1299662Slinton poparg(1, r1, fr1); 1309662Slinton poparg(0, r0, fr0); 1319662Slinton break; 1329662Slinton 1339662Slinton case UNARY: 1349662Slinton poparg(0, r0, fr0); 1359662Slinton break; 1369662Slinton 1379662Slinton default: 1389662Slinton /* do nothing */; 1399662Slinton } 1409662Slinton switch (p->op) { 1419662Slinton case O_SYM: 1429662Slinton s = p->value.sym; 1439662Slinton if (s == retaddrsym) { 1449662Slinton push(long, return_addr()); 14518217Slinton } else if (isvariable(s)) { 14618217Slinton if (s != program and not isactive(container(s))) { 14718217Slinton error("\"%s\" is not active", symname(s)); 14818217Slinton } 14918217Slinton if (isvarparam(s) and not isopenarray(s)) { 15018217Slinton rpush(address(s, nil), sizeof(Address)); 1519662Slinton } else { 15218217Slinton push(Address, address(s, nil)); 1539662Slinton } 15418217Slinton } else if (isblock(s)) { 15518217Slinton push(Symbol, s); 15618217Slinton } else if (isconst(s)) { 15718217Slinton eval(constval(s)); 15818217Slinton } else { 15918217Slinton error("can't evaluate a %s", classname(s)); 1609662Slinton } 1619662Slinton break; 1629662Slinton 1639662Slinton case O_LCON: 16418217Slinton case O_CCON: 1659662Slinton r0 = p->value.lcon; 1669662Slinton pushsmall(p->nodetype, r0); 1679662Slinton break; 1689662Slinton 1699662Slinton case O_FCON: 1709662Slinton push(double, p->value.fcon); 1719662Slinton break; 1729662Slinton 1739662Slinton case O_SCON: 1749662Slinton len = size(p->nodetype); 1759662Slinton mov(p->value.scon, sp, len); 1769662Slinton sp += len; 1779662Slinton break; 1789662Slinton 1799662Slinton case O_INDEX: 18018217Slinton s = p->value.arg[0]->nodetype; 18118217Slinton p->value.arg[0]->nodetype = t_addr; 18218217Slinton eval(p->value.arg[0]); 18318217Slinton p->value.arg[0]->nodetype = s; 18418217Slinton n = pop(Address); 18518217Slinton eval(p->value.arg[1]); 18618217Slinton evalindex(s, n, popsmall(p->value.arg[1]->nodetype)); 1879662Slinton break; 1889662Slinton 1899662Slinton case O_DOT: 1909662Slinton s = p->value.arg[1]->value.sym; 19118217Slinton eval(p->value.arg[0]); 19218217Slinton n = pop(long); 1939662Slinton push(long, n + (s->symvalue.field.offset div 8)); 1949662Slinton break; 1959662Slinton 1969662Slinton /* 1979662Slinton * Get the value of the expression addressed by the top of the stack. 1989662Slinton * Push the result back on the stack. 1999662Slinton */ 2009662Slinton 2019662Slinton case O_INDIR: 2029662Slinton case O_RVAL: 2039662Slinton addr = pop(long); 2049662Slinton if (addr == 0) { 2059662Slinton error("reference through nil pointer"); 2069662Slinton } 20718217Slinton len = size(p->nodetype); 2089662Slinton rpush(addr, len); 2099662Slinton break; 2109662Slinton 21111175Slinton case O_TYPERENAME: 212*33315Sdonn loophole(size(p->value.arg[0]->nodetype), size(p->nodetype)); 21311175Slinton break; 21411175Slinton 2159662Slinton case O_COMMA: 21618217Slinton eval(p->value.arg[0]); 21718217Slinton if (p->value.arg[1] != nil) { 21818217Slinton eval(p->value.arg[1]); 21918217Slinton } 2209662Slinton break; 2219662Slinton 2229662Slinton case O_ITOF: 2239662Slinton push(double, (double) r0); 2249662Slinton break; 2259662Slinton 2269662Slinton case O_ADD: 2279662Slinton push(long, r0+r1); 2289662Slinton break; 2299662Slinton 2309662Slinton case O_ADDF: 2319662Slinton push(double, fr0+fr1); 2329662Slinton break; 2339662Slinton 2349662Slinton case O_SUB: 2359662Slinton push(long, r0-r1); 2369662Slinton break; 2379662Slinton 2389662Slinton case O_SUBF: 2399662Slinton push(double, fr0-fr1); 2409662Slinton break; 2419662Slinton 2429662Slinton case O_NEG: 2439662Slinton push(long, -r0); 2449662Slinton break; 2459662Slinton 2469662Slinton case O_NEGF: 2479662Slinton push(double, -fr0); 2489662Slinton break; 2499662Slinton 2509662Slinton case O_MUL: 2519662Slinton push(long, r0*r1); 2529662Slinton break; 2539662Slinton 2549662Slinton case O_MULF: 2559662Slinton push(double, fr0*fr1); 2569662Slinton break; 2579662Slinton 2589662Slinton case O_DIVF: 2599662Slinton if (fr1 == 0) { 2609662Slinton error("error: division by 0"); 2619662Slinton } 2629662Slinton push(double, fr0 / fr1); 2639662Slinton break; 2649662Slinton 2659662Slinton case O_DIV: 2669662Slinton if (r1 == 0) { 2679662Slinton error("error: div by 0"); 2689662Slinton } 2699662Slinton push(long, r0 div r1); 2709662Slinton break; 2719662Slinton 2729662Slinton case O_MOD: 2739662Slinton if (r1 == 0) { 2749662Slinton error("error: mod by 0"); 2759662Slinton } 2769662Slinton push(long, r0 mod r1); 2779662Slinton break; 2789662Slinton 2799662Slinton case O_LT: 2809662Slinton push(Boolrep, r0 < r1); 2819662Slinton break; 2829662Slinton 2839662Slinton case O_LTF: 2849662Slinton push(Boolrep, fr0 < fr1); 2859662Slinton break; 2869662Slinton 2879662Slinton case O_LE: 2889662Slinton push(Boolrep, r0 <= r1); 2899662Slinton break; 2909662Slinton 2919662Slinton case O_LEF: 2929662Slinton push(Boolrep, fr0 <= fr1); 2939662Slinton break; 2949662Slinton 2959662Slinton case O_GT: 2969662Slinton push(Boolrep, r0 > r1); 2979662Slinton break; 2989662Slinton 2999662Slinton case O_GTF: 3009662Slinton push(Boolrep, fr0 > fr1); 3019662Slinton break; 3029662Slinton 3039662Slinton case O_EQ: 3049662Slinton push(Boolrep, r0 == r1); 3059662Slinton break; 3069662Slinton 3079662Slinton case O_EQF: 3089662Slinton push(Boolrep, fr0 == fr1); 3099662Slinton break; 3109662Slinton 3119662Slinton case O_NE: 3129662Slinton push(Boolrep, r0 != r1); 3139662Slinton break; 3149662Slinton 3159662Slinton case O_NEF: 3169662Slinton push(Boolrep, fr0 != fr1); 3179662Slinton break; 3189662Slinton 3199662Slinton case O_AND: 3209662Slinton push(Boolrep, r0 and r1); 3219662Slinton break; 3229662Slinton 3239662Slinton case O_OR: 3249662Slinton push(Boolrep, r0 or r1); 3259662Slinton break; 3269662Slinton 3279662Slinton case O_ASSIGN: 3289662Slinton assign(p->value.arg[0], p->value.arg[1]); 3299662Slinton break; 3309662Slinton 3319662Slinton case O_CHFILE: 3329662Slinton if (p->value.scon == nil) { 3339662Slinton printf("%s\n", cursource); 3349662Slinton } else { 3359662Slinton file = opensource(p->value.scon); 3369662Slinton if (file == nil) { 3379662Slinton error("can't read \"%s\"", p->value.scon); 3389662Slinton } else { 3399662Slinton fclose(file); 3409662Slinton setsource(p->value.scon); 3419662Slinton } 3429662Slinton } 3439662Slinton break; 3449662Slinton 3459662Slinton case O_CONT: 34611871Slinton cont(p->value.lcon); 3479662Slinton printnews(); 3489662Slinton break; 3499662Slinton 3509662Slinton case O_LIST: 35118217Slinton list(p); 3529662Slinton break; 3539662Slinton 3549662Slinton case O_FUNC: 35518217Slinton func(p->value.arg[0]); 3569662Slinton break; 3579662Slinton 3589662Slinton case O_EXAMINE: 3599662Slinton eval(p->value.examine.beginaddr); 3609662Slinton r0 = pop(long); 3619662Slinton if (p->value.examine.endaddr == nil) { 3629662Slinton n = p->value.examine.count; 36311175Slinton if (n == 0) { 36411175Slinton printvalue(r0, p->value.examine.mode); 36511175Slinton } else if (streq(p->value.examine.mode, "i")) { 3669662Slinton printninst(n, (Address) r0); 3679662Slinton } else { 3689662Slinton printndata(n, (Address) r0, p->value.examine.mode); 3699662Slinton } 3709662Slinton } else { 3719662Slinton eval(p->value.examine.endaddr); 3729662Slinton r1 = pop(long); 3739662Slinton if (streq(p->value.examine.mode, "i")) { 3749662Slinton printinst((Address)r0, (Address)r1); 3759662Slinton } else { 3769662Slinton printdata((Address)r0, (Address)r1, p->value.examine.mode); 3779662Slinton } 3789662Slinton } 3799662Slinton break; 3809662Slinton 3819662Slinton case O_PRINT: 3829662Slinton for (n1 = p->value.arg[0]; n1 != nil; n1 = n1->value.arg[1]) { 3839662Slinton eval(n1->value.arg[0]); 3849662Slinton printval(n1->value.arg[0]->nodetype); 3859662Slinton putchar(' '); 3869662Slinton } 3879662Slinton putchar('\n'); 3889662Slinton break; 3899662Slinton 3909662Slinton case O_PSYM: 3919662Slinton if (p->value.arg[0]->op == O_SYM) { 3929662Slinton psym(p->value.arg[0]->value.sym); 3939662Slinton } else { 3949662Slinton psym(p->value.arg[0]->nodetype); 3959662Slinton } 3969662Slinton break; 3979662Slinton 3989662Slinton case O_QLINE: 3999662Slinton eval(p->value.arg[1]); 4009662Slinton break; 4019662Slinton 4029662Slinton case O_STEP: 4039662Slinton b = inst_tracing; 4049662Slinton inst_tracing = (Boolean) (not p->value.step.source); 4059662Slinton if (p->value.step.skipcalls) { 4069662Slinton next(); 4079662Slinton } else { 4089662Slinton stepc(); 4099662Slinton } 4109662Slinton inst_tracing = b; 41114674Slinton useInstLoc = (Boolean) (not p->value.step.source); 4129662Slinton printnews(); 4139662Slinton break; 4149662Slinton 4159662Slinton case O_WHATIS: 4169662Slinton if (p->value.arg[0]->op == O_SYM) { 4179662Slinton printdecl(p->value.arg[0]->value.sym); 4189662Slinton } else { 4199662Slinton printdecl(p->value.arg[0]->nodetype); 4209662Slinton } 4219662Slinton break; 4229662Slinton 4239662Slinton case O_WHERE: 4249662Slinton wherecmd(); 4259662Slinton break; 4269662Slinton 4279662Slinton case O_WHEREIS: 42812538Scsvaf if (p->value.arg[0]->op == O_SYM) { 42918217Slinton printwhereis(stdout, p->value.arg[0]->value.sym); 43012538Scsvaf } else { 43118217Slinton printwhereis(stdout, p->value.arg[0]->nodetype); 43212538Scsvaf } 4339662Slinton break; 4349662Slinton 4359662Slinton case O_WHICH: 43612538Scsvaf if (p->value.arg[0]->op == O_SYM) { 43718217Slinton printwhich(stdout, p->value.arg[0]->value.sym); 43812538Scsvaf } else { 43918217Slinton printwhich(stdout, p->value.arg[0]->nodetype); 44012538Scsvaf } 4419662Slinton putchar('\n'); 4429662Slinton break; 4439662Slinton 4449662Slinton case O_ALIAS: 4459662Slinton n1 = p->value.arg[0]; 4469662Slinton n2 = p->value.arg[1]; 44718217Slinton if (n2 == nil) { 44818217Slinton if (n1 == nil) { 44918217Slinton alias(nil, nil, nil); 45018217Slinton } else { 45118217Slinton alias(n1->value.name, nil, nil); 45218217Slinton } 45318217Slinton } else if (n2->op == O_NAME) { 45418217Slinton str = ident(n2->value.name); 45518217Slinton alias(n1->value.name, nil, strdup(str)); 4569662Slinton } else { 45718217Slinton if (n1->op == O_COMMA) { 45818217Slinton alias( 45918217Slinton n1->value.arg[0]->value.name, 46018217Slinton (List) n1->value.arg[1], 46118217Slinton n2->value.scon 46218217Slinton ); 46318217Slinton } else { 46418217Slinton alias(n1->value.name, nil, n2->value.scon); 46518217Slinton } 4669662Slinton } 4679662Slinton break; 4689662Slinton 46918217Slinton case O_UNALIAS: 47018217Slinton unalias(p->value.arg[0]->value.name); 47118217Slinton break; 47218217Slinton 47318217Slinton case O_CALLPROC: 47418217Slinton callproc(p, false); 47518217Slinton break; 47618217Slinton 4779662Slinton case O_CALL: 47818217Slinton callproc(p, true); 4799662Slinton break; 4809662Slinton 4819662Slinton case O_CATCH: 48218217Slinton if (p->value.lcon == 0) { 48318217Slinton printsigscaught(process); 48418217Slinton } else { 48518217Slinton psigtrace(process, p->value.lcon, true); 48618217Slinton } 4879662Slinton break; 4889662Slinton 4899662Slinton case O_EDIT: 4909662Slinton edit(p->value.scon); 4919662Slinton break; 4929662Slinton 49312538Scsvaf case O_DEBUG: 49412538Scsvaf debug(p); 49512538Scsvaf break; 49612538Scsvaf 49716608Ssam case O_DOWN: 49816608Ssam checkref(p->value.arg[0]); 49916608Ssam assert(p->value.arg[0]->op == O_LCON); 50016608Ssam down(p->value.arg[0]->value.lcon); 50116608Ssam break; 50216608Ssam 5039662Slinton case O_DUMP: 50418217Slinton if (p->value.arg[0] == nil) { 50518217Slinton dumpall(); 50618217Slinton } else { 50718217Slinton s = p->value.arg[0]->value.sym; 50818217Slinton if (s == curfunc) { 50918217Slinton dump(nil); 51018217Slinton } else { 51118217Slinton dump(s); 51218217Slinton } 51318217Slinton } 5149662Slinton break; 5159662Slinton 5169662Slinton case O_GRIPE: 5179662Slinton gripe(); 5189662Slinton break; 5199662Slinton 5209662Slinton case O_HELP: 5219662Slinton help(); 5229662Slinton break; 5239662Slinton 5249662Slinton case O_IGNORE: 52518217Slinton if (p->value.lcon == 0) { 52618217Slinton printsigsignored(process); 52718217Slinton } else { 52818217Slinton psigtrace(process, p->value.lcon, false); 52918217Slinton } 5309662Slinton break; 5319662Slinton 53216608Ssam case O_RETURN: 53316608Ssam if (p->value.arg[0] == nil) { 53416608Ssam rtnfunc(nil); 53516608Ssam } else { 53616608Ssam assert(p->value.arg[0]->op == O_SYM); 53716608Ssam rtnfunc(p->value.arg[0]->value.sym); 53816608Ssam } 53916608Ssam break; 54016608Ssam 5419662Slinton case O_RUN: 5429662Slinton run(); 5439662Slinton break; 5449662Slinton 54518217Slinton case O_SET: 54618217Slinton set(p->value.arg[0], p->value.arg[1]); 54718217Slinton break; 54818217Slinton 54918217Slinton case O_SEARCH: 55018217Slinton search(p->value.arg[0]->value.lcon, p->value.arg[1]->value.scon); 55118217Slinton break; 55218217Slinton 5539662Slinton case O_SOURCE: 5549662Slinton setinput(p->value.scon); 5559662Slinton break; 5569662Slinton 5579662Slinton case O_STATUS: 5589662Slinton status(); 5599662Slinton break; 5609662Slinton 5619662Slinton case O_TRACE: 5629662Slinton case O_TRACEI: 5639662Slinton trace(p); 5649662Slinton break; 5659662Slinton 5669662Slinton case O_STOP: 5679662Slinton case O_STOPI: 5689662Slinton stop(p); 5699662Slinton break; 5709662Slinton 57118217Slinton case O_UNSET: 57218217Slinton undefvar(p->value.arg[0]->value.name); 57318217Slinton break; 57418217Slinton 57516608Ssam case O_UP: 57616608Ssam checkref(p->value.arg[0]); 57716608Ssam assert(p->value.arg[0]->op == O_LCON); 57816608Ssam up(p->value.arg[0]->value.lcon); 57916608Ssam break; 58016608Ssam 5819662Slinton case O_ADDEVENT: 5829662Slinton addevent(p->value.event.cond, p->value.event.actions); 5839662Slinton break; 5849662Slinton 5859662Slinton case O_DELETE: 58616608Ssam n1 = p->value.arg[0]; 58716608Ssam while (n1->op == O_COMMA) { 58816608Ssam n2 = n1->value.arg[0]; 58916608Ssam assert(n2->op == O_LCON); 59016608Ssam if (not delevent((unsigned int) n2->value.lcon)) { 59116608Ssam error("unknown event %ld", n2->value.lcon); 59216608Ssam } 59316608Ssam n1 = n1->value.arg[1]; 59416608Ssam } 59516608Ssam assert(n1->op == O_LCON); 59616608Ssam if (not delevent((unsigned int) n1->value.lcon)) { 59716608Ssam error("unknown event %ld", n1->value.lcon); 59816608Ssam } 5999662Slinton break; 6009662Slinton 6019662Slinton case O_ENDX: 6029662Slinton endprogram(); 6039662Slinton break; 6049662Slinton 6059662Slinton case O_IF: 6069662Slinton if (cond(p->value.event.cond)) { 6079662Slinton evalcmdlist(p->value.event.actions); 6089662Slinton } 6099662Slinton break; 6109662Slinton 6119662Slinton case O_ONCE: 6129662Slinton event_once(p->value.event.cond, p->value.event.actions); 6139662Slinton break; 6149662Slinton 6159662Slinton case O_PRINTCALL: 6169662Slinton printcall(p->value.sym, whatblock(return_addr())); 6179662Slinton break; 6189662Slinton 6199662Slinton case O_PRINTIFCHANGED: 6209662Slinton printifchanged(p->value.arg[0]); 6219662Slinton break; 6229662Slinton 6239662Slinton case O_PRINTRTN: 6249662Slinton printrtn(p->value.sym); 6259662Slinton break; 6269662Slinton 6279662Slinton case O_PRINTSRCPOS: 6289662Slinton getsrcpos(); 6299662Slinton if (p->value.arg[0] == nil) { 6309662Slinton printsrcpos(); 6319662Slinton putchar('\n'); 6329662Slinton printlines(curline, curline); 6339662Slinton } else if (p->value.arg[0]->op == O_QLINE) { 6349662Slinton if (p->value.arg[0]->value.arg[1]->value.lcon == 0) { 6359662Slinton printf("tracei: "); 6369662Slinton printinst(pc, pc); 6379662Slinton } else { 63818217Slinton if (canReadSource()) { 63918217Slinton printf("trace: "); 64018217Slinton printlines(curline, curline); 64118217Slinton } 6429662Slinton } 6439662Slinton } else { 6449662Slinton printsrcpos(); 6459662Slinton printf(": "); 6469662Slinton eval(p->value.arg[0]); 6479662Slinton prtree(stdout, p->value.arg[0]); 6489662Slinton printf(" = "); 6499662Slinton printval(p->value.arg[0]->nodetype); 6509662Slinton putchar('\n'); 6519662Slinton } 6529662Slinton break; 6539662Slinton 6549662Slinton case O_PROCRTN: 6559662Slinton procreturn(p->value.sym); 6569662Slinton break; 6579662Slinton 6589662Slinton case O_STOPIFCHANGED: 6599662Slinton stopifchanged(p->value.arg[0]); 6609662Slinton break; 6619662Slinton 6629662Slinton case O_STOPX: 6639662Slinton isstopped = true; 6649662Slinton break; 6659662Slinton 6669662Slinton case O_TRACEON: 6679662Slinton traceon(p->value.trace.inst, p->value.trace.event, 6689662Slinton p->value.trace.actions); 6699662Slinton break; 6709662Slinton 6719662Slinton case O_TRACEOFF: 6729662Slinton traceoff(p->value.lcon); 6739662Slinton break; 6749662Slinton 6759662Slinton default: 6769662Slinton panic("eval: bad op %d", p->op); 6779662Slinton } 67818217Slinton if (traceeval) { 67918217Slinton fprintf(stderr, "end eval %s\n", opname(p->op)); 68018217Slinton } 6819662Slinton } 6829662Slinton 6839662Slinton /* 6849662Slinton * Evaluate a list of commands. 6859662Slinton */ 6869662Slinton 6879662Slinton public evalcmdlist(cl) 6889662Slinton Cmdlist cl; 6899662Slinton { 6909662Slinton Command c; 6919662Slinton 6929662Slinton foreach (Command, c, cl) 6939662Slinton evalcmd(c); 6949662Slinton endfor 6959662Slinton } 6969662Slinton 6979662Slinton /* 6989662Slinton * Push "len" bytes onto the expression stack from address "addr" 6999662Slinton * in the process. If there isn't room on the stack, print an error message. 7009662Slinton */ 7019662Slinton 7029662Slinton public rpush(addr, len) 7039662Slinton Address addr; 7049662Slinton int len; 7059662Slinton { 7069662Slinton if (not canpush(len)) { 7079662Slinton error("expression too large to evaluate"); 7089662Slinton } else { 7099662Slinton chksp(); 7109662Slinton dread(sp, addr, len); 7119662Slinton sp += len; 7129662Slinton } 7139662Slinton } 7149662Slinton 7159662Slinton /* 7169662Slinton * Check if the stack has n bytes available. 7179662Slinton */ 7189662Slinton 7199662Slinton public Boolean canpush(n) 7209662Slinton Integer n; 7219662Slinton { 7229662Slinton return (Boolean) (sp + n < &stack[STACKSIZE]); 7239662Slinton } 7249662Slinton 7259662Slinton /* 7269662Slinton * Push a small scalar of the given type onto the stack. 7279662Slinton */ 7289662Slinton 7299662Slinton public pushsmall(t, v) 7309662Slinton Symbol t; 7319662Slinton long v; 7329662Slinton { 7339662Slinton register Integer s; 7349662Slinton 7359662Slinton s = size(t); 7369662Slinton switch (s) { 7379662Slinton case sizeof(char): 7389662Slinton push(char, v); 7399662Slinton break; 7409662Slinton 7419662Slinton case sizeof(short): 7429662Slinton push(short, v); 7439662Slinton break; 7449662Slinton 7459662Slinton case sizeof(long): 7469662Slinton push(long, v); 7479662Slinton break; 7489662Slinton 7499662Slinton default: 7509662Slinton panic("bad size %d in popsmall", s); 7519662Slinton } 7529662Slinton } 7539662Slinton 7549662Slinton /* 7559662Slinton * Pop an item of the given type which is assumed to be no larger 7569662Slinton * than a long and return it expanded into a long. 7579662Slinton */ 7589662Slinton 7599662Slinton public long popsmall(t) 7609662Slinton Symbol t; 7619662Slinton { 76218217Slinton register integer n; 7639662Slinton long r; 7649662Slinton 76518217Slinton n = size(t); 76618217Slinton if (n == sizeof(char)) { 76718217Slinton if (t->class == RANGE and t->symvalue.rangev.lower >= 0) { 76818217Slinton r = (long) pop(unsigned char); 76918217Slinton } else { 7709662Slinton r = (long) pop(char); 77118217Slinton } 77218217Slinton } else if (n == sizeof(short)) { 77318217Slinton if (t->class == RANGE and t->symvalue.rangev.lower >= 0) { 77418217Slinton r = (long) pop(unsigned short); 77518217Slinton } else { 7769662Slinton r = (long) pop(short); 77718217Slinton } 77818217Slinton } else if (n == sizeof(long)) { 77918217Slinton r = pop(long); 78018217Slinton } else { 78118217Slinton error("[internal error: size %d in popsmall]", n); 7829662Slinton } 7839662Slinton return r; 7849662Slinton } 7859662Slinton 7869662Slinton /* 7879662Slinton * Evaluate a conditional expression. 7889662Slinton */ 7899662Slinton 7909662Slinton public Boolean cond(p) 7919662Slinton Node p; 7929662Slinton { 793*33315Sdonn Boolean b; 794*33315Sdonn int i; 7959662Slinton 7969662Slinton if (p == nil) { 7979662Slinton b = true; 7989662Slinton } else { 7999662Slinton eval(p); 800*33315Sdonn i = pop(Boolrep); 801*33315Sdonn b = (Boolean) i; 8029662Slinton } 8039662Slinton return b; 8049662Slinton } 8059662Slinton 8069662Slinton /* 8079662Slinton * Return the address corresponding to a given tree. 8089662Slinton */ 8099662Slinton 8109662Slinton public Address lval(p) 8119662Slinton Node p; 8129662Slinton { 8139662Slinton if (p->op == O_RVAL) { 8149662Slinton eval(p->value.arg[0]); 8159662Slinton } else { 8169662Slinton eval(p); 8179662Slinton } 8189662Slinton return (Address) (pop(long)); 8199662Slinton } 8209662Slinton 8219662Slinton /* 8229662Slinton * Process a trace command, translating into the appropriate events 8239662Slinton * and associated actions. 8249662Slinton */ 8259662Slinton 8269662Slinton public trace(p) 8279662Slinton Node p; 8289662Slinton { 8299662Slinton Node exp, place, cond; 8309662Slinton Node left; 8319662Slinton 8329662Slinton exp = p->value.arg[0]; 8339662Slinton place = p->value.arg[1]; 8349662Slinton cond = p->value.arg[2]; 8359662Slinton if (exp == nil) { 8369662Slinton traceall(p->op, place, cond); 83711771Slinton } else if (exp->op == O_QLINE or exp->op == O_LCON) { 8389662Slinton traceinst(p->op, exp, cond); 8399662Slinton } else if (place != nil and place->op == O_QLINE) { 8409662Slinton traceat(p->op, exp, place, cond); 8419662Slinton } else { 8429861Slinton left = exp; 8439861Slinton if (left->op == O_RVAL or left->op == O_CALL) { 8449861Slinton left = left->value.arg[0]; 8459861Slinton } 8469662Slinton if (left->op == O_SYM and isblock(left->value.sym)) { 8479662Slinton traceproc(p->op, left->value.sym, place, cond); 8489662Slinton } else { 8499662Slinton tracedata(p->op, exp, place, cond); 8509662Slinton } 8519662Slinton } 8529662Slinton } 8539662Slinton 8549662Slinton /* 8559662Slinton * Set a breakpoint that will turn on tracing. 8569662Slinton */ 8579662Slinton 8589662Slinton private traceall(op, place, cond) 8599662Slinton Operator op; 8609662Slinton Node place; 8619662Slinton Node cond; 8629662Slinton { 8639662Slinton Symbol s; 8649662Slinton Node event; 8659662Slinton Command action; 8669662Slinton 8679662Slinton if (place == nil) { 8689662Slinton s = program; 8699662Slinton } else { 8709662Slinton s = place->value.sym; 8719662Slinton } 8729662Slinton event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s)); 8739662Slinton action = build(O_PRINTSRCPOS, 8749662Slinton build(O_QLINE, nil, build(O_LCON, (op == O_TRACE) ? 1 : 0))); 8759662Slinton if (cond != nil) { 8769662Slinton action = build(O_IF, cond, buildcmdlist(action)); 8779662Slinton } 8789662Slinton action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action)); 8799662Slinton action->value.trace.event = addevent(event, buildcmdlist(action)); 88011871Slinton if (isstdin()) { 88111871Slinton printevent(action->value.trace.event); 88211871Slinton } 8839662Slinton } 8849662Slinton 8859662Slinton /* 8869662Slinton * Set up the appropriate breakpoint for tracing an instruction. 8879662Slinton */ 8889662Slinton 8899662Slinton private traceinst(op, exp, cond) 8909662Slinton Operator op; 8919662Slinton Node exp; 8929662Slinton Node cond; 8939662Slinton { 89411771Slinton Node event, wh; 8959662Slinton Command action; 89611871Slinton Event e; 8979662Slinton 89811771Slinton if (exp->op == O_LCON) { 89918217Slinton wh = build(O_QLINE, build(O_SCON, strdup(cursource)), exp); 90011771Slinton } else { 90111771Slinton wh = exp; 90211771Slinton } 9039662Slinton if (op == O_TRACEI) { 90411771Slinton event = build(O_EQ, build(O_SYM, pcsym), wh); 9059662Slinton } else { 90611771Slinton event = build(O_EQ, build(O_SYM, linesym), wh); 9079662Slinton } 90811771Slinton action = build(O_PRINTSRCPOS, wh); 9099662Slinton if (cond) { 9109662Slinton action = build(O_IF, cond, buildcmdlist(action)); 9119662Slinton } 91211871Slinton e = addevent(event, buildcmdlist(action)); 91311871Slinton if (isstdin()) { 91411871Slinton printevent(e); 91511871Slinton } 9169662Slinton } 9179662Slinton 9189662Slinton /* 9199662Slinton * Set a breakpoint to print an expression at a given line or address. 9209662Slinton */ 9219662Slinton 9229662Slinton private traceat(op, exp, place, cond) 9239662Slinton Operator op; 9249662Slinton Node exp; 9259662Slinton Node place; 9269662Slinton Node cond; 9279662Slinton { 9289662Slinton Node event; 9299662Slinton Command action; 93011871Slinton Event e; 9319662Slinton 9329662Slinton if (op == O_TRACEI) { 9339662Slinton event = build(O_EQ, build(O_SYM, pcsym), place); 9349662Slinton } else { 9359662Slinton event = build(O_EQ, build(O_SYM, linesym), place); 9369662Slinton } 9379662Slinton action = build(O_PRINTSRCPOS, exp); 9389662Slinton if (cond != nil) { 9399662Slinton action = build(O_IF, cond, buildcmdlist(action)); 9409662Slinton } 94111871Slinton e = addevent(event, buildcmdlist(action)); 94211871Slinton if (isstdin()) { 94311871Slinton printevent(e); 94411871Slinton } 9459662Slinton } 9469662Slinton 9479662Slinton /* 9489662Slinton * Construct event for tracing a procedure. 9499662Slinton * 9509662Slinton * What we want here is 9519662Slinton * 9529662Slinton * when $proc = p do 9539662Slinton * if <condition> then 9549662Slinton * printcall; 9559662Slinton * once $pc = $retaddr do 9569662Slinton * printrtn; 9579662Slinton * end; 9589662Slinton * end if; 9599662Slinton * end; 9609662Slinton * 9619662Slinton * Note that "once" is like "when" except that the event 9629662Slinton * deletes itself as part of its associated action. 9639662Slinton */ 9649662Slinton 9659662Slinton private traceproc(op, p, place, cond) 9669662Slinton Operator op; 9679662Slinton Symbol p; 9689662Slinton Node place; 9699662Slinton Node cond; 9709662Slinton { 9719662Slinton Node event; 9729662Slinton Command action; 9739662Slinton Cmdlist actionlist; 97411871Slinton Event e; 9759662Slinton 9769662Slinton action = build(O_PRINTCALL, p); 9779662Slinton actionlist = list_alloc(); 9789662Slinton cmdlist_append(action, actionlist); 9799662Slinton event = build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)); 9809662Slinton action = build(O_ONCE, event, buildcmdlist(build(O_PRINTRTN, p))); 9819662Slinton cmdlist_append(action, actionlist); 9829662Slinton if (cond != nil) { 9839662Slinton actionlist = buildcmdlist(build(O_IF, cond, actionlist)); 9849662Slinton } 9859662Slinton event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p)); 98611871Slinton e = addevent(event, actionlist); 98711871Slinton if (isstdin()) { 98811871Slinton printevent(e); 98911871Slinton } 9909662Slinton } 9919662Slinton 9929662Slinton /* 9939662Slinton * Set up breakpoint for tracing data. 9949662Slinton */ 9959662Slinton 9969662Slinton private tracedata(op, exp, place, cond) 9979662Slinton Operator op; 9989662Slinton Node exp; 9999662Slinton Node place; 10009662Slinton Node cond; 10019662Slinton { 10029662Slinton Symbol p; 10039662Slinton Node event; 10049662Slinton Command action; 10059662Slinton 1006*33315Sdonn if (size(exp->nodetype) > MAXTRSIZE) { 1007*33315Sdonn error("expression too large to trace (limit is %d bytes)", MAXTRSIZE); 1008*33315Sdonn } 10099662Slinton p = (place == nil) ? tcontainer(exp) : place->value.sym; 10109662Slinton if (p == nil) { 10119662Slinton p = program; 10129662Slinton } 10139662Slinton action = build(O_PRINTIFCHANGED, exp); 10149662Slinton if (cond != nil) { 10159662Slinton action = build(O_IF, cond, buildcmdlist(action)); 10169662Slinton } 10179662Slinton action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action)); 10189662Slinton event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p)); 10199662Slinton action->value.trace.event = addevent(event, buildcmdlist(action)); 102011871Slinton if (isstdin()) { 102111871Slinton printevent(action->value.trace.event); 102211871Slinton } 10239662Slinton } 10249662Slinton 10259662Slinton /* 10269662Slinton * Setting and unsetting of stops. 10279662Slinton */ 10289662Slinton 10299662Slinton public stop(p) 10309662Slinton Node p; 10319662Slinton { 103213846Slinton Node exp, place, cond, t; 10339662Slinton Symbol s; 10349662Slinton Command action; 103511871Slinton Event e; 10369662Slinton 10379662Slinton exp = p->value.arg[0]; 10389662Slinton place = p->value.arg[1]; 10399662Slinton cond = p->value.arg[2]; 10409662Slinton if (exp != nil) { 10419662Slinton stopvar(p->op, exp, place, cond); 104213846Slinton } else { 104313846Slinton action = build(O_STOPX); 104413846Slinton if (cond != nil) { 104513846Slinton action = build(O_IF, cond, buildcmdlist(action)); 104611871Slinton } 104716608Ssam if (place == nil or place->op == O_SYM) { 104816608Ssam if (place == nil) { 104916608Ssam s = program; 105016608Ssam } else { 105116608Ssam s = place->value.sym; 105216608Ssam } 105313846Slinton t = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s)); 105413846Slinton if (cond != nil) { 105513846Slinton action = build(O_TRACEON, (p->op == O_STOPI), 105613846Slinton buildcmdlist(action)); 105713846Slinton e = addevent(t, buildcmdlist(action)); 105813846Slinton action->value.trace.event = e; 105913846Slinton } else { 106013846Slinton e = addevent(t, buildcmdlist(action)); 106113846Slinton } 106213846Slinton if (isstdin()) { 106313846Slinton printevent(e); 106413846Slinton } 106513846Slinton } else { 106613846Slinton stopinst(p->op, place, cond, action); 106713846Slinton } 10689662Slinton } 10699662Slinton } 10709662Slinton 107113846Slinton private stopinst(op, place, cond, action) 10729662Slinton Operator op; 10739662Slinton Node place; 10749662Slinton Node cond; 107513846Slinton Command action; 10769662Slinton { 10779662Slinton Node event; 107811871Slinton Event e; 10799662Slinton 10809662Slinton if (op == O_STOP) { 10819662Slinton event = build(O_EQ, build(O_SYM, linesym), place); 10829662Slinton } else { 10839662Slinton event = build(O_EQ, build(O_SYM, pcsym), place); 10849662Slinton } 108513846Slinton e = addevent(event, buildcmdlist(action)); 108611871Slinton if (isstdin()) { 108711871Slinton printevent(e); 108811871Slinton } 10899662Slinton } 10909662Slinton 10919662Slinton /* 10929662Slinton * Implement stopping on assignment to a variable by adding it to 10939662Slinton * the variable list. 10949662Slinton */ 10959662Slinton 10969662Slinton private stopvar(op, exp, place, cond) 10979662Slinton Operator op; 10989662Slinton Node exp; 10999662Slinton Node place; 11009662Slinton Node cond; 11019662Slinton { 11029662Slinton Symbol p; 11039662Slinton Node event; 11049662Slinton Command action; 11059662Slinton 1106*33315Sdonn if (size(exp->nodetype) > MAXTRSIZE) { 1107*33315Sdonn error("expression too large to trace (limit is %d bytes)", MAXTRSIZE); 1108*33315Sdonn } 110914445Slinton if (place == nil) { 111014445Slinton if (exp->op == O_LCON) { 111114445Slinton p = program; 111214445Slinton } else { 111314445Slinton p = tcontainer(exp); 111414445Slinton if (p == nil) { 111514445Slinton p = program; 111614445Slinton } 111714445Slinton } 111814445Slinton } else { 111914445Slinton p = place->value.sym; 11209662Slinton } 112114445Slinton action = build(O_STOPIFCHANGED, exp); 112214445Slinton if (cond != nil) { 112314445Slinton action = build(O_IF, cond, buildcmdlist(action)); 112414445Slinton } 11259662Slinton action = build(O_TRACEON, (op == O_STOPI), buildcmdlist(action)); 11269662Slinton event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p)); 11279662Slinton action->value.trace.event = addevent(event, buildcmdlist(action)); 112811871Slinton if (isstdin()) { 112911871Slinton printevent(action->value.trace.event); 113011871Slinton } 11319662Slinton } 11329662Slinton 11339662Slinton /* 11349662Slinton * Assign the value of an expression to a variable (or term). 11359662Slinton */ 11369662Slinton 11379662Slinton public assign(var, exp) 11389662Slinton Node var; 11399662Slinton Node exp; 11409662Slinton { 11419662Slinton Address addr; 114216608Ssam integer varsize, expsize; 11439662Slinton char cvalue; 11449662Slinton short svalue; 11459662Slinton long lvalue; 114616608Ssam float fvalue; 11479662Slinton 114818217Slinton if (var->op == O_SYM and regnum(var->value.sym) != -1) { 114918217Slinton eval(exp); 115018217Slinton setreg(regnum(var->value.sym), pop(Address)); 115116608Ssam } else { 115218217Slinton addr = lval(var); 115318217Slinton varsize = size(var->nodetype); 115418217Slinton expsize = size(exp->nodetype); 115518217Slinton eval(exp); 115618217Slinton if (varsize == sizeof(float) and expsize == sizeof(double)) { 115718217Slinton fvalue = (float) pop(double); 115818217Slinton dwrite(&fvalue, addr, sizeof(fvalue)); 115918217Slinton } else { 116018217Slinton if (varsize < sizeof(long)) { 116118217Slinton lvalue = 0; 116218217Slinton popn(expsize, &lvalue); 116318217Slinton if (varsize == sizeof(char)) { 116416608Ssam cvalue = lvalue; 116516608Ssam dwrite(&cvalue, addr, sizeof(cvalue)); 116618217Slinton } else if (varsize == sizeof(short)) { 116716608Ssam svalue = lvalue; 116816608Ssam dwrite(&svalue, addr, sizeof(svalue)); 116918217Slinton } else { 117018217Slinton error("[internal error: bad size %d in assign]", varsize); 117118217Slinton } 117218217Slinton } else { 117318217Slinton if (expsize <= varsize) { 117418217Slinton sp -= expsize; 117518217Slinton dwrite(sp, addr, expsize); 117618217Slinton } else { 117718217Slinton sp -= expsize; 117818217Slinton dwrite(sp, addr, varsize); 117918217Slinton } 118018217Slinton } 118118217Slinton } 118218217Slinton } 118318217Slinton } 11849662Slinton 118518217Slinton /* 118618217Slinton * Set a debugger variable. 118718217Slinton */ 118818217Slinton 118918217Slinton private set (var, exp) 119018217Slinton Node var, exp; 119118217Slinton { 119218217Slinton Symbol t; 119318217Slinton 119418217Slinton if (var == nil) { 119518217Slinton defvar(nil, nil); 119618217Slinton } else if (exp == nil) { 119718217Slinton defvar(var->value.name, nil); 119818217Slinton } else if (var->value.name == identname("$frame", true)) { 119918217Slinton t = exp->nodetype; 120018217Slinton if (not compatible(t, t_int) and not compatible(t, t_addr)) { 120118217Slinton error("$frame must be an address"); 120218217Slinton } 120318217Slinton eval(exp); 120418217Slinton getnewregs(pop(Address)); 120518217Slinton } else { 120618217Slinton defvar(var->value.name, unrval(exp)); 120718217Slinton } 120818217Slinton } 120918217Slinton 121018217Slinton /* 121118217Slinton * Execute a list command. 121218217Slinton */ 121318217Slinton 121418217Slinton private list (p) 121518217Slinton Node p; 121618217Slinton { 121718217Slinton Symbol f; 121818217Slinton Address addr; 121918217Slinton Lineno line, l1, l2; 122018217Slinton 122118217Slinton if (p->value.arg[0]->op == O_SYM) { 122218217Slinton f = p->value.arg[0]->value.sym; 122318217Slinton addr = firstline(f); 122418217Slinton if (addr == NOADDR) { 122518217Slinton error("no source lines for \"%s\"", symname(f)); 122618217Slinton } 122718217Slinton setsource(srcfilename(addr)); 122818217Slinton line = srcline(addr); 122918217Slinton getsrcwindow(line, &l1, &l2); 123018217Slinton } else { 123118217Slinton eval(p->value.arg[0]); 123218217Slinton l1 = (Lineno) (pop(long)); 123318217Slinton eval(p->value.arg[1]); 123418217Slinton l2 = (Lineno) (pop(long)); 123518217Slinton } 123618217Slinton printlines(l1, l2); 123718217Slinton } 123818217Slinton 123918217Slinton /* 124018217Slinton * Execute a func command. 124118217Slinton */ 124218217Slinton 124318217Slinton private func (p) 124418217Slinton Node p; 124518217Slinton { 124618217Slinton Symbol s, f; 124718217Slinton Address addr; 124818217Slinton 124918217Slinton if (p == nil) { 125018217Slinton printname(stdout, curfunc); 125118217Slinton putchar('\n'); 125218217Slinton } else { 125318217Slinton s = p->value.sym; 125418217Slinton if (isroutine(s)) { 125518217Slinton setcurfunc(s); 125616608Ssam } else { 125718217Slinton find(f, s->name) where isroutine(f) endfind(f); 125818217Slinton if (f == nil) { 125918217Slinton error("%s is not a procedure or function", symname(s)); 126016608Ssam } 126118217Slinton setcurfunc(f); 12629662Slinton } 126318217Slinton addr = codeloc(curfunc); 126418217Slinton if (addr != NOADDR) { 126518217Slinton setsource(srcfilename(addr)); 126618217Slinton cursrcline = srcline(addr); 126718217Slinton } 12689662Slinton } 12699662Slinton } 12709662Slinton 12719662Slinton /* 127218217Slinton * Send a message to the current support person. 12739662Slinton */ 12749662Slinton 12759662Slinton public gripe() 12769662Slinton { 12779662Slinton typedef Operation(); 12789662Slinton Operation *old; 127914445Slinton int pid, status; 128016608Ssam extern int versionNumber; 128116608Ssam char subject[100]; 12829662Slinton 1283*33315Sdonn # ifdef MAINTAINER 1284*33315Sdonn puts("Type control-D to end your message. Be sure to include"); 1285*33315Sdonn puts("your name and the name of the file you are debugging."); 1286*33315Sdonn putchar('\n'); 1287*33315Sdonn old = signal(SIGINT, SIG_DFL); 1288*33315Sdonn sprintf(subject, "dbx (version 3.%d) gripe", versionNumber); 1289*33315Sdonn pid = back("Mail", stdin, stdout, "-s", subject, MAINTAINER, nil); 1290*33315Sdonn signal(SIGINT, SIG_IGN); 1291*33315Sdonn pwait(pid, &status); 1292*33315Sdonn signal(SIGINT, old); 1293*33315Sdonn if (status == 0) { 1294*33315Sdonn puts("Thank you."); 1295*33315Sdonn } else { 1296*33315Sdonn puts("\nMail not sent."); 1297*33315Sdonn } 1298*33315Sdonn # else 1299*33315Sdonn puts("Sorry, no dbx maintainer available to gripe to."); 1300*33315Sdonn puts("Try contacting your system manager."); 1301*33315Sdonn # endif 13029662Slinton } 13039662Slinton 13049662Slinton /* 13059662Slinton * Give the user some help. 13069662Slinton */ 13079662Slinton 13089662Slinton public help() 13099662Slinton { 13109662Slinton puts("run - begin execution of the program"); 131116608Ssam puts("print <exp> - print the value of the expression"); 131216608Ssam puts("where - print currently active procedures"); 131316608Ssam puts("stop at <line> - suspend execution at the line"); 131416608Ssam puts("stop in <proc> - suspend execution when <proc> is called"); 13159662Slinton puts("cont - continue execution"); 13169662Slinton puts("step - single step one line"); 13179662Slinton puts("next - step to next line (skip over calls)"); 13189662Slinton puts("trace <line#> - trace execution of the line"); 13199662Slinton puts("trace <proc> - trace calls to the procedure"); 13209662Slinton puts("trace <var> - trace changes to the variable"); 13219662Slinton puts("trace <exp> at <line#> - print <exp> when <line> is reached"); 13229662Slinton puts("status - print trace/stop's in effect"); 13239662Slinton puts("delete <number> - remove trace or stop of given number"); 132416608Ssam puts("call <proc> - call a procedure in program"); 13259662Slinton puts("whatis <name> - print the declaration of the name"); 13269662Slinton puts("list <line>, <line> - list source lines"); 13279662Slinton puts("gripe - send mail to the person in charge of dbx"); 13289662Slinton puts("quit - exit dbx"); 13299662Slinton } 13309662Slinton 13319662Slinton /* 13329662Slinton * Divert output to the given file name. 13339662Slinton * Cannot redirect to an existing file. 13349662Slinton */ 13359662Slinton 13369662Slinton private int so_fd; 13379662Slinton private Boolean notstdout; 13389662Slinton 13399662Slinton public setout(filename) 13409662Slinton String filename; 13419662Slinton { 13429662Slinton File f; 13439662Slinton 13449662Slinton f = fopen(filename, "r"); 13459662Slinton if (f != nil) { 13469662Slinton fclose(f); 13479662Slinton error("%s: file already exists", filename); 13489662Slinton } else { 13499662Slinton so_fd = dup(1); 13509662Slinton close(1); 13519662Slinton if (creat(filename, 0666) == nil) { 13529662Slinton unsetout(); 13539662Slinton error("can't create %s", filename); 13549662Slinton } 13559662Slinton notstdout = true; 13569662Slinton } 13579662Slinton } 13589662Slinton 13599662Slinton /* 13609662Slinton * Revert output to standard output. 13619662Slinton */ 13629662Slinton 13639662Slinton public unsetout() 13649662Slinton { 13659662Slinton fflush(stdout); 13669662Slinton close(1); 13679662Slinton if (dup(so_fd) != 1) { 13689662Slinton panic("standard out dup failed"); 13699662Slinton } 13709662Slinton close(so_fd); 13719662Slinton notstdout = false; 13729662Slinton } 13739662Slinton 13749662Slinton /* 13759662Slinton * Determine is standard output is currently being redirected 13769662Slinton * to a file (as far as we know). 13779662Slinton */ 13789662Slinton 13799662Slinton public Boolean isredirected() 13809662Slinton { 13819662Slinton return notstdout; 13829662Slinton } 1383