⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eval.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
    }}/* * Evaluate a list of commands. */public evalcmdlist(cl)Cmdlist cl;{    Command c;    foreach (Command, c, cl)	evalcmd(c);    endfor}/* * Push "len" bytes onto the expression stack from address "addr" * in the process.  If there isn't room on the stack, print an error message. */public rpush(addr, len)Address addr;int len;{    if (not canpush(len)) {	error("expression too large to evaluate");    } else {	chksp();	dread(sp, addr, len);	sp += len;    }}/* * Check if the stack has n bytes available. */public Boolean canpush(n)Integer n;{    return (Boolean) (sp + n < &stack[STACKSIZE]);}/* * Push a small scalar of the given type onto the stack. */public pushsmall(t, v)Symbol t;long v;{    register Integer s;    s = size(t);    switch (s) {	case sizeof(char):	    push(char, v);	    break;	case sizeof(short):	    push(short, v);	    break;	case sizeof(long):	    push(long, v);	    break;	default:	    panic("bad size %d in popsmall", s);    }}/* * Pop an item of the given type which is assumed to be no larger * than a long and return it expanded into a long. */public long popsmall(t)Symbol t;{    register integer n;    long r;    n = size(t);    if (n == sizeof(char)) {	if (t->class == RANGE and t->symvalue.rangev.lower >= 0) {	    r = (long) pop(unsigned char);	} else {	    r = (long) pop(char);	}    } else if (n == sizeof(short)) {	if (t->class == RANGE and t->symvalue.rangev.lower >= 0) {	    r = (long) pop(unsigned short);	} else {	    r = (long) pop(short);	}    } else if (n == sizeof(long)) {	r = pop(long);    } else {	error("[internal error: size %d in popsmall]", n);    }    return r;}/* * Evaluate a conditional expression. */public Boolean cond(p)Node p;{    Boolean b;    int i;    if (p == nil) {	b = true;    } else {	eval(p);	i = pop(Boolrep);	b = (Boolean) i;    }    return b;}/* * Return the address corresponding to a given tree. */public Address lval(p)Node p;{    if (p->op == O_RVAL) {	eval(p->value.arg[0]);    } else {	eval(p);    }    return (Address) (pop(long));}/* * Process a trace command, translating into the appropriate events * and associated actions. */public trace(p)Node p;{    Node exp, place, cond;    Node left;    exp = p->value.arg[0];    place = p->value.arg[1];    cond = p->value.arg[2];    if (exp == nil) {	traceall(p->op, place, cond);    } else if (exp->op == O_QLINE or exp->op == O_LCON) {	traceinst(p->op, exp, cond);    } else if (place != nil and place->op == O_QLINE) {	traceat(p->op, exp, place, cond);    } else {	left = exp;	if (left->op == O_RVAL or left->op == O_CALL) {	    left = left->value.arg[0];	}	if (left->op == O_SYM and isblock(left->value.sym)) {	    traceproc(p->op, left->value.sym, place, cond);	} else {	    tracedata(p->op, exp, place, cond);	}    }}/* * Set a breakpoint that will turn on tracing. */private traceall(op, place, cond)Operator op;Node place;Node cond;{    Symbol s;    Node event;    Command action;    if (place == nil) {	s = program;    } else {	s = place->value.sym;    }    event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s));    action = build(O_PRINTSRCPOS,	build(O_QLINE, nil, build(O_LCON, (op == O_TRACE) ? 1 : 0)));    if (cond != nil) {	action = build(O_IF, cond, buildcmdlist(action));    }    action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action));    action->value.trace.event = addevent(event, buildcmdlist(action));    if (isstdin()) {	printevent(action->value.trace.event);    }}/* * Set up the appropriate breakpoint for tracing an instruction. */private traceinst(op, exp, cond)Operator op;Node exp;Node cond;{    Node event, wh;    Command action;    Event e;    if (exp->op == O_LCON) {	wh = build(O_QLINE, build(O_SCON, strdup(cursource)), exp);    } else {	wh = exp;    }    if (op == O_TRACEI) {	event = build(O_EQ, build(O_SYM, pcsym), wh);    } else {	event = build(O_EQ, build(O_SYM, linesym), wh);    }    action = build(O_PRINTSRCPOS, wh);    if (cond) {	action = build(O_IF, cond, buildcmdlist(action));    }    e = addevent(event, buildcmdlist(action));    if (isstdin()) {	printevent(e);    }}/* * Set a breakpoint to print an expression at a given line or address. */private traceat(op, exp, place, cond)Operator op;Node exp;Node place;Node cond;{    Node event;    Command action;    Event e;    if (op == O_TRACEI) {	event = build(O_EQ, build(O_SYM, pcsym), place);    } else {	event = build(O_EQ, build(O_SYM, linesym), place);    }    action = build(O_PRINTSRCPOS, exp);    if (cond != nil) {	action = build(O_IF, cond, buildcmdlist(action));    }    e = addevent(event, buildcmdlist(action));    if (isstdin()) {	printevent(e);    }}/* * Construct event for tracing a procedure. * * What we want here is * * 	when $proc = p do *	    if <condition> then *	        printcall; *	        once $pc = $retaddr do *	            printrtn; *	        end; *	    end if; *	end; * * Note that "once" is like "when" except that the event * deletes itself as part of its associated action. */private traceproc(op, p, place, cond)Operator op;Symbol p;Node place;Node cond;{    Node event;    Command action;    Cmdlist actionlist;    Event e;    action = build(O_PRINTCALL, p);    actionlist = list_alloc();    cmdlist_append(action, actionlist);    event = build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym));    action = build(O_ONCE, event, buildcmdlist(build(O_PRINTRTN, p)));    cmdlist_append(action, actionlist);    if (cond != nil) {	actionlist = buildcmdlist(build(O_IF, cond, actionlist));    }    event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));    e = addevent(event, actionlist);    if (isstdin()) {	printevent(e);    }}/* * Set up breakpoint for tracing data. */private tracedata(op, exp, place, cond)Operator op;Node exp;Node place;Node cond;{    Symbol p;    Node event;    Command action;    if (size(exp->nodetype) > MAXTRSIZE) {	error("expression too large to trace (limit is %d bytes)", MAXTRSIZE);    }    p = (place == nil) ? tcontainer(exp) : place->value.sym;    if (p == nil) {	p = program;    }    action = build(O_PRINTIFCHANGED, exp);    if (cond != nil) {	action = build(O_IF, cond, buildcmdlist(action));    }    action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action));    event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));    action->value.trace.event = addevent(event, buildcmdlist(action));    if (isstdin()) {	printevent(action->value.trace.event);    }}/* * Setting and unsetting of stops. */public stop(p)Node p;{    Node exp, place, cond, t;    Symbol s;    Command action;    Event e;    exp = p->value.arg[0];    place = p->value.arg[1];    cond = p->value.arg[2];    if (exp != nil) {	stopvar(p->op, exp, place, cond);    } else {	action = build(O_STOPX);	if (cond != nil) {	    action = build(O_IF, cond, buildcmdlist(action));	}	if (place == nil or place->op == O_SYM) {	    if (place == nil) {		s = program;	    } else {		s = place->value.sym;	    }	    t = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s));	    if (cond != nil) {		action = build(O_TRACEON, (p->op == O_STOPI),		    buildcmdlist(action));		e = addevent(t, buildcmdlist(action));		action->value.trace.event = e;	    } else {		e = addevent(t, buildcmdlist(action));	    }	    if (isstdin()) {		printevent(e);	    }	} else {	    stopinst(p->op, place, cond, action);	}    }}private stopinst(op, place, cond, action)Operator op;Node place;Node cond;Command action;{    Node event;    Event e;    if (op == O_STOP) {	event = build(O_EQ, build(O_SYM, linesym), place);    } else {	event = build(O_EQ, build(O_SYM, pcsym), place);    }    e = addevent(event, buildcmdlist(action));    if (isstdin()) {	printevent(e);    }}/* * Implement stopping on assignment to a variable by adding it to * the variable list. */private stopvar(op, exp, place, cond)Operator op;Node exp;Node place;Node cond;{    Symbol p;    Node event;    Command action;    if (size(exp->nodetype) > MAXTRSIZE) {	error("expression too large to trace (limit is %d bytes)", MAXTRSIZE);    }    if (place == nil) {	if (exp->op == O_LCON) {	    p = program;	} else {	    p = tcontainer(exp);	    if (p == nil) {		p = program;	    }	}    } else {	p = place->value.sym;    }    action = build(O_STOPIFCHANGED, exp);    if (cond != nil) {	action = build(O_IF, cond, buildcmdlist(action));    }    action = build(O_TRACEON, (op == O_STOPI), buildcmdlist(action));    event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));    action->value.trace.event = addevent(event, buildcmdlist(action));    if (isstdin()) {	printevent(action->value.trace.event);    }}/* * Assign the value of an expression to a variable (or term). */public assign(var, exp)Node var;Node exp;{    Address addr;    integer varsize, expsize;    char cvalue;    short svalue;    long lvalue;    float fvalue;    if (var->op == O_SYM and regnum(var->value.sym) != -1) {	eval(exp);	setreg(regnum(var->value.sym), pop(Address));    } else {	addr = lval(var);	varsize = size(var->nodetype);	expsize = size(exp->nodetype);	eval(exp);	if (varsize == sizeof(float) and expsize == sizeof(double)) {	    fvalue = (float) pop(double);	    dwrite(&fvalue, addr, sizeof(fvalue));	} else {	    if (varsize < sizeof(long)) {		lvalue = 0;		popn(expsize, &lvalue);		if (varsize == sizeof(char)) {		    cvalue = lvalue;		    dwrite(&cvalue, addr, sizeof(cvalue));		} else if (varsize == sizeof(short)) {		    svalue = lvalue;		    dwrite(&svalue, addr, sizeof(svalue));		} else {		    error("[internal error: bad size %d in assign]", varsize);		}	    } else {		if (expsize <= varsize) {		    sp -= expsize;		    dwrite(sp, addr, expsize);		} else {		    sp -= expsize;		    dwrite(sp, addr, varsize);		}	    }	}    }}/* * Set a debugger variable. */private set (var, exp)Node var, exp;{    Symbol t;    if (var == nil) {	defvar(nil, nil);    } else if (exp == nil) {	defvar(var->value.name, nil);    } else if (var->value.name == identname("$frame", true)) {	t = exp->nodetype;	if (not compatible(t, t_int) and not compatible(t, t_addr)) {	    error("$frame must be an address");	}	eval(exp);	getnewregs(pop(Address));    } else {	defvar(var->value.name, unrval(exp));    }}/* * Execute a list command. */private list (p)Node p;{    Symbol f;    Address addr;    Lineno line, l1, l2;    if (p->value.arg[0]->op == O_SYM) {	f = p->value.arg[0]->value.sym;	addr = firstline(f);	if (addr == NOADDR) {	    error("no source lines for \"%s\"", symname(f));	}	setsource(srcfilename(addr));	line = srcline(addr);	getsrcwindow(line, &l1, &l2);    } else {	eval(p->value.arg[0]);	l1 = (Lineno) (pop(long));	eval(p->value.arg[1]);	l2 = (Lineno) (pop(long));    }    printlines(l1, l2);}/* * Execute a func command. */private func (p)Node p;{    Symbol s, f;    Address addr;    if (p == nil) {	printname(stdout, curfunc);	putchar('\n');    } else {	s = p->value.sym;	if (isroutine(s)) {	    setcurfunc(s);	} else {	    find(f, s->name) where isroutine(f) endfind(f);	    if (f == nil) {		error("%s is not a procedure or function", symname(s));	    }	    setcurfunc(f);	}	addr = codeloc(curfunc);	if (addr != NOADDR) {	    setsource(srcfilename(addr));	    cursrcline = srcline(addr);	}    }}/* * Send a message to the current support person. */public gripe(){    typedef Operation();    Operation *old;    int pid, status;    extern int versionNumber;    char subject[100];#   ifdef MAINTAINER	puts("Type control-D to end your message.  Be sure to include");	puts("your name and the name of the file you are debugging.");	putchar('\n');	old = signal(SIGINT, SIG_DFL);	sprintf(subject, "dbx (version 3.%d) gripe", versionNumber);	pid = back("Mail", stdin, stdout, "-s", subject, MAINTAINER, nil);	signal(SIGINT, SIG_IGN);	pwait(pid, &status);	signal(SIGINT, old);	if (status == 0) {	    puts("Thank you.");	} else {	    puts("\nMail not sent.");	}#   else	puts("Sorry, no dbx maintainer available to gripe to.");	puts("Try contacting your system manager.");#   endif}/* * Give the user some help. */public help(){    puts("run                    - begin execution of the program");    puts("print <exp>            - print the value of the expression");    puts("where                  - print currently active procedures");    puts("stop at <line>         - suspend execution at the line");    puts("stop in <proc>         - suspend execution when <proc> is called");    puts("cont                   - continue execution");    puts("step                   - single step one line");    puts("next                   - step to next line (skip over calls)");    puts("trace <line#>          - trace execution of the line");    puts("trace <proc>           - trace calls to the procedure");    puts("trace <var>            - trace changes to the variable");    puts("trace <exp> at <line#> - print <exp> when <line> is reached");    puts("status                 - print trace/stop's in effect");    puts("delete <number>        - remove trace or stop of given number");    puts("call <proc>            - call a procedure in program");    puts("whatis <name>          - print the declaration of the name");    puts("list <line>, <line>    - list source lines");    puts("gripe                  - send mail to the person in charge of dbx");    puts("quit                   - exit dbx");}/* * Divert output to the given file name. * Cannot redirect to an existing file. */private int so_fd;private Boolean notstdout;public setout(filename)String filename;{    File f;    f = fopen(filename, "r");    if (f != nil) {	fclose(f);	error("%s: file already exists", filename);    } else {	so_fd = dup(1);	close(1);	if (creat(filename, 0666) == nil) {	    unsetout();	    error("can't create %s", filename);	}	notstdout = true;    }}/* * Revert output to standard output. */public unsetout(){    fflush(stdout);    close(1);    if (dup(so_fd) != 1) {	panic("standard out dup failed");    }    close(so_fd);    notstdout = false;}/* * Determine is standard output is currently being redirected * to a file (as far as we know). */public Boolean isredirected(){    return notstdout;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -