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

📄 opcodes.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 1994 David I. Bell * Permission is granted to use, distribute, or modify this source, * provided that this copyright notice remains intact. * * Opcode execution module */#include "stdarg.h"#include "calc.h"#include "opcodes.h"#include "func.h"#include "symbol.h"#include "hist.h"#define	QUICKLOCALS	20		/* local vars to handle quickly */VALUE *stack;				/* current location of top of stack */static VALUE stackarray[MAXSTACK];	/* storage for stack */static VALUE oldvalue;			/* previous calculation value */static char *funcname;			/* function being executed */static long funcline;			/* function line being executed */FLAG traceflags;			/* current trace flags */int tab_ok = TRUE;			/* FALSE => don't print lading tabs *//* * Routine definitions */static void o_nop(), o_localaddr(), o_globaladdr(), o_paramaddr();static void o_globalvalue(), o_paramvalue(), o_number(), o_indexaddr();static void o_assign(), o_add(), o_sub(), o_mul(), o_div();static void o_mod(), o_save(), o_negate(), o_invert(), o_int(), o_frac();static void o_numerator(), o_denominator(), o_duplicate(), o_pop();static void o_jumpeq(), o_jumpne(), o_jump(), o_usercall(), o_getvalue();static void o_eq(), o_ne(), o_le(), o_ge(), o_lt(), o_gt(), o_preinc();static void o_postinc(), o_postdec(), o_debug(), o_print(), o_assignpop();static void o_zero(), o_one(), o_printeol(), o_printspace(), o_printstring();static void o_oldvalue(), o_quo(), o_power(), o_quit(), o_call(), o_swap();static void o_dupvalue(), o_getepsilon(), o_and(), o_or(), o_not();static void o_abs(), o_sgn(), o_isint(), o_condorjump(), o_condandjump();static void o_square(), o_string(), o_isnum(), o_undef(), o_isnull();static void o_matcreate(), o_ismat(), o_isstr(), o_getconfig(), o_predec();static void o_leftshift(), o_rightshift(), o_casejump();static void o_isodd(), o_iseven(), o_fiaddr(), o_fivalue(), o_argvalue();static void o_isreal(), o_imaginary(), o_re(), o_im(), o_conjugate();static void o_objcreate(), o_isobj(), o_norm(), o_elemaddr(), o_elemvalue();static void o_istype(), o_scale(), o_localvalue(), o_return(), o_islist();static void o_issimple(), o_cmp(), o_quomod(), o_setconfig(), o_setepsilon();static void o_printresult(), o_isfile(), o_isassoc(), o_eleminit();/* * Types of opcodes (depends on arguments saved after the opcode). */#define OPNUL	1	/* opcode has no arguments */#define OPONE	2	/* opcode has one integer argument */#define OPTWO	3	/* opcode has two integer arguments */#define OPJMP	4	/* opcode is a jump (with one pointer argument) */#define OPRET	5	/* opcode is a return (with no argument) */#define OPGLB	6	/* opcode has global symbol pointer argument */#define OPPAR	7	/* opcode has parameter index argument */#define OPLOC	8	/* opcode needs local variable pointer (with one arg) */#define OPSTR	9	/* opcode has a string constant arg */#define OPARG	10	/* opcode is given number of arguments */#define	OPSTI	11	/* opcode is static initialization *//* * Information about each opcode. */static struct opcode {	void (*o_func)();	/* routine to call for opcode */	int o_type;		/* type of opcode */	char *o_name;		/* name of opcode */} opcodes[MAX_OPCODE+1] = {	o_nop,		OPNUL,  "NOP",		/* no operation */	o_localaddr,	OPLOC,  "LOCALADDR",	/* address of local variable */	o_globaladdr,	OPGLB,  "GLOBALADDR",	/* address of global variable */	o_paramaddr,	OPPAR,  "PARAMADDR",	/* address of paramater variable */	o_localvalue,	OPLOC,  "LOCALVALUE",	/* value of local variable */	o_globalvalue,	OPGLB,  "GLOBALVALUE",	/* value of global variable */	o_paramvalue,	OPPAR,  "PARAMVALUE", 	/* value of paramater variable */	o_number,	OPONE,  "NUMBER",	/* constant real numeric value */	o_indexaddr,	OPTWO,  "INDEXADDR",	/* array index address */	o_printresult,	OPNUL,  "PRINTRESULT",	/* print result of top-level expression */	o_assign,	OPNUL,  "ASSIGN",	/* assign value to variable */	o_add,		OPNUL,  "ADD",		/* add top two values */	o_sub,		OPNUL,  "SUB",		/* subtract top two values */	o_mul,		OPNUL,  "MUL",		/* multiply top two values */	o_div,		OPNUL,  "DIV",		/* divide top two values */	o_mod,		OPNUL,  "MOD",		/* take mod of top two values */	o_save,		OPNUL,  "SAVE",		/* save value for later use */	o_negate,	OPNUL,  "NEGATE",	/* negate top value */	o_invert,	OPNUL,  "INVERT",	/* invert top value */	o_int,		OPNUL,  "INT",		/* take integer part */	o_frac,		OPNUL,  "FRAC",		/* take fraction part */	o_numerator,	OPNUL,  "NUMERATOR",	/* take numerator */	o_denominator,	OPNUL,  "DENOMINATOR",	/* take denominator */	o_duplicate,	OPNUL,  "DUPLICATE",	/* duplicate top value */	o_pop,		OPNUL,  "POP",		/* pop top value */	o_return,	OPRET,  "RETURN",	/* return value of function */	o_jumpeq,	OPJMP,  "JUMPEQ",	/* jump if value zero */	o_jumpne,	OPJMP,  "JUMPNE",	/* jump if value nonzero */	o_jump,		OPJMP,  "JUMP",		/* jump unconditionally */	o_usercall,	OPTWO,  "USERCALL",	/* call a user function */	o_getvalue,	OPNUL,  "GETVALUE",	/* convert address to value */	o_eq,		OPNUL,  "EQ",		/* test elements for equality */	o_ne,		OPNUL,  "NE",		/* test elements for inequality */	o_le,		OPNUL,  "LE",		/* test elements for <= */	o_ge,		OPNUL,  "GE",		/* test elements for >= */	o_lt,		OPNUL,  "LT",		/* test elements for < */	o_gt,		OPNUL,  "GT",		/* test elements for > */	o_preinc,	OPNUL,  "PREINC",	/* add one to variable (++x) */	o_predec,	OPNUL,  "PREDEC",	/* subtract one from variable (--x) */	o_postinc,	OPNUL,  "POSTINC",	/* add one to variable (x++) */	o_postdec,	OPNUL,  "POSTDEC",	/* subtract one from variable (x--) */	o_debug,	OPONE,  "DEBUG",	/* debugging point */	o_print,	OPONE,  "PRINT",	/* print value */	o_assignpop,	OPNUL,  "ASSIGNPOP",	/* assign to variable and pop it */	o_zero,		OPNUL,  "ZERO",		/* put zero on the stack */	o_one,		OPNUL,  "ONE",		/* put one on the stack */	o_printeol,	OPNUL,  "PRINTEOL",	/* print end of line */	o_printspace,	OPNUL,  "PRINTSPACE",	/* print a space */	o_printstring,	OPSTR,  "PRINTSTR",	/* print constant string */	o_dupvalue,	OPNUL,  "DUPVALUE",	/* duplicate value of top value */	o_oldvalue,	OPNUL,  "OLDVALUE",	/* old value from previous calc */	o_quo,		OPNUL,  "QUO",		/* integer quotient of top values */	o_power,	OPNUL,  "POWER",	/* value raised to a power */	o_quit,		OPSTR,  "QUIT",		/* quit program */	o_call,		OPTWO,  "CALL",		/* call built-in routine */	o_getepsilon,	OPNUL,  "GETEPSILON",	/* get allowed error for calculations */	o_and,		OPNUL,  "AND",		/* arithmetic and or top two values */	o_or,		OPNUL,  "OR",		/* arithmetic or of top two values */	o_not,		OPNUL,  "NOT",		/* logical not or top value */	o_abs,		OPNUL,  "ABS",		/* absolute value of top value */	o_sgn,		OPNUL,  "SGN",		/* sign of number */	o_isint,	OPNUL,  "ISINT",	/* whether number is an integer */	o_condorjump,	OPJMP,  "CONDORJUMP",	/* conditional or jump */	o_condandjump,	OPJMP,  "CONDANDJUMP",	/* conditional and jump */	o_square,	OPNUL,  "SQUARE",	/* square top value */	o_string,	OPSTR,  "STRING",	/* string constant value */	o_isnum,	OPNUL,  "ISNUM",	/* whether value is a number */	o_undef,	OPNUL,  "UNDEF",	/* load undefined value on stack */	o_isnull,	OPNUL,  "ISNULL",	/* whether value is the null value */	o_argvalue,	OPARG,  "ARGVALUE",	/* load value of arg (parameter) n */	o_matcreate,	OPONE,  "MATCREATE",	/* create matrix */	o_ismat,	OPNUL,  "ISMAT",	/* whether value is a matrix */	o_isstr,	OPNUL,  "ISSTR",	/* whether value is a string */	o_getconfig,	OPNUL,  "GETCONFIG",	/* get value of configuration parameter */	o_leftshift,	OPNUL,  "LEFTSHIFT",	/* left shift of integer */	o_rightshift,	OPNUL,  "RIGHTSHIFT",	/* right shift of integer */	o_casejump,	OPJMP,  "CASEJUMP",	/* test case and jump if not matched */	o_isodd,	OPNUL,  "ISODD",	/* whether value is odd integer */	o_iseven,	OPNUL,  "ISEVEN",	/* whether value is even integer */	o_fiaddr,	OPNUL,  "FIADDR",	/* 'fast index' matrix address */	o_fivalue,	OPNUL,  "FIVALUE",	/* 'fast index' matrix value */	o_isreal,	OPNUL,  "ISREAL",	/* whether value is real number */	o_imaginary,	OPONE,  "IMAGINARY",	/* constant imaginary numeric value */	o_re,		OPNUL,  "RE",		/* real part of complex number */	o_im,		OPNUL,  "IM",		/* imaginary part of complex number */	o_conjugate,	OPNUL,  "CONJUGATE",	/* complex conjugate */	o_objcreate,	OPONE,  "OBJCREATE",	/* create object */	o_isobj,	OPNUL,  "ISOBJ",	/* whether value is an object */	o_norm,		OPNUL,  "NORM",		/* norm of value (square of abs) */	o_elemaddr,	OPONE,  "ELEMADDR",	/* address of element of object */	o_elemvalue,	OPONE,  "ELEMVALUE",	/* value of element of object */	o_istype,	OPNUL,  "ISTYPE",	/* whether types are the same */	o_scale,	OPNUL,  "SCALE",	/* scale value by a power of two */	o_islist,	OPNUL,	"ISLIST",	/* whether value is a list */	o_swap,		OPNUL,	"SWAP",		/* swap values of two variables */	o_issimple,	OPNUL,	"ISSIMPLE",	/* whether value is simple type */	o_cmp,		OPNUL,	"CMP",		/* compare values returning -1, 0, 1 */	o_quomod,	OPNUL,	"QUOMOD",	/* calculate quotient and remainder */	o_setconfig,	OPNUL,	"SETCONFIG",	/* set configuration parameter */	o_setepsilon,	OPNUL,  "SETEPSILON",	/* set allowed error for calculations */	o_isfile,	OPNUL,  "ISFILE",	/* whether value is a file */	o_isassoc,	OPNUL,  "ISASSOC",	/* whether value is an association */	o_nop,		OPSTI,  "INITSTATIC",	/* once only code for static init */	o_eleminit,	OPONE,	"ELEMINIT"	/* assign element of matrix or object */};/* * Initialize the stack. */voidinitstack(){	int i;	/* on first init, setup the stack array */	if (stack == NULL) {		for (i=0; i < sizeof(stackarray)/sizeof(stackarray[0]); ++i) {			stackarray[i].v_type = V_NULL;			stackarray[i].v_subtype = V_NOSUBTYPE;		}		stack = stackarray;	/* on subsequent inits, free the old stack */	} else {		while (stack > stackarray) {			freevalue(stack--);		}	}}/* * Compute the result of a function by interpreting opcodes. * Arguments have just been pushed onto the evaluation stack. */voidcalculate(fp, argcount)	register FUNC *fp;		/* function to calculate */	int argcount;			/* number of arguments called with */{	register unsigned long pc;	/* current pc inside function */	register struct opcode *op;	/* current opcode pointer */	register VALUE *locals;		/* pointer to local variables */	long oldline;			/* old value of line counter */	unsigned int opnum;		/* current opcode number */	int origargcount;		/* original number of arguments */	int i;				/* loop counter */	BOOL dojump;			/* TRUE if jump is to occur */	char *oldname;			/* old function name being executed */	VALUE *beginstack;		/* beginning of stack frame */	VALUE *args;			/* pointer to function arguments */	VALUE retval;			/* function return value */	VALUE localtable[QUICKLOCALS];	/* some local variables */	oldname = funcname;	oldline = funcline;	funcname = fp->f_name;	funcline = 0;	origargcount = argcount;	while (argcount < fp->f_paramcount) {		stack++;		stack->v_type = V_NULL;		argcount++;	}	locals = localtable;	if (fp->f_localcount > QUICKLOCALS) {		locals = (VALUE *) malloc(sizeof(VALUE) * fp->f_localcount);		if (locals == NULL)			math_error("No memory for local variables");	}	for (i = 0; i < fp->f_localcount; i++) {		locals[i].v_num = qlink(&_qzero_);		locals[i].v_type = V_NUM;		locals[i].v_subtype = V_NOSUBTYPE;	}	pc = 0;	beginstack = stack;	args = beginstack - (argcount - 1);	for (;;) {		if (abortlevel >= ABORT_OPCODE)			math_error("Calculation aborted in opcode");		if (pc >= fp->f_opcodecount)			math_error("Function pc out of range");		if (stack > &stackarray[MAXSTACK-3])			math_error("Evaluation stack depth exceeded");		opnum = fp->f_opcodes[pc];		if (opnum > MAX_OPCODE)			math_error("Function opcode out of range");		op = &opcodes[opnum];		if (traceflags & TRACE_OPCODES) {			printf("%8s, pc %4ld:  ", fp->f_name, pc);			(void)dumpop(&fp->f_opcodes[pc]);		}		/*		 * Now call the opcode routine appropriately.		 */		pc++;		switch (op->o_type) {		case OPNUL:	/* no extra arguments */			(*op->o_func)(fp);			break;		case OPONE:	/* one extra integer argument */			(*op->o_func)(fp, fp->f_opcodes[pc++]);			break;		case OPTWO:	/* two extra integer arguments */			(*op->o_func)(fp, fp->f_opcodes[pc],				fp->f_opcodes[pc+1]);			pc += 2;			break;		case OPJMP:	/* jump opcodes (one extra pointer arg) */			dojump = FALSE;			(*op->o_func)(fp, &dojump);			if (dojump)				pc = fp->f_opcodes[pc];			else				pc++;			break;		case OPGLB:	/* global symbol reference (pointer arg) */		case OPSTR:	/* string constant address */			(*op->o_func)(fp, *((char **) &fp->f_opcodes[pc]));			pc += PTR_SIZE;			break;		case OPLOC:	/* local variable reference */			(*op->o_func)(fp, locals, fp->f_opcodes[pc++]);			break;		case OPPAR:	/* parameter variable reference */			(*op->o_func)(fp, argcount, args, fp->f_opcodes[pc++]);			break;		case OPARG:	/* parameter variable reference */			(*op->o_func)(fp, origargcount, args);			break;		case OPRET:	/* return from function */			if (stack->v_type == V_ADDR)				copyvalue(stack->v_addr, stack);			for (i = 0; i < fp->f_localcount; i++)				freevalue(&locals[i]);			if (locals != localtable)				free(locals);			if (stack != &beginstack[1])				math_error("Misaligned stack");			if (argcount <= 0) {				funcname = oldname;				funcline = oldline;				return;			}			retval = *stack--;			while (--argcount >= 0)				freevalue(stack--);			*++stack = retval;			funcname = oldname;			funcline = oldline;			return;		case OPSTI:	/* static initialization code */			fp->f_opcodes[pc++ - 1] = OP_JUMP;			break;				default:			math_error("Unknown opcode type");		}	}}/* * Dump an opcode at a particular address. * Returns the size of the opcode so that it can easily be skipped over. */intdumpop(pc)	long *pc;		/* location of the opcode */{	unsigned long op;	/* opcode number */	op = *pc++;	if (op <= MAX_OPCODE)		printf("%s", opcodes[op].o_name);	else		printf("OP%ld", op);	switch (op) {		case OP_LOCALADDR: case OP_LOCALVALUE:			printf(" %s\n", localname(*pc));			return 2;		case OP_GLOBALADDR: case OP_GLOBALVALUE:			printf(" %s\n", globalname(*((GLOBAL **) pc)));			return (1 + PTR_SIZE);		case OP_PARAMADDR: case OP_PARAMVALUE:			printf(" %s\n", paramname(*pc));			return 2;		case OP_PRINTSTRING: case OP_STRING:			printf(" \"%s\"\n", *((char **) pc));			return (1 + PTR_SIZE);		case OP_QUIT:			if (*(char **) pc)				printf(" \"%s\"\n", *((char **) pc));			else				printf("\n");			return (1 + PTR_SIZE);		case OP_INDEXADDR:			printf(" %ld %ld\n", pc[0], pc[1]);			return 3;		case OP_PRINT: case OP_JUMPEQ: case OP_JUMPNE: case OP_JUMP:		case OP_CONDORJUMP: case OP_CONDANDJUMP: case OP_CASEJUMP:		case OP_INITSTATIC: case OP_MATCREATE: case OP_OBJCREATE:			printf(" %ld\n", *pc);			return 2;		case OP_NUMBER: case OP_IMAGINARY:			qprintf(" %r\n", constvalue(*pc));			return 2;		case OP_DEBUG:			printf(" line %ld\n", *pc);			return 2;		case OP_CALL:			printf(" %s with %ld args\n", builtinname(pc[0]), pc[1]);			return 3;		case OP_USERCALL:			printf(" %s with %ld args\n", namefunc(pc[0]), pc[1]);			return 3;		default:			printf("\n");			return 1;	}}/* * The various opcodes */static voido_nop(){}static voido_localaddr(fp, locals, index)	FUNC *fp;	VALUE *locals;	long index;{	if ((unsigned long)index >= fp->f_localcount)		math_error("Bad local variable index");	locals += index;	stack++;	stack->v_addr = locals;	stack->v_type = V_ADDR;}/*ARGSUSED*/static voido_globaladdr(fp, sp)	FUNC *fp;	GLOBAL *sp;{	if (sp == NULL)		math_error("Global variable \"%s\" not initialized", sp->g_name);	stack++;	stack->v_addr = &sp->g_value;	stack->v_type = V_ADDR;}/*ARGSUSED*/static voido_paramaddr(fp, argcount, args, index)	FUNC *fp;	int argcount;	VALUE *args;	long index;{	if ((unsigned long)index >= argcount)		math_error("Bad parameter index");	args += index;	stack++;	if (args->v_type == V_ADDR)		stack->v_addr = args->v_addr;	else		stack->v_addr = args;	stack->v_type = V_ADDR;}static voido_localvalue(fp, locals, index)	FUNC *fp;	VALUE *locals;	long index;{	if ((unsigned long)index >= fp->f_localcount)		math_error("Bad local variable index");	locals += index;	copyvalue(locals, ++stack);}/*ARGSUSED*/static voido_globalvalue(fp, sp)	FUNC *fp;	GLOBAL *sp;		/* global symbol */{	if (sp == NULL)		math_error("Global variable not defined");	copyvalue(&sp->g_value, ++stack);}/*ARGSUSED*/static voido_paramvalue(fp, argcount, args, index)	FUNC *fp;	int argcount;	VALUE *args;	long index;{	if ((unsigned long)index >= argcount)		math_error("Bad paramaeter index");	args += index;	if (args->v_type == V_ADDR)		args = args->v_addr;	copyvalue(args, ++stack);}static voido_argvalue(fp, argcount, args)	FUNC *fp;	int argcount;	VALUE *args;{	VALUE *vp;	long index;	vp = stack;	if (vp->v_type == V_ADDR)		vp = vp->v_addr;	if ((vp->v_type != V_NUM) || qisneg(vp->v_num) ||		qisfrac(vp->v_num))			math_error("Illegal argument for arg function");	if (qiszero(vp->v_num)) {		if (stack->v_type == V_NUM)			qfree(stack->v_num);		stack->v_num = itoq((long) argcount);		stack->v_type = V_NUM;		return;	}	index = qtoi(vp->v_num) - 1;	if (stack->v_type == V_NUM)		qfree(stack->v_num);	stack--;	(void) o_paramvalue(fp, argcount, args, index);}/*ARGSUSED*/static voido_number(fp, arg)	FUNC *fp;	long arg;{	NUMBER *q;	q = constvalue(arg);	if (q == NULL)		math_error("Numeric constant value not found");	stack++;	stack->v_num = qlink(q);	stack->v_type = V_NUM;}/*ARGSUSED*/static voido_imaginary(fp, arg)	FUNC *fp;	long arg;{	NUMBER *q;	COMPLEX *c;	q = constvalue(arg);	if (q == NULL)		math_error("Numeric constant value not found");	stack++;	if (qiszero(q)) {		stack->v_num = qlink(q);		stack->v_type = V_NUM;		return;	}	c = comalloc();	c->real = qlink(&_qzero_);	c->imag = qlink(q);	stack->v_com = c;	stack->v_type = V_COM;}/*ARGSUSED*/static voido_string(fp, cp)	FUNC *fp;	char *cp;{	stack++;	stack->v_str = cp;	stack->v_type = V_STR;	stack->v_subtype = V_STRLITERAL;}static voido_undef(){	stack++;	stack->v_type = V_NULL;}/*ARGSUSED*/static voido_matcreate(fp, dim)	FUNC *fp;	long dim;{	register MATRIX *mp;	/* matrix being defined */	NUMBER *num1;		/* first number from stack */	NUMBER *num2;		/* second number from stack */	VALUE *vp;		/* value being defined */	VALUE *v1, *v2;	long min[MAXDIM];	/* minimum range */	long max[MAXDIM];	/* maximum range */	long i;			/* index */	long tmp;		/* temporary */	long size;		/* size of matrix */	if ((dim <= 0) || (dim > MAXDIM))		math_error("Bad dimension %ld for matrix", dim);	if (stack[-2*dim].v_type != V_ADDR)		math_error("Attempting to init matrix for non-address");	size = 1;	for (i = dim - 1; i >= 0; i--) {		v1 = &stack[-1];		v2 = &stack[0];		if (v1->v_type == V_ADDR)			v1 = v1->v_addr;		if (v2->v_type == V_ADDR)			v2 = v2->v_addr;		if ((v1->v_type != V_NUM) || (v2->v_type != V_NUM))			math_error("Non-numeric bounds for matrix");		num1 = v1->v_num;		num2 = v2->v_num;		if (qisfrac(num1) || qisfrac(num2))			math_error("Non-integral bounds for matrix");		if (zisbig(num1->num) || zisbig(num2->num))			math_error("Very large bounds for matrix");		min[i] = qtoi(num1);		max[i] = qtoi(num2);		if (min[i] > max[i]) {			tmp = min[i];			min[i] = max[i];			max[i] = tmp;		}		size *= (max[i] - min[i] + 1);		if (size > 10000000)			math_error("Very large size for matrix");		freevalue(stack--);		freevalue(stack--);	}	mp = matalloc(size);	mp->m_dim = dim;	for (i = 0; i < dim; i++) {		mp->m_min[i] = min[i];		mp->m_max[i] = max[i];

⌨️ 快捷键说明

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