📄 interp.c
字号:
/*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)interp.c 8.1 (Berkeley) 6/6/93";#endif /* not lint */#include <math.h>#include <signal.h>#include "whoami.h"#include "vars.h"#include "objfmt.h"#include "h02opcs.h"#include "machdep.h"#include "libpc.h"/* * program variables */union display _display;struct dispsave *_dp;long _lino = 0;int _argc;char **_argv;long _mode;long _runtst = (long)TRUE;bool _nodump = FALSE;long _stlim = 500000;long _stcnt = 0;long _seed = 1;#ifdef ADDR32char *_minptr = (char *)0x7fffffff;#endif ADDR32#ifdef ADDR16char *_minptr = (char *)0xffff;#endif ADDR16char *_maxptr = (char *)0;long *_pcpcount = (long *)0;long _cntrs = 0;long _rtns = 0;/* * standard files */char _inwin, _outwin, _errwin;struct iorechd _err = { &_errwin, /* fileptr */ 0, /* lcount */ 0x7fffffff, /* llimit */ stderr, /* fbuf */ FILNIL, /* fchain */ STDLVL, /* flev */ "Message file", /* pfname */ FTEXT | FWRITE | EOFF, /* funit */ 2, /* fblk */ 1 /* fsize */};struct iorechd output = { &_outwin, /* fileptr */ 0, /* lcount */ 0x7fffffff, /* llimit */ stdout, /* fbuf */ ERR, /* fchain */ STDLVL, /* flev */ "standard output", /* pfname */ FTEXT | FWRITE | EOFF, /* funit */ 1, /* fblk */ 1 /* fsize */};struct iorechd input = { &_inwin, /* fileptr */ 0, /* lcount */ 0x7fffffff, /* llimit */ stdin, /* fbuf */ OUTPUT, /* fchain */ STDLVL, /* flev */ "standard input", /* pfname */ FTEXT|FREAD|SYNC|EOLN, /* funit */ 0, /* fblk */ 1 /* fsize */};/* * file record variables */long _filefre = PREDEF;struct iorechd _fchain = { 0, 0, 0, 0, /* only use fchain field */ INPUT /* fchain */};struct iorec *_actfile[MAXFILES] = { INPUT, OUTPUT, ERR};/* * stuff for pdx to watch what the interpreter is doing. * The .globl is #ifndef DBX since it breaks DBX to have a global * asm label in the middle of a function (see _loopaddr: below). */union progcntr pdx_pc;#ifndef DBXasm(".globl _loopaddr");#endif DBX/* * Px profile array */#ifdef PROFILElong _profcnts[NUMOPS];#endif PROFILE/* * debugging variables */#ifdef PXDEBUGchar opc[10];long opcptr = 9;#endif PXDEBUGvoidinterpreter(base) char *base;{ /* register */ union progcntr pc; /* interpreted program cntr */ struct iorec *curfile; /* active file */ register struct blockmark *stp; /* active stack frame ptr */ /* * the following variables are used as scratch */ register char *tcp; register short *tsp; register long tl, tl1, tl2, tl3; char *tcp2; long tl4; double td, td1; struct sze8 t8; register short *tsp1; long *tlp; char *tcp1; bool tb; struct blockmark *tstp; register struct formalrtn *tfp; struct iorec **ip; int mypid; int ti, ti2; short ts; FILE *tf; /* register */ union progcntr stack; /* Interpreted stack */ mypid = getpid(); /* * Setup sets up any hardware specific parameters before * starting the interpreter. Typically this is macro- or inline- * replaced by "machdep.h" or interp.sed. */ setup(); /* * necessary only on systems which do not initialize * memory to zero */ for (ip = &_actfile[3]; ip < &_actfile[MAXFILES]; *ip++ = FILNIL) /* void */; /* * set up global environment, then ``call'' the main program */ STACKALIGN(tl, 2 * sizeof(struct iorec *)); _display.frame[0].locvars = pushsp(tl); _display.frame[0].locvars += 2 * sizeof(struct iorec *); *(struct iorec **)(_display.frame[0].locvars + OUTPUT_OFF) = OUTPUT; *(struct iorec **)(_display.frame[0].locvars + INPUT_OFF) = INPUT; STACKALIGN(tl, sizeof(struct blockmark)); stp = (struct blockmark *)pushsp(tl); _dp = &_display.frame[0]; pc.cp = base; for(;;) {# ifdef PXDEBUG if (++opcptr == 10) opcptr = 0; opc[opcptr] = *pc.ucp;# endif PXDEBUG# ifdef PROFILE _profcnts[*pc.ucp]++;# endif PROFILE /* * Save away the program counter to a fixed location for pdx. */ pdx_pc = pc; /* * Having the label below makes dbx not work * to debug this interpreter, * since it thinks a new function called loopaddr() * has started here, and it won't display the local * variables of interpreter(). You have to compile * -DDBX to avoid this problem... */# ifndef DBX ;asm("_loopaddr:");# endif DBX switch (*pc.ucp++) { case O_BPT: /* breakpoint trap */ PFLUSH(); kill(mypid, SIGILL); pc.ucp--; continue; case O_NODUMP: _nodump = TRUE; /* and fall through */ case O_BEG: _dp += 1; /* enter local scope */ stp->odisp = *_dp; /* save old display value */ tl = *pc.ucp++; /* tl = name size */ stp->entry = pc.hdrp; /* pointer to entry info */ tl1 = pc.hdrp->framesze;/* tl1 = size of frame */ _lino = pc.hdrp->offset; _runtst = pc.hdrp->tests; disableovrflo(); if (_runtst) enableovrflo(); pc.cp += (int)tl; /* skip over proc hdr info */ stp->file = curfile; /* save active file */ STACKALIGN(tl2, tl1); tcp = pushsp(tl2); /* tcp = new top of stack */ if (_runtst) /* zero stack frame */ blkclr(tcp, tl1); tcp += (int)tl1; /* offsets of locals are neg */ _dp->locvars = tcp; /* set new display pointer */ _dp->stp = stp; stp->tos = pushsp((long)0); /* set tos pointer */ continue; case O_END: PCLOSE(_dp->locvars); /* flush & close local files */ stp = _dp->stp; curfile = stp->file; /* restore old active file */ *_dp = stp->odisp; /* restore old display entry */ if (_dp == &_display.frame[1]) return; /* exiting main proc ??? */ _lino = stp->lino; /* restore lino, pc, dp */ pc.cp = stp->pc; _dp = stp->dp; _runtst = stp->entry->tests; disableovrflo(); if (_runtst) enableovrflo(); STACKALIGN(tl, stp->entry->framesze); STACKALIGN(tl1, sizeof(struct blockmark)); popsp(tl + /* pop local vars */ tl1 + /* pop stack frame */ stp->entry->nargs);/* pop parms */ continue; case O_CALL: tl = *pc.cp++; PCLONGVAL(tl1); tcp = base + tl1 + sizeof(short);/* new entry point */ GETLONGVAL(tl1, tcp); tcp = base + tl1; STACKALIGN(tl1, sizeof(struct blockmark)); stp = (struct blockmark *)pushsp(tl1); stp->lino = _lino; /* save lino, pc, dp */ stp->pc = pc.cp; stp->dp = _dp; _dp = &_display.frame[tl]; /* set up new display ptr */ pc.cp = tcp; continue; case O_FCALL: pc.cp++; tcp = popaddr(); /* ptr to display save area */ tfp = (struct formalrtn *)popaddr(); STACKALIGN(tl, sizeof(struct blockmark)); stp = (struct blockmark *)pushsp(tl); stp->lino = _lino; /* save lino, pc, dp */ stp->pc = pc.cp; stp->dp = _dp; pc.cp = (char *)(tfp->fentryaddr);/* new entry point */ _dp = &_display.frame[tfp->fbn];/* new display ptr */ blkcpy(&_display.frame[1], tcp, tfp->fbn * sizeof(struct dispsave)); blkcpy(&tfp->fdisp[0], &_display.frame[1], tfp->fbn * sizeof(struct dispsave)); continue; case O_FRTN: tl = *pc.cp++; /* tl = size of return obj */ if (tl == 0) tl = *pc.usp++; tcp = pushsp((long)(0)); tfp = *(struct formalrtn **)(tcp + tl); tcp1 = *(char **) (tcp + tl + sizeof(struct formalrtn *)); if (tl != 0) { blkcpy(tcp, tcp + sizeof(struct formalrtn *) + sizeof(char *), tl); } STACKALIGN(tl, sizeof(struct formalrtn *) + sizeof (char *)); popsp(tl); blkcpy(tcp1, &_display.frame[1], tfp->fbn * sizeof(struct dispsave)); continue; case O_FSAV: tfp = (struct formalrtn *)popaddr(); tfp->fbn = *pc.cp++; /* blk number of routine */ PCLONGVAL(tl); tcp = base + tl + sizeof(short);/* new entry point */ GETLONGVAL(tl, tcp); tfp->fentryaddr = (long (*)())(base + tl); blkcpy(&_display.frame[1], &tfp->fdisp[0], tfp->fbn * sizeof(struct dispsave)); pushaddr(tfp); continue; case O_SDUP2: pc.cp++; tl = pop2(); push2((short)(tl)); push2((short)(tl)); continue; case O_SDUP4: pc.cp++; tl = pop4(); push4(tl); push4(tl); continue; case O_TRA: pc.cp++; pc.cp += *pc.sp; continue; case O_TRA4: pc.cp++; PCLONGVAL(tl); pc.cp = base + tl; continue; case O_GOTO: tstp = _display.frame[*pc.cp++].stp; /* ptr to exit frame */ PCLONGVAL(tl); pc.cp = base + tl; stp = _dp->stp; while (tstp != stp) { if (_dp == &_display.frame[1]) ERROR("Active frame not found in non-local goto\n", 0); /* exiting prog ??? */ PCLOSE(_dp->locvars); /* close local files */ curfile = stp->file; /* restore active file */ *_dp = stp->odisp; /* old display entry */ _dp = stp->dp; /* restore dp */ stp = _dp->stp; } /* pop locals, stack frame, parms, and return values */ popsp((long)(stp->tos - pushsp((long)(0)))); continue; case O_LINO: if (_dp->stp->tos != pushsp((long)(0))) ERROR("Panic: stack not empty between statements\n"); _lino = *pc.cp++; /* set line number */ if (_lino == 0) _lino = *pc.sp++; if (_runtst) { LINO(); /* inc statement count */ continue; } _stcnt++; continue; case O_PUSH: tl = *pc.cp++; if (tl == 0) PCLONGVAL(tl); STACKALIGN(tl1, -tl); tcp = pushsp(tl1); if (_runtst) blkclr(tcp, tl1); continue; case O_IF: pc.cp++; if (pop2()) { pc.sp++; continue; } pc.cp += *pc.sp; continue; case O_REL2: tl = pop2(); tl1 = pop2(); goto cmplong; case O_REL24: tl = pop2(); tl1 = pop4(); goto cmplong; case O_REL42: tl = pop4(); tl1 = pop2(); goto cmplong; case O_REL4: tl = pop4(); tl1 = pop4(); cmplong: switch (*pc.cp++) { case releq: push2(tl1 == tl); continue; case relne: push2(tl1 != tl); continue; case rellt: push2(tl1 < tl); continue; case relgt: push2(tl1 > tl); continue; case relle: push2(tl1 <= tl); continue; case relge: push2(tl1 >= tl); continue; default: ERROR("Panic: bad relation %d to REL4*\n", *(pc.cp - 1)); continue; } case O_RELG: tl2 = *pc.cp++; /* tc has jump opcode */ tl = *pc.usp++; /* tl has comparison length */ STACKALIGN(tl1, tl); /* tl1 has arg stack length */ tcp = pushsp((long)(0));/* tcp pts to first arg */ switch (tl2) { case releq: tb = RELEQ(tl, tcp + tl1, tcp); break; case relne: tb = RELNE(tl, tcp + tl1, tcp); break; case rellt: tb = RELSLT(tl, tcp + tl1, tcp); break; case relgt: tb = RELSGT(tl, tcp + tl1, tcp); break; case relle: tb = RELSLE(tl, tcp + tl1, tcp); break; case relge: tb = RELSGE(tl, tcp + tl1, tcp); break; default: ERROR("Panic: bad relation %d to RELG*\n", tl2); break; } popsp(tl1 << 1); push2((short)(tb)); continue; case O_RELT: tl2 = *pc.cp++; /* tc has jump opcode */ tl1 = *pc.usp++; /* tl1 has comparison length */ tcp = pushsp((long)(0));/* tcp pts to first arg */ switch (tl2) { case releq: tb = RELEQ(tl1, tcp + tl1, tcp); break; case relne: tb = RELNE(tl1, tcp + tl1, tcp); break; case rellt: tb = RELTLT(tl1, tcp + tl1, tcp); break; case relgt: tb = RELTGT(tl1, tcp + tl1, tcp); break; case relle: tb = RELTLE(tl1, tcp + tl1, tcp); break; case relge: tb = RELTGE(tl1, tcp + tl1, tcp); break; default: ERROR("Panic: bad relation %d to RELT*\n", tl2); break; } STACKALIGN(tl, tl1); popsp(tl << 1); push2((short)(tb)); continue; case O_REL28: td = pop2(); td1 = pop8(); goto cmpdbl; case O_REL48: td = pop4(); td1 = pop8(); goto cmpdbl; case O_REL82: td = pop8(); td1 = pop2(); goto cmpdbl; case O_REL84: td = pop8(); td1 = pop4(); goto cmpdbl; case O_REL8: td = pop8(); td1 = pop8(); cmpdbl: switch (*pc.cp++) { case releq: push2(td1 == td); continue; case relne: push2(td1 != td); continue; case rellt: push2(td1 < td); continue; case relgt: push2(td1 > td); continue; case relle: push2(td1 <= td); continue; case relge: push2(td1 >= td); continue; default: ERROR("Panic: bad relation %d to REL8*\n", *(pc.cp - 1)); continue; } case O_AND: pc.cp++; tl = pop2(); tl1 = pop2(); push2(tl1 & tl); continue; case O_OR: pc.cp++; tl = pop2(); tl1 = pop2(); push2(tl1 | tl); continue; case O_NOT: pc.cp++; tl = pop2(); push2(tl ^ 1); continue; case O_AS2: pc.cp++; tl = pop2(); *(short *)popaddr() = tl; continue; case O_AS4: pc.cp++; tl = pop4(); *(long *)popaddr() = tl; continue; case O_AS24: pc.cp++; tl = pop2(); *(long *)popaddr() = tl; continue; case O_AS42: pc.cp++; tl = pop4(); *(short *)popaddr() = tl; continue; case O_AS21: pc.cp++; tl = pop2(); *popaddr() = tl; continue; case O_AS41: pc.cp++; tl = pop4(); *popaddr() = tl; continue; case O_AS28: pc.cp++; tl = pop2(); *(double *)popaddr() = tl; continue; case O_AS48: pc.cp++; tl = pop4(); *(double *)popaddr() = tl; continue; case O_AS8: pc.cp++; t8 = popsze8(); *(struct sze8 *)popaddr() = t8; continue; case O_AS: tl = *pc.cp++; if (tl == 0) tl = *pc.usp++; STACKALIGN(tl1, tl); tcp = pushsp((long)(0)); blkcpy(tcp, *(char **)(tcp + tl1), tl); popsp(tl1 + sizeof(char *)); continue; case O_VAS: pc.cp++; tl = pop4(); tcp1 = popaddr(); tcp = popaddr(); blkcpy(tcp1, tcp, tl); continue; case O_INX2P2: tl = *pc.cp++; /* tl has shift amount */ tl1 = pop2(); tl1 = (tl1 - *pc.sp++) << tl; tcp = popaddr(); pushaddr(tcp + tl1); continue; case O_INX4P2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -