121601Sdist /*
238105Sbostic * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic * All rights reserved.
438105Sbostic *
5*42683Sbostic * %sccs.include.redist.c%
621601Sdist */
79662Slinton
821601Sdist #ifndef lint
9*42683Sbostic static char sccsid[] = "@(#)eval.c 5.7 (Berkeley) 06/01/90";
1038105Sbostic #endif /* not lint */
119662Slinton
129662Slinton /*
139662Slinton * Tree evaluation.
149662Slinton */
159662Slinton
169662Slinton #include "defs.h"
179662Slinton #include "tree.h"
189662Slinton #include "operators.h"
1918217Slinton #include "debug.h"
209662Slinton #include "eval.h"
219662Slinton #include "events.h"
229662Slinton #include "symbols.h"
239662Slinton #include "scanner.h"
249662Slinton #include "source.h"
259662Slinton #include "object.h"
269662Slinton #include "mappings.h"
279662Slinton #include "process.h"
2816608Ssam #include "runtime.h"
299662Slinton #include "machine.h"
309662Slinton #include <signal.h>
319662Slinton
329662Slinton #ifndef public
339662Slinton
349662Slinton #include "machine.h"
359662Slinton
3612538Scsvaf #define STACKSIZE 20000
379662Slinton
389662Slinton typedef Char Stack;
399662Slinton
409662Slinton #define push(type, value) { \
419662Slinton ((type *) (sp += sizeof(type)))[-1] = (value); \
429662Slinton }
439662Slinton
449662Slinton #define pop(type) ( \
459662Slinton (*((type *) (sp -= sizeof(type)))) \
469662Slinton )
479662Slinton
4816608Ssam #define popn(n, dest) { \
4916608Ssam sp -= n; \
5016608Ssam bcopy(sp, dest, n); \
5116608Ssam }
5216608Ssam
539662Slinton #define alignstack() { \
549662Slinton sp = (Stack *) (( ((int) sp) + sizeof(int) - 1)&~(sizeof(int) - 1)); \
559662Slinton }
569662Slinton
579662Slinton #endif
589662Slinton
599662Slinton public Stack stack[STACKSIZE];
609662Slinton public Stack *sp = &stack[0];
6114674Slinton public Boolean useInstLoc = false;
629662Slinton
639662Slinton #define chksp() \
649662Slinton { \
659662Slinton if (sp < &stack[0]) { \
669662Slinton panic("stack underflow"); \
679662Slinton } \
689662Slinton }
699662Slinton
709662Slinton #define poparg(n, r, fr) { \
719662Slinton eval(p->value.arg[n]); \
729662Slinton if (isreal(p->op)) { \
7316608Ssam if (size(p->value.arg[n]->nodetype) == sizeof(float)) { \
7416608Ssam fr = pop(float); \
7516608Ssam } else { \
7616608Ssam fr = pop(double); \
7716608Ssam } \
789662Slinton } else if (isint(p->op)) { \
799662Slinton r = popsmall(p->value.arg[n]->nodetype); \
809662Slinton } \
819662Slinton }
829662Slinton
839662Slinton #define Boolrep char /* underlying representation type for booleans */
849662Slinton
859662Slinton /*
8618217Slinton * Command-level evaluation.
8718217Slinton */
8818217Slinton
8918217Slinton public Node topnode;
9018217Slinton
topeval(p)9118217Slinton public topeval (p)
9218217Slinton Node p;
9318217Slinton {
9418217Slinton if (traceeval) {
9518217Slinton fprintf(stderr, "topeval(");
9618217Slinton prtree(stderr, p);
9718217Slinton fprintf(stderr, ")\n");
9818217Slinton fflush(stderr);
9918217Slinton }
10018217Slinton topnode = p;
10118217Slinton eval(p);
10218217Slinton }
10318217Slinton
10418217Slinton /*
1059662Slinton * Evaluate a parse tree leaving the value on the top of the stack.
1069662Slinton */
1079662Slinton
eval(p)1089662Slinton public eval(p)
1099662Slinton register Node p;
1109662Slinton {
1119662Slinton long r0, r1;
1129662Slinton double fr0, fr1;
1139662Slinton Address addr;
1149662Slinton long i, n;
1159662Slinton int len;
11618217Slinton Symbol s;
1179662Slinton Node n1, n2;
11818217Slinton boolean b;
1199662Slinton File file;
12018217Slinton String str;
1219662Slinton
1229662Slinton checkref(p);
12318217Slinton if (traceeval) {
12418217Slinton fprintf(stderr, "begin eval %s\n", opname(p->op));
12512538Scsvaf }
1269662Slinton switch (degree(p->op)) {
1279662Slinton case BINARY:
1289662Slinton poparg(1, r1, fr1);
1299662Slinton poparg(0, r0, fr0);
1309662Slinton break;
1319662Slinton
1329662Slinton case UNARY:
1339662Slinton poparg(0, r0, fr0);
1349662Slinton break;
1359662Slinton
1369662Slinton default:
1379662Slinton /* do nothing */;
1389662Slinton }
1399662Slinton switch (p->op) {
1409662Slinton case O_SYM:
1419662Slinton s = p->value.sym;
1429662Slinton if (s == retaddrsym) {
1439662Slinton push(long, return_addr());
14418217Slinton } else if (isvariable(s)) {
14518217Slinton if (s != program and not isactive(container(s))) {
14618217Slinton error("\"%s\" is not active", symname(s));
14718217Slinton }
14818217Slinton if (isvarparam(s) and not isopenarray(s)) {
14918217Slinton rpush(address(s, nil), sizeof(Address));
1509662Slinton } else {
15118217Slinton push(Address, address(s, nil));
1529662Slinton }
15318217Slinton } else if (isblock(s)) {
15418217Slinton push(Symbol, s);
15518217Slinton } else if (isconst(s)) {
15618217Slinton eval(constval(s));
15718217Slinton } else {
15818217Slinton error("can't evaluate a %s", classname(s));
1599662Slinton }
1609662Slinton break;
1619662Slinton
1629662Slinton case O_LCON:
16318217Slinton case O_CCON:
1649662Slinton r0 = p->value.lcon;
1659662Slinton pushsmall(p->nodetype, r0);
1669662Slinton break;
1679662Slinton
1689662Slinton case O_FCON:
1699662Slinton push(double, p->value.fcon);
1709662Slinton break;
1719662Slinton
1729662Slinton case O_SCON:
1739662Slinton len = size(p->nodetype);
1749662Slinton mov(p->value.scon, sp, len);
1759662Slinton sp += len;
1769662Slinton break;
1779662Slinton
1789662Slinton case O_INDEX:
17918217Slinton s = p->value.arg[0]->nodetype;
18018217Slinton p->value.arg[0]->nodetype = t_addr;
18118217Slinton eval(p->value.arg[0]);
18218217Slinton p->value.arg[0]->nodetype = s;
18318217Slinton n = pop(Address);
18418217Slinton eval(p->value.arg[1]);
18518217Slinton evalindex(s, n, popsmall(p->value.arg[1]->nodetype));
1869662Slinton break;
1879662Slinton
1889662Slinton case O_DOT:
1899662Slinton s = p->value.arg[1]->value.sym;
19018217Slinton eval(p->value.arg[0]);
19118217Slinton n = pop(long);
1929662Slinton push(long, n + (s->symvalue.field.offset div 8));
1939662Slinton break;
1949662Slinton
1959662Slinton /*
1969662Slinton * Get the value of the expression addressed by the top of the stack.
1979662Slinton * Push the result back on the stack.
1989662Slinton */
1999662Slinton
2009662Slinton case O_INDIR:
2019662Slinton case O_RVAL:
2029662Slinton addr = pop(long);
2039662Slinton if (addr == 0) {
2049662Slinton error("reference through nil pointer");
2059662Slinton }
20618217Slinton len = size(p->nodetype);
2079662Slinton rpush(addr, len);
2089662Slinton break;
2099662Slinton
21011175Slinton case O_TYPERENAME:
21133315Sdonn loophole(size(p->value.arg[0]->nodetype), size(p->nodetype));
21211175Slinton break;
21311175Slinton
2149662Slinton case O_COMMA:
21518217Slinton eval(p->value.arg[0]);
21618217Slinton if (p->value.arg[1] != nil) {
21718217Slinton eval(p->value.arg[1]);
21818217Slinton }
2199662Slinton break;
2209662Slinton
2219662Slinton case O_ITOF:
2229662Slinton push(double, (double) r0);
2239662Slinton break;
2249662Slinton
2259662Slinton case O_ADD:
2269662Slinton push(long, r0+r1);
2279662Slinton break;
2289662Slinton
2299662Slinton case O_ADDF:
2309662Slinton push(double, fr0+fr1);
2319662Slinton break;
2329662Slinton
2339662Slinton case O_SUB:
2349662Slinton push(long, r0-r1);
2359662Slinton break;
2369662Slinton
2379662Slinton case O_SUBF:
2389662Slinton push(double, fr0-fr1);
2399662Slinton break;
2409662Slinton
2419662Slinton case O_NEG:
2429662Slinton push(long, -r0);
2439662Slinton break;
2449662Slinton
2459662Slinton case O_NEGF:
2469662Slinton push(double, -fr0);
2479662Slinton break;
2489662Slinton
2499662Slinton case O_MUL:
2509662Slinton push(long, r0*r1);
2519662Slinton break;
2529662Slinton
2539662Slinton case O_MULF:
2549662Slinton push(double, fr0*fr1);
2559662Slinton break;
2569662Slinton
2579662Slinton case O_DIVF:
2589662Slinton if (fr1 == 0) {
2599662Slinton error("error: division by 0");
2609662Slinton }
2619662Slinton push(double, fr0 / fr1);
2629662Slinton break;
2639662Slinton
2649662Slinton case O_DIV:
2659662Slinton if (r1 == 0) {
2669662Slinton error("error: div by 0");
2679662Slinton }
2689662Slinton push(long, r0 div r1);
2699662Slinton break;
2709662Slinton
2719662Slinton case O_MOD:
2729662Slinton if (r1 == 0) {
2739662Slinton error("error: mod by 0");
2749662Slinton }
2759662Slinton push(long, r0 mod r1);
2769662Slinton break;
2779662Slinton
2789662Slinton case O_LT:
2799662Slinton push(Boolrep, r0 < r1);
2809662Slinton break;
2819662Slinton
2829662Slinton case O_LTF:
2839662Slinton push(Boolrep, fr0 < fr1);
2849662Slinton break;
2859662Slinton
2869662Slinton case O_LE:
2879662Slinton push(Boolrep, r0 <= r1);
2889662Slinton break;
2899662Slinton
2909662Slinton case O_LEF:
2919662Slinton push(Boolrep, fr0 <= fr1);
2929662Slinton break;
2939662Slinton
2949662Slinton case O_GT:
2959662Slinton push(Boolrep, r0 > r1);
2969662Slinton break;
2979662Slinton
2989662Slinton case O_GTF:
2999662Slinton push(Boolrep, fr0 > fr1);
3009662Slinton break;
3019662Slinton
3029662Slinton case O_EQ:
3039662Slinton push(Boolrep, r0 == r1);
3049662Slinton break;
3059662Slinton
3069662Slinton case O_EQF:
3079662Slinton push(Boolrep, fr0 == fr1);
3089662Slinton break;
3099662Slinton
3109662Slinton case O_NE:
3119662Slinton push(Boolrep, r0 != r1);
3129662Slinton break;
3139662Slinton
3149662Slinton case O_NEF:
3159662Slinton push(Boolrep, fr0 != fr1);
3169662Slinton break;
3179662Slinton
3189662Slinton case O_AND:
3199662Slinton push(Boolrep, r0 and r1);
3209662Slinton break;
3219662Slinton
3229662Slinton case O_OR:
3239662Slinton push(Boolrep, r0 or r1);
3249662Slinton break;
3259662Slinton
3269662Slinton case O_ASSIGN:
3279662Slinton assign(p->value.arg[0], p->value.arg[1]);
3289662Slinton break;
3299662Slinton
3309662Slinton case O_CHFILE:
3319662Slinton if (p->value.scon == nil) {
3329662Slinton printf("%s\n", cursource);
3339662Slinton } else {
3349662Slinton file = opensource(p->value.scon);
3359662Slinton if (file == nil) {
3369662Slinton error("can't read \"%s\"", p->value.scon);
3379662Slinton } else {
3389662Slinton fclose(file);
3399662Slinton setsource(p->value.scon);
3409662Slinton }
3419662Slinton }
3429662Slinton break;
3439662Slinton
3449662Slinton case O_CONT:
34511871Slinton cont(p->value.lcon);
3469662Slinton printnews();
3479662Slinton break;
3489662Slinton
3499662Slinton case O_LIST:
35018217Slinton list(p);
3519662Slinton break;
3529662Slinton
3539662Slinton case O_FUNC:
35418217Slinton func(p->value.arg[0]);
3559662Slinton break;
3569662Slinton
3579662Slinton case O_EXAMINE:
3589662Slinton eval(p->value.examine.beginaddr);
3599662Slinton r0 = pop(long);
3609662Slinton if (p->value.examine.endaddr == nil) {
3619662Slinton n = p->value.examine.count;
36211175Slinton if (n == 0) {
36311175Slinton printvalue(r0, p->value.examine.mode);
36411175Slinton } else if (streq(p->value.examine.mode, "i")) {
3659662Slinton printninst(n, (Address) r0);
3669662Slinton } else {
3679662Slinton printndata(n, (Address) r0, p->value.examine.mode);
3689662Slinton }
3699662Slinton } else {
3709662Slinton eval(p->value.examine.endaddr);
3719662Slinton r1 = pop(long);
3729662Slinton if (streq(p->value.examine.mode, "i")) {
3739662Slinton printinst((Address)r0, (Address)r1);
3749662Slinton } else {
3759662Slinton printdata((Address)r0, (Address)r1, p->value.examine.mode);
3769662Slinton }
3779662Slinton }
3789662Slinton break;
3799662Slinton
3809662Slinton case O_PRINT:
3819662Slinton for (n1 = p->value.arg[0]; n1 != nil; n1 = n1->value.arg[1]) {
3829662Slinton eval(n1->value.arg[0]);
3839662Slinton printval(n1->value.arg[0]->nodetype);
3849662Slinton putchar(' ');
3859662Slinton }
3869662Slinton putchar('\n');
3879662Slinton break;
3889662Slinton
3899662Slinton case O_PSYM:
3909662Slinton if (p->value.arg[0]->op == O_SYM) {
3919662Slinton psym(p->value.arg[0]->value.sym);
3929662Slinton } else {
3939662Slinton psym(p->value.arg[0]->nodetype);
3949662Slinton }
3959662Slinton break;
3969662Slinton
3979662Slinton case O_QLINE:
3989662Slinton eval(p->value.arg[1]);
3999662Slinton break;
4009662Slinton
4019662Slinton case O_STEP:
4029662Slinton b = inst_tracing;
4039662Slinton inst_tracing = (Boolean) (not p->value.step.source);
4049662Slinton if (p->value.step.skipcalls) {
4059662Slinton next();
4069662Slinton } else {
4079662Slinton stepc();
4089662Slinton }
4099662Slinton inst_tracing = b;
41014674Slinton useInstLoc = (Boolean) (not p->value.step.source);
4119662Slinton printnews();
4129662Slinton break;
4139662Slinton
4149662Slinton case O_WHATIS:
4159662Slinton if (p->value.arg[0]->op == O_SYM) {
4169662Slinton printdecl(p->value.arg[0]->value.sym);
4179662Slinton } else {
4189662Slinton printdecl(p->value.arg[0]->nodetype);
4199662Slinton }
4209662Slinton break;
4219662Slinton
4229662Slinton case O_WHERE:
4239662Slinton wherecmd();
4249662Slinton break;
4259662Slinton
4269662Slinton case O_WHEREIS:
42712538Scsvaf if (p->value.arg[0]->op == O_SYM) {
42818217Slinton printwhereis(stdout, p->value.arg[0]->value.sym);
42912538Scsvaf } else {
43018217Slinton printwhereis(stdout, p->value.arg[0]->nodetype);
43112538Scsvaf }
4329662Slinton break;
4339662Slinton
4349662Slinton case O_WHICH:
43512538Scsvaf if (p->value.arg[0]->op == O_SYM) {
43618217Slinton printwhich(stdout, p->value.arg[0]->value.sym);
43712538Scsvaf } else {
43818217Slinton printwhich(stdout, p->value.arg[0]->nodetype);
43912538Scsvaf }
4409662Slinton putchar('\n');
4419662Slinton break;
4429662Slinton
4439662Slinton case O_ALIAS:
4449662Slinton n1 = p->value.arg[0];
4459662Slinton n2 = p->value.arg[1];
44618217Slinton if (n2 == nil) {
44718217Slinton if (n1 == nil) {
44818217Slinton alias(nil, nil, nil);
44918217Slinton } else {
45018217Slinton alias(n1->value.name, nil, nil);
45118217Slinton }
45218217Slinton } else if (n2->op == O_NAME) {
45318217Slinton str = ident(n2->value.name);
45418217Slinton alias(n1->value.name, nil, strdup(str));
4559662Slinton } else {
45618217Slinton if (n1->op == O_COMMA) {
45718217Slinton alias(
45818217Slinton n1->value.arg[0]->value.name,
45918217Slinton (List) n1->value.arg[1],
46018217Slinton n2->value.scon
46118217Slinton );
46218217Slinton } else {
46318217Slinton alias(n1->value.name, nil, n2->value.scon);
46418217Slinton }
4659662Slinton }
4669662Slinton break;
4679662Slinton
46818217Slinton case O_UNALIAS:
46918217Slinton unalias(p->value.arg[0]->value.name);
47018217Slinton break;
47118217Slinton
47218217Slinton case O_CALLPROC:
47318217Slinton callproc(p, false);
47418217Slinton break;
47518217Slinton
4769662Slinton case O_CALL:
47718217Slinton callproc(p, true);
4789662Slinton break;
4799662Slinton
4809662Slinton case O_CATCH:
48118217Slinton if (p->value.lcon == 0) {
48218217Slinton printsigscaught(process);
48318217Slinton } else {
48418217Slinton psigtrace(process, p->value.lcon, true);
48518217Slinton }
4869662Slinton break;
4879662Slinton
4889662Slinton case O_EDIT:
4899662Slinton edit(p->value.scon);
4909662Slinton break;
4919662Slinton
49212538Scsvaf case O_DEBUG:
49312538Scsvaf debug(p);
49412538Scsvaf break;
49512538Scsvaf
49616608Ssam case O_DOWN:
49716608Ssam checkref(p->value.arg[0]);
49816608Ssam assert(p->value.arg[0]->op == O_LCON);
49916608Ssam down(p->value.arg[0]->value.lcon);
50016608Ssam break;
50116608Ssam
5029662Slinton case O_DUMP:
50318217Slinton if (p->value.arg[0] == nil) {
50418217Slinton dumpall();
50518217Slinton } else {
50618217Slinton s = p->value.arg[0]->value.sym;
50718217Slinton if (s == curfunc) {
50818217Slinton dump(nil);
50918217Slinton } else {
51018217Slinton dump(s);
51118217Slinton }
51218217Slinton }
5139662Slinton break;
5149662Slinton
5159662Slinton case O_GRIPE:
5169662Slinton gripe();
5179662Slinton break;
5189662Slinton
5199662Slinton case O_HELP:
5209662Slinton help();
5219662Slinton break;
5229662Slinton
5239662Slinton case O_IGNORE:
52418217Slinton if (p->value.lcon == 0) {
52518217Slinton printsigsignored(process);
52618217Slinton } else {
52718217Slinton psigtrace(process, p->value.lcon, false);
52818217Slinton }
5299662Slinton break;
5309662Slinton
53116608Ssam case O_RETURN:
53216608Ssam if (p->value.arg[0] == nil) {
53316608Ssam rtnfunc(nil);
53416608Ssam } else {
53516608Ssam assert(p->value.arg[0]->op == O_SYM);
53616608Ssam rtnfunc(p->value.arg[0]->value.sym);
53716608Ssam }
53816608Ssam break;
53916608Ssam
5409662Slinton case O_RUN:
5419662Slinton run();
5429662Slinton break;
5439662Slinton
54418217Slinton case O_SET:
54518217Slinton set(p->value.arg[0], p->value.arg[1]);
54618217Slinton break;
54718217Slinton
54818217Slinton case O_SEARCH:
54918217Slinton search(p->value.arg[0]->value.lcon, p->value.arg[1]->value.scon);
55018217Slinton break;
55118217Slinton
5529662Slinton case O_SOURCE:
5539662Slinton setinput(p->value.scon);
5549662Slinton break;
5559662Slinton
5569662Slinton case O_STATUS:
5579662Slinton status();
5589662Slinton break;
5599662Slinton
5609662Slinton case O_TRACE:
5619662Slinton case O_TRACEI:
5629662Slinton trace(p);
5639662Slinton break;
5649662Slinton
5659662Slinton case O_STOP:
5669662Slinton case O_STOPI:
5679662Slinton stop(p);
5689662Slinton break;
5699662Slinton
57018217Slinton case O_UNSET:
57118217Slinton undefvar(p->value.arg[0]->value.name);
57218217Slinton break;
57318217Slinton
57416608Ssam case O_UP:
57516608Ssam checkref(p->value.arg[0]);
57616608Ssam assert(p->value.arg[0]->op == O_LCON);
57716608Ssam up(p->value.arg[0]->value.lcon);
57816608Ssam break;
57916608Ssam
5809662Slinton case O_ADDEVENT:
5819662Slinton addevent(p->value.event.cond, p->value.event.actions);
5829662Slinton break;
5839662Slinton
5849662Slinton case O_DELETE:
58516608Ssam n1 = p->value.arg[0];
58616608Ssam while (n1->op == O_COMMA) {
58716608Ssam n2 = n1->value.arg[0];
58816608Ssam assert(n2->op == O_LCON);
58916608Ssam if (not delevent((unsigned int) n2->value.lcon)) {
59016608Ssam error("unknown event %ld", n2->value.lcon);
59116608Ssam }
59216608Ssam n1 = n1->value.arg[1];
59316608Ssam }
59416608Ssam assert(n1->op == O_LCON);
59516608Ssam if (not delevent((unsigned int) n1->value.lcon)) {
59616608Ssam error("unknown event %ld", n1->value.lcon);
59716608Ssam }
5989662Slinton break;
5999662Slinton
6009662Slinton case O_ENDX:
6019662Slinton endprogram();
6029662Slinton break;
6039662Slinton
6049662Slinton case O_IF:
6059662Slinton if (cond(p->value.event.cond)) {
6069662Slinton evalcmdlist(p->value.event.actions);
6079662Slinton }
6089662Slinton break;
6099662Slinton
6109662Slinton case O_ONCE:
6119662Slinton event_once(p->value.event.cond, p->value.event.actions);
6129662Slinton break;
6139662Slinton
6149662Slinton case O_PRINTCALL:
6159662Slinton printcall(p->value.sym, whatblock(return_addr()));
6169662Slinton break;
6179662Slinton
6189662Slinton case O_PRINTIFCHANGED:
6199662Slinton printifchanged(p->value.arg[0]);
6209662Slinton break;
6219662Slinton
6229662Slinton case O_PRINTRTN:
6239662Slinton printrtn(p->value.sym);
6249662Slinton break;
6259662Slinton
6269662Slinton case O_PRINTSRCPOS:
6279662Slinton getsrcpos();
6289662Slinton if (p->value.arg[0] == nil) {
6299662Slinton printsrcpos();
6309662Slinton putchar('\n');
6319662Slinton printlines(curline, curline);
6329662Slinton } else if (p->value.arg[0]->op == O_QLINE) {
6339662Slinton if (p->value.arg[0]->value.arg[1]->value.lcon == 0) {
6349662Slinton printf("tracei: ");
6359662Slinton printinst(pc, pc);
6369662Slinton } else {
63718217Slinton if (canReadSource()) {
63818217Slinton printf("trace: ");
63918217Slinton printlines(curline, curline);
64018217Slinton }
6419662Slinton }
6429662Slinton } else {
6439662Slinton printsrcpos();
6449662Slinton printf(": ");
6459662Slinton eval(p->value.arg[0]);
6469662Slinton prtree(stdout, p->value.arg[0]);
6479662Slinton printf(" = ");
6489662Slinton printval(p->value.arg[0]->nodetype);
6499662Slinton putchar('\n');
6509662Slinton }
6519662Slinton break;
6529662Slinton
6539662Slinton case O_PROCRTN:
6549662Slinton procreturn(p->value.sym);
6559662Slinton break;
6569662Slinton
6579662Slinton case O_STOPIFCHANGED:
6589662Slinton stopifchanged(p->value.arg[0]);
6599662Slinton break;
6609662Slinton
6619662Slinton case O_STOPX:
6629662Slinton isstopped = true;
6639662Slinton break;
6649662Slinton
6659662Slinton case O_TRACEON:
6669662Slinton traceon(p->value.trace.inst, p->value.trace.event,
6679662Slinton p->value.trace.actions);
6689662Slinton break;
6699662Slinton
6709662Slinton case O_TRACEOFF:
6719662Slinton traceoff(p->value.lcon);
6729662Slinton break;
6739662Slinton
6749662Slinton default:
6759662Slinton panic("eval: bad op %d", p->op);
6769662Slinton }
67718217Slinton if (traceeval) {
67818217Slinton fprintf(stderr, "end eval %s\n", opname(p->op));
67918217Slinton }
6809662Slinton }
6819662Slinton
6829662Slinton /*
6839662Slinton * Evaluate a list of commands.
6849662Slinton */
6859662Slinton
evalcmdlist(cl)6869662Slinton public evalcmdlist(cl)
6879662Slinton Cmdlist cl;
6889662Slinton {
6899662Slinton Command c;
6909662Slinton
6919662Slinton foreach (Command, c, cl)
6929662Slinton evalcmd(c);
6939662Slinton endfor
6949662Slinton }
6959662Slinton
6969662Slinton /*
6979662Slinton * Push "len" bytes onto the expression stack from address "addr"
6989662Slinton * in the process. If there isn't room on the stack, print an error message.
6999662Slinton */
7009662Slinton
rpush(addr,len)7019662Slinton public rpush(addr, len)
7029662Slinton Address addr;
7039662Slinton int len;
7049662Slinton {
7059662Slinton if (not canpush(len)) {
7069662Slinton error("expression too large to evaluate");
7079662Slinton } else {
7089662Slinton chksp();
7099662Slinton dread(sp, addr, len);
7109662Slinton sp += len;
7119662Slinton }
7129662Slinton }
7139662Slinton
7149662Slinton /*
7159662Slinton * Check if the stack has n bytes available.
7169662Slinton */
7179662Slinton
canpush(n)7189662Slinton public Boolean canpush(n)
7199662Slinton Integer n;
7209662Slinton {
7219662Slinton return (Boolean) (sp + n < &stack[STACKSIZE]);
7229662Slinton }
7239662Slinton
7249662Slinton /*
7259662Slinton * Push a small scalar of the given type onto the stack.
7269662Slinton */
7279662Slinton
pushsmall(t,v)7289662Slinton public pushsmall(t, v)
7299662Slinton Symbol t;
7309662Slinton long v;
7319662Slinton {
7329662Slinton register Integer s;
7339662Slinton
7349662Slinton s = size(t);
7359662Slinton switch (s) {
7369662Slinton case sizeof(char):
7379662Slinton push(char, v);
7389662Slinton break;
7399662Slinton
7409662Slinton case sizeof(short):
7419662Slinton push(short, v);
7429662Slinton break;
7439662Slinton
7449662Slinton case sizeof(long):
7459662Slinton push(long, v);
7469662Slinton break;
7479662Slinton
7489662Slinton default:
7499662Slinton panic("bad size %d in popsmall", s);
7509662Slinton }
7519662Slinton }
7529662Slinton
7539662Slinton /*
7549662Slinton * Pop an item of the given type which is assumed to be no larger
7559662Slinton * than a long and return it expanded into a long.
7569662Slinton */
7579662Slinton
popsmall(t)7589662Slinton public long popsmall(t)
7599662Slinton Symbol t;
7609662Slinton {
76118217Slinton register integer n;
7629662Slinton long r;
7639662Slinton
76418217Slinton n = size(t);
76518217Slinton if (n == sizeof(char)) {
76618217Slinton if (t->class == RANGE and t->symvalue.rangev.lower >= 0) {
76718217Slinton r = (long) pop(unsigned char);
76818217Slinton } else {
7699662Slinton r = (long) pop(char);
77018217Slinton }
77118217Slinton } else if (n == sizeof(short)) {
77218217Slinton if (t->class == RANGE and t->symvalue.rangev.lower >= 0) {
77318217Slinton r = (long) pop(unsigned short);
77418217Slinton } else {
7759662Slinton r = (long) pop(short);
77618217Slinton }
77718217Slinton } else if (n == sizeof(long)) {
77818217Slinton r = pop(long);
77918217Slinton } else {
78018217Slinton error("[internal error: size %d in popsmall]", n);
7819662Slinton }
7829662Slinton return r;
7839662Slinton }
7849662Slinton
7859662Slinton /*
7869662Slinton * Evaluate a conditional expression.
7879662Slinton */
7889662Slinton
cond(p)7899662Slinton public Boolean cond(p)
7909662Slinton Node p;
7919662Slinton {
79233315Sdonn Boolean b;
79333315Sdonn int i;
7949662Slinton
7959662Slinton if (p == nil) {
7969662Slinton b = true;
7979662Slinton } else {
7989662Slinton eval(p);
79933315Sdonn i = pop(Boolrep);
80033315Sdonn b = (Boolean) i;
8019662Slinton }
8029662Slinton return b;
8039662Slinton }
8049662Slinton
8059662Slinton /*
8069662Slinton * Return the address corresponding to a given tree.
8079662Slinton */
8089662Slinton
lval(p)8099662Slinton public Address lval(p)
8109662Slinton Node p;
8119662Slinton {
8129662Slinton if (p->op == O_RVAL) {
8139662Slinton eval(p->value.arg[0]);
8149662Slinton } else {
8159662Slinton eval(p);
8169662Slinton }
8179662Slinton return (Address) (pop(long));
8189662Slinton }
8199662Slinton
8209662Slinton /*
8219662Slinton * Process a trace command, translating into the appropriate events
8229662Slinton * and associated actions.
8239662Slinton */
8249662Slinton
trace(p)8259662Slinton public trace(p)
8269662Slinton Node p;
8279662Slinton {
8289662Slinton Node exp, place, cond;
8299662Slinton Node left;
8309662Slinton
8319662Slinton exp = p->value.arg[0];
8329662Slinton place = p->value.arg[1];
8339662Slinton cond = p->value.arg[2];
8349662Slinton if (exp == nil) {
8359662Slinton traceall(p->op, place, cond);
83611771Slinton } else if (exp->op == O_QLINE or exp->op == O_LCON) {
8379662Slinton traceinst(p->op, exp, cond);
8389662Slinton } else if (place != nil and place->op == O_QLINE) {
8399662Slinton traceat(p->op, exp, place, cond);
8409662Slinton } else {
8419861Slinton left = exp;
8429861Slinton if (left->op == O_RVAL or left->op == O_CALL) {
8439861Slinton left = left->value.arg[0];
8449861Slinton }
8459662Slinton if (left->op == O_SYM and isblock(left->value.sym)) {
8469662Slinton traceproc(p->op, left->value.sym, place, cond);
8479662Slinton } else {
8489662Slinton tracedata(p->op, exp, place, cond);
8499662Slinton }
8509662Slinton }
8519662Slinton }
8529662Slinton
8539662Slinton /*
8549662Slinton * Set a breakpoint that will turn on tracing.
8559662Slinton */
8569662Slinton
traceall(op,place,cond)8579662Slinton private traceall(op, place, cond)
8589662Slinton Operator op;
8599662Slinton Node place;
8609662Slinton Node cond;
8619662Slinton {
8629662Slinton Symbol s;
8639662Slinton Node event;
8649662Slinton Command action;
8659662Slinton
8669662Slinton if (place == nil) {
8679662Slinton s = program;
8689662Slinton } else {
8699662Slinton s = place->value.sym;
8709662Slinton }
8719662Slinton event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s));
8729662Slinton action = build(O_PRINTSRCPOS,
8739662Slinton build(O_QLINE, nil, build(O_LCON, (op == O_TRACE) ? 1 : 0)));
8749662Slinton if (cond != nil) {
8759662Slinton action = build(O_IF, cond, buildcmdlist(action));
8769662Slinton }
8779662Slinton action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action));
8789662Slinton action->value.trace.event = addevent(event, buildcmdlist(action));
87911871Slinton if (isstdin()) {
88011871Slinton printevent(action->value.trace.event);
88111871Slinton }
8829662Slinton }
8839662Slinton
8849662Slinton /*
8859662Slinton * Set up the appropriate breakpoint for tracing an instruction.
8869662Slinton */
8879662Slinton
traceinst(op,exp,cond)8889662Slinton private traceinst(op, exp, cond)
8899662Slinton Operator op;
8909662Slinton Node exp;
8919662Slinton Node cond;
8929662Slinton {
89311771Slinton Node event, wh;
8949662Slinton Command action;
89511871Slinton Event e;
8969662Slinton
89711771Slinton if (exp->op == O_LCON) {
89818217Slinton wh = build(O_QLINE, build(O_SCON, strdup(cursource)), exp);
89911771Slinton } else {
90011771Slinton wh = exp;
90111771Slinton }
9029662Slinton if (op == O_TRACEI) {
90311771Slinton event = build(O_EQ, build(O_SYM, pcsym), wh);
9049662Slinton } else {
90511771Slinton event = build(O_EQ, build(O_SYM, linesym), wh);
9069662Slinton }
90711771Slinton action = build(O_PRINTSRCPOS, wh);
9089662Slinton if (cond) {
9099662Slinton action = build(O_IF, cond, buildcmdlist(action));
9109662Slinton }
91111871Slinton e = addevent(event, buildcmdlist(action));
91211871Slinton if (isstdin()) {
91311871Slinton printevent(e);
91411871Slinton }
9159662Slinton }
9169662Slinton
9179662Slinton /*
9189662Slinton * Set a breakpoint to print an expression at a given line or address.
9199662Slinton */
9209662Slinton
traceat(op,exp,place,cond)9219662Slinton private traceat(op, exp, place, cond)
9229662Slinton Operator op;
9239662Slinton Node exp;
9249662Slinton Node place;
9259662Slinton Node cond;
9269662Slinton {
9279662Slinton Node event;
9289662Slinton Command action;
92911871Slinton Event e;
9309662Slinton
9319662Slinton if (op == O_TRACEI) {
9329662Slinton event = build(O_EQ, build(O_SYM, pcsym), place);
9339662Slinton } else {
9349662Slinton event = build(O_EQ, build(O_SYM, linesym), place);
9359662Slinton }
9369662Slinton action = build(O_PRINTSRCPOS, exp);
9379662Slinton if (cond != nil) {
9389662Slinton action = build(O_IF, cond, buildcmdlist(action));
9399662Slinton }
94011871Slinton e = addevent(event, buildcmdlist(action));
94111871Slinton if (isstdin()) {
94211871Slinton printevent(e);
94311871Slinton }
9449662Slinton }
9459662Slinton
9469662Slinton /*
9479662Slinton * Construct event for tracing a procedure.
9489662Slinton *
9499662Slinton * What we want here is
9509662Slinton *
9519662Slinton * when $proc = p do
9529662Slinton * if <condition> then
9539662Slinton * printcall;
9549662Slinton * once $pc = $retaddr do
9559662Slinton * printrtn;
9569662Slinton * end;
9579662Slinton * end if;
9589662Slinton * end;
9599662Slinton *
9609662Slinton * Note that "once" is like "when" except that the event
9619662Slinton * deletes itself as part of its associated action.
9629662Slinton */
9639662Slinton
traceproc(op,p,place,cond)9649662Slinton private traceproc(op, p, place, cond)
9659662Slinton Operator op;
9669662Slinton Symbol p;
9679662Slinton Node place;
9689662Slinton Node cond;
9699662Slinton {
9709662Slinton Node event;
9719662Slinton Command action;
9729662Slinton Cmdlist actionlist;
97311871Slinton Event e;
9749662Slinton
9759662Slinton action = build(O_PRINTCALL, p);
9769662Slinton actionlist = list_alloc();
9779662Slinton cmdlist_append(action, actionlist);
9789662Slinton event = build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym));
9799662Slinton action = build(O_ONCE, event, buildcmdlist(build(O_PRINTRTN, p)));
9809662Slinton cmdlist_append(action, actionlist);
9819662Slinton if (cond != nil) {
9829662Slinton actionlist = buildcmdlist(build(O_IF, cond, actionlist));
9839662Slinton }
9849662Slinton event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
98511871Slinton e = addevent(event, actionlist);
98611871Slinton if (isstdin()) {
98711871Slinton printevent(e);
98811871Slinton }
9899662Slinton }
9909662Slinton
9919662Slinton /*
9929662Slinton * Set up breakpoint for tracing data.
9939662Slinton */
9949662Slinton
tracedata(op,exp,place,cond)9959662Slinton private tracedata(op, exp, place, cond)
9969662Slinton Operator op;
9979662Slinton Node exp;
9989662Slinton Node place;
9999662Slinton Node cond;
10009662Slinton {
10019662Slinton Symbol p;
10029662Slinton Node event;
10039662Slinton Command action;
10049662Slinton
100533315Sdonn if (size(exp->nodetype) > MAXTRSIZE) {
100633315Sdonn error("expression too large to trace (limit is %d bytes)", MAXTRSIZE);
100733315Sdonn }
10089662Slinton p = (place == nil) ? tcontainer(exp) : place->value.sym;
10099662Slinton if (p == nil) {
10109662Slinton p = program;
10119662Slinton }
10129662Slinton action = build(O_PRINTIFCHANGED, exp);
10139662Slinton if (cond != nil) {
10149662Slinton action = build(O_IF, cond, buildcmdlist(action));
10159662Slinton }
10169662Slinton action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action));
10179662Slinton event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
10189662Slinton action->value.trace.event = addevent(event, buildcmdlist(action));
101911871Slinton if (isstdin()) {
102011871Slinton printevent(action->value.trace.event);
102111871Slinton }
10229662Slinton }
10239662Slinton
10249662Slinton /*
10259662Slinton * Setting and unsetting of stops.
10269662Slinton */
10279662Slinton
stop(p)10289662Slinton public stop(p)
10299662Slinton Node p;
10309662Slinton {
103113846Slinton Node exp, place, cond, t;
10329662Slinton Symbol s;
10339662Slinton Command action;
103411871Slinton Event e;
10359662Slinton
10369662Slinton exp = p->value.arg[0];
10379662Slinton place = p->value.arg[1];
10389662Slinton cond = p->value.arg[2];
10399662Slinton if (exp != nil) {
10409662Slinton stopvar(p->op, exp, place, cond);
104113846Slinton } else {
104213846Slinton action = build(O_STOPX);
104313846Slinton if (cond != nil) {
104413846Slinton action = build(O_IF, cond, buildcmdlist(action));
104511871Slinton }
104616608Ssam if (place == nil or place->op == O_SYM) {
104716608Ssam if (place == nil) {
104816608Ssam s = program;
104916608Ssam } else {
105016608Ssam s = place->value.sym;
105116608Ssam }
105213846Slinton t = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s));
105313846Slinton if (cond != nil) {
105413846Slinton action = build(O_TRACEON, (p->op == O_STOPI),
105513846Slinton buildcmdlist(action));
105613846Slinton e = addevent(t, buildcmdlist(action));
105713846Slinton action->value.trace.event = e;
105813846Slinton } else {
105913846Slinton e = addevent(t, buildcmdlist(action));
106013846Slinton }
106113846Slinton if (isstdin()) {
106213846Slinton printevent(e);
106313846Slinton }
106413846Slinton } else {
106513846Slinton stopinst(p->op, place, cond, action);
106613846Slinton }
10679662Slinton }
10689662Slinton }
10699662Slinton
stopinst(op,place,cond,action)107013846Slinton private stopinst(op, place, cond, action)
10719662Slinton Operator op;
10729662Slinton Node place;
10739662Slinton Node cond;
107413846Slinton Command action;
10759662Slinton {
10769662Slinton Node event;
107711871Slinton Event e;
10789662Slinton
10799662Slinton if (op == O_STOP) {
10809662Slinton event = build(O_EQ, build(O_SYM, linesym), place);
10819662Slinton } else {
10829662Slinton event = build(O_EQ, build(O_SYM, pcsym), place);
10839662Slinton }
108413846Slinton e = addevent(event, buildcmdlist(action));
108511871Slinton if (isstdin()) {
108611871Slinton printevent(e);
108711871Slinton }
10889662Slinton }
10899662Slinton
10909662Slinton /*
10919662Slinton * Implement stopping on assignment to a variable by adding it to
10929662Slinton * the variable list.
10939662Slinton */
10949662Slinton
stopvar(op,exp,place,cond)10959662Slinton private stopvar(op, exp, place, cond)
10969662Slinton Operator op;
10979662Slinton Node exp;
10989662Slinton Node place;
10999662Slinton Node cond;
11009662Slinton {
11019662Slinton Symbol p;
11029662Slinton Node event;
11039662Slinton Command action;
11049662Slinton
110533315Sdonn if (size(exp->nodetype) > MAXTRSIZE) {
110633315Sdonn error("expression too large to trace (limit is %d bytes)", MAXTRSIZE);
110733315Sdonn }
110814445Slinton if (place == nil) {
110914445Slinton if (exp->op == O_LCON) {
111014445Slinton p = program;
111114445Slinton } else {
111214445Slinton p = tcontainer(exp);
111314445Slinton if (p == nil) {
111414445Slinton p = program;
111514445Slinton }
111614445Slinton }
111714445Slinton } else {
111814445Slinton p = place->value.sym;
11199662Slinton }
112014445Slinton action = build(O_STOPIFCHANGED, exp);
112114445Slinton if (cond != nil) {
112214445Slinton action = build(O_IF, cond, buildcmdlist(action));
112314445Slinton }
11249662Slinton action = build(O_TRACEON, (op == O_STOPI), buildcmdlist(action));
11259662Slinton event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
11269662Slinton action->value.trace.event = addevent(event, buildcmdlist(action));
112711871Slinton if (isstdin()) {
112811871Slinton printevent(action->value.trace.event);
112911871Slinton }
11309662Slinton }
11319662Slinton
11329662Slinton /*
11339662Slinton * Assign the value of an expression to a variable (or term).
11349662Slinton */
11359662Slinton
assign(var,exp)11369662Slinton public assign(var, exp)
11379662Slinton Node var;
11389662Slinton Node exp;
11399662Slinton {
11409662Slinton Address addr;
114116608Ssam integer varsize, expsize;
11429662Slinton char cvalue;
11439662Slinton short svalue;
11449662Slinton long lvalue;
114516608Ssam float fvalue;
11469662Slinton
114718217Slinton if (var->op == O_SYM and regnum(var->value.sym) != -1) {
114818217Slinton eval(exp);
114918217Slinton setreg(regnum(var->value.sym), pop(Address));
115016608Ssam } else {
115118217Slinton addr = lval(var);
115218217Slinton varsize = size(var->nodetype);
115318217Slinton expsize = size(exp->nodetype);
115418217Slinton eval(exp);
115518217Slinton if (varsize == sizeof(float) and expsize == sizeof(double)) {
115618217Slinton fvalue = (float) pop(double);
115718217Slinton dwrite(&fvalue, addr, sizeof(fvalue));
115818217Slinton } else {
115918217Slinton if (varsize < sizeof(long)) {
116018217Slinton lvalue = 0;
116118217Slinton popn(expsize, &lvalue);
116218217Slinton if (varsize == sizeof(char)) {
116316608Ssam cvalue = lvalue;
116416608Ssam dwrite(&cvalue, addr, sizeof(cvalue));
116518217Slinton } else if (varsize == sizeof(short)) {
116616608Ssam svalue = lvalue;
116716608Ssam dwrite(&svalue, addr, sizeof(svalue));
116818217Slinton } else {
116918217Slinton error("[internal error: bad size %d in assign]", varsize);
117018217Slinton }
117118217Slinton } else {
117218217Slinton if (expsize <= varsize) {
117318217Slinton sp -= expsize;
117418217Slinton dwrite(sp, addr, expsize);
117518217Slinton } else {
117618217Slinton sp -= expsize;
117718217Slinton dwrite(sp, addr, varsize);
117818217Slinton }
117918217Slinton }
118018217Slinton }
118118217Slinton }
118218217Slinton }
11839662Slinton
118418217Slinton /*
118518217Slinton * Set a debugger variable.
118618217Slinton */
118718217Slinton
set(var,exp)118818217Slinton private set (var, exp)
118918217Slinton Node var, exp;
119018217Slinton {
119118217Slinton Symbol t;
119218217Slinton
119318217Slinton if (var == nil) {
119418217Slinton defvar(nil, nil);
119518217Slinton } else if (exp == nil) {
119618217Slinton defvar(var->value.name, nil);
119718217Slinton } else if (var->value.name == identname("$frame", true)) {
119818217Slinton t = exp->nodetype;
119918217Slinton if (not compatible(t, t_int) and not compatible(t, t_addr)) {
120018217Slinton error("$frame must be an address");
120118217Slinton }
120218217Slinton eval(exp);
120318217Slinton getnewregs(pop(Address));
120418217Slinton } else {
120518217Slinton defvar(var->value.name, unrval(exp));
120618217Slinton }
120718217Slinton }
120818217Slinton
120918217Slinton /*
121018217Slinton * Execute a list command.
121118217Slinton */
121218217Slinton
list(p)121318217Slinton private list (p)
121418217Slinton Node p;
121518217Slinton {
121618217Slinton Symbol f;
121718217Slinton Address addr;
121818217Slinton Lineno line, l1, l2;
121918217Slinton
122018217Slinton if (p->value.arg[0]->op == O_SYM) {
122118217Slinton f = p->value.arg[0]->value.sym;
122218217Slinton addr = firstline(f);
122318217Slinton if (addr == NOADDR) {
122418217Slinton error("no source lines for \"%s\"", symname(f));
122518217Slinton }
122618217Slinton setsource(srcfilename(addr));
122718217Slinton line = srcline(addr);
122818217Slinton getsrcwindow(line, &l1, &l2);
122918217Slinton } else {
123018217Slinton eval(p->value.arg[0]);
123118217Slinton l1 = (Lineno) (pop(long));
123218217Slinton eval(p->value.arg[1]);
123318217Slinton l2 = (Lineno) (pop(long));
123418217Slinton }
123518217Slinton printlines(l1, l2);
123618217Slinton }
123718217Slinton
123818217Slinton /*
123918217Slinton * Execute a func command.
124018217Slinton */
124118217Slinton
func(p)124218217Slinton private func (p)
124318217Slinton Node p;
124418217Slinton {
124518217Slinton Symbol s, f;
124618217Slinton Address addr;
124718217Slinton
124818217Slinton if (p == nil) {
124918217Slinton printname(stdout, curfunc);
125018217Slinton putchar('\n');
125118217Slinton } else {
125218217Slinton s = p->value.sym;
125318217Slinton if (isroutine(s)) {
125418217Slinton setcurfunc(s);
125516608Ssam } else {
125618217Slinton find(f, s->name) where isroutine(f) endfind(f);
125718217Slinton if (f == nil) {
125818217Slinton error("%s is not a procedure or function", symname(s));
125916608Ssam }
126018217Slinton setcurfunc(f);
12619662Slinton }
126218217Slinton addr = codeloc(curfunc);
126318217Slinton if (addr != NOADDR) {
126418217Slinton setsource(srcfilename(addr));
126518217Slinton cursrcline = srcline(addr);
126618217Slinton }
12679662Slinton }
12689662Slinton }
12699662Slinton
12709662Slinton /*
127118217Slinton * Send a message to the current support person.
12729662Slinton */
12739662Slinton
gripe()12749662Slinton public gripe()
12759662Slinton {
12769662Slinton typedef Operation();
12779662Slinton Operation *old;
127814445Slinton int pid, status;
127916608Ssam extern int versionNumber;
128016608Ssam char subject[100];
12819662Slinton
128233315Sdonn # ifdef MAINTAINER
128333315Sdonn puts("Type control-D to end your message. Be sure to include");
128433315Sdonn puts("your name and the name of the file you are debugging.");
128533315Sdonn putchar('\n');
128633315Sdonn old = signal(SIGINT, SIG_DFL);
128733315Sdonn sprintf(subject, "dbx (version 3.%d) gripe", versionNumber);
128833315Sdonn pid = back("Mail", stdin, stdout, "-s", subject, MAINTAINER, nil);
128933315Sdonn signal(SIGINT, SIG_IGN);
129033315Sdonn pwait(pid, &status);
129133315Sdonn signal(SIGINT, old);
129233315Sdonn if (status == 0) {
129333315Sdonn puts("Thank you.");
129433315Sdonn } else {
129533315Sdonn puts("\nMail not sent.");
129633315Sdonn }
129733315Sdonn # else
129833315Sdonn puts("Sorry, no dbx maintainer available to gripe to.");
129933315Sdonn puts("Try contacting your system manager.");
130033315Sdonn # endif
13019662Slinton }
13029662Slinton
13039662Slinton /*
13049662Slinton * Give the user some help.
13059662Slinton */
13069662Slinton
help()13079662Slinton public help()
13089662Slinton {
13099662Slinton puts("run - begin execution of the program");
131016608Ssam puts("print <exp> - print the value of the expression");
131116608Ssam puts("where - print currently active procedures");
131216608Ssam puts("stop at <line> - suspend execution at the line");
131316608Ssam puts("stop in <proc> - suspend execution when <proc> is called");
13149662Slinton puts("cont - continue execution");
13159662Slinton puts("step - single step one line");
13169662Slinton puts("next - step to next line (skip over calls)");
13179662Slinton puts("trace <line#> - trace execution of the line");
13189662Slinton puts("trace <proc> - trace calls to the procedure");
13199662Slinton puts("trace <var> - trace changes to the variable");
13209662Slinton puts("trace <exp> at <line#> - print <exp> when <line> is reached");
13219662Slinton puts("status - print trace/stop's in effect");
13229662Slinton puts("delete <number> - remove trace or stop of given number");
132316608Ssam puts("call <proc> - call a procedure in program");
13249662Slinton puts("whatis <name> - print the declaration of the name");
13259662Slinton puts("list <line>, <line> - list source lines");
13269662Slinton puts("gripe - send mail to the person in charge of dbx");
13279662Slinton puts("quit - exit dbx");
13289662Slinton }
13299662Slinton
13309662Slinton /*
13319662Slinton * Divert output to the given file name.
13329662Slinton * Cannot redirect to an existing file.
13339662Slinton */
13349662Slinton
13359662Slinton private int so_fd;
13369662Slinton private Boolean notstdout;
13379662Slinton
setout(filename)13389662Slinton public setout(filename)
13399662Slinton String filename;
13409662Slinton {
13419662Slinton File f;
13429662Slinton
13439662Slinton f = fopen(filename, "r");
13449662Slinton if (f != nil) {
13459662Slinton fclose(f);
13469662Slinton error("%s: file already exists", filename);
13479662Slinton } else {
13489662Slinton so_fd = dup(1);
13499662Slinton close(1);
13509662Slinton if (creat(filename, 0666) == nil) {
13519662Slinton unsetout();
13529662Slinton error("can't create %s", filename);
13539662Slinton }
13549662Slinton notstdout = true;
13559662Slinton }
13569662Slinton }
13579662Slinton
13589662Slinton /*
13599662Slinton * Revert output to standard output.
13609662Slinton */
13619662Slinton
unsetout()13629662Slinton public unsetout()
13639662Slinton {
13649662Slinton fflush(stdout);
13659662Slinton close(1);
13669662Slinton if (dup(so_fd) != 1) {
13679662Slinton panic("standard out dup failed");
13689662Slinton }
13699662Slinton close(so_fd);
13709662Slinton notstdout = false;
13719662Slinton }
13729662Slinton
13739662Slinton /*
13749662Slinton * Determine is standard output is currently being redirected
13759662Slinton * to a file (as far as we know).
13769662Slinton */
13779662Slinton
isredirected()13789662Slinton public Boolean isredirected()
13799662Slinton {
13809662Slinton return notstdout;
13819662Slinton }
1382