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

📄 interp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * 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 PXDEBUGvoidinterpreter(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 + -