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

📄 obj.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * obj - object handling primitives * * Copyright (C) 1999-2006  David I. Bell * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General * Public License for more details. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL.  You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA. * * @(#) $Revision: 29.8 $ * @(#) $Id: obj.c,v 29.8 2006/05/20 08:43:55 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/RCS/obj.c,v $ * * Under source code control:	1990/02/15 01:48:19 * File existed as early as:	before 1990 * * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/ *//* * "Object" handling primitives. * This simply means that user-specified routines are called to perform * the indicated operations. */#include <stdio.h>#include "calc.h"#include "opcodes.h"#include "func.h"#include "symbol.h"#include "string.h"/* * Types of values returned by calling object routines. */#define A_VALUE 0	/* returns arbitrary value */#define A_INT	1	/* returns integer value */#define A_UNDEF 2	/* returns no value *//* * Error handling actions for when the function is undefined. */#define ERR_NONE	0	/* no special action */#define ERR_PRINT	1	/* print element */#define ERR_CMP 2	/* compare two values */#define ERR_TEST	3	/* test value for nonzero */#define ERR_POW 4	/* call generic power routine */#define ERR_ONE 5	/* return number 1 */#define ERR_INC 6	/* increment by one */#define ERR_DEC 7	/* decrement by one */#define ERR_SQUARE 8	/* square value */#define ERR_VALUE 9	/* return value */#define ERR_ASSIGN 10	/* assign value */static struct objectinfo {	short args;	/* number of arguments */	short retval;	/* type of return value */	short error;	/* special action on errors */	char *name;	/* name of function to call */	char *comment;	/* useful comment if any */} objectinfo[] = {	{1, A_UNDEF, ERR_PRINT, "print",	"print value, default prints elements"},	{1, A_VALUE, ERR_ONE,	"one",	"multiplicative identity, default is 1"},	{1, A_INT,   ERR_TEST,	"test", "logical test (false,true => 0,1), default tests elements"},	{2, A_VALUE, ERR_NONE,	"add",	NULL},	{2, A_VALUE, ERR_NONE,	"sub",	NULL},	{1, A_VALUE, ERR_NONE,	"neg",	"negative"},	{2, A_VALUE, ERR_NONE,	"mul",	NULL},	{2, A_VALUE, ERR_NONE,	"div",	"non-integral division"},	{1, A_VALUE, ERR_NONE,	"inv",	"multiplicative inverse"},	{2, A_VALUE, ERR_NONE,	"abs",	"absolute value within given error"},	{1, A_VALUE, ERR_NONE,	"norm", "square of absolute value"},	{1, A_VALUE, ERR_NONE,	"conj", "conjugate"},	{2, A_VALUE, ERR_POW,	"pow",	"integer power, default does multiply, square, inverse"},	{1, A_VALUE, ERR_NONE,	"sgn",	"sign of value (-1, 0, 1)"},	{2, A_INT,   ERR_CMP,	"cmp",	"equality (equal,nonequal => 0,1), default tests elements"},	{2, A_VALUE, ERR_NONE,	"rel",	"relative order, positive for >, etc."},	{3, A_VALUE, ERR_NONE,	"quo",	"integer quotient"},	{3, A_VALUE, ERR_NONE,	"mod",	"remainder of division"},	{1, A_VALUE, ERR_NONE,	"int",	"integer part"},	{1, A_VALUE, ERR_NONE,	"frac", "fractional part"},	{1, A_VALUE, ERR_INC,	"inc",	"increment, default adds 1"},	{1, A_VALUE, ERR_DEC,	"dec",	"decrement, default subtracts 1"},	{1, A_VALUE, ERR_SQUARE,"square",	"default multiplies by itself"},	{2, A_VALUE, ERR_NONE,	"scale",	"multiply by power of 2"},	{2, A_VALUE, ERR_NONE,	"shift",	"shift left by n bits (right if negative)"},	{3, A_VALUE, ERR_NONE,	"round",	"round to given number of decimal places"},	{3, A_VALUE, ERR_NONE,	"bround",	"round to given number of binary places"},	{3, A_VALUE, ERR_NONE,	"root", "root of value within given error"},	{3, A_VALUE, ERR_NONE,	"sqrt", "square root within given error"},	{2, A_VALUE, ERR_NONE,	"or",	"bitwise or"},	{2, A_VALUE, ERR_NONE,	"and",	"bitwise and"},	{1, A_VALUE, ERR_NONE,	"not",	"logical not"},	{1, A_VALUE, ERR_NONE,	"fact", "factorial or postfix !"},	{1, A_VALUE, ERR_VALUE, "min",	"value for min(...)"},	{1, A_VALUE, ERR_VALUE, "max",	"value for max(...)"},	{1, A_VALUE, ERR_VALUE, "sum",	"value for sum(...)"},	{2, A_UNDEF, ERR_ASSIGN, "assign", "assign, defaults to a = b"},	{2, A_VALUE, ERR_NONE,	"xor",	"value for binary ~"},	{1, A_VALUE, ERR_NONE,	"comp", "value for unary ~"},	{1, A_VALUE, ERR_NONE,	"content", "unary hash op"},	{2, A_VALUE, ERR_NONE,	"hashop",  "binary hash op"},	{1, A_VALUE, ERR_NONE,	"backslash", "unary backslash op"},	{2, A_VALUE, ERR_NONE,	"setminus", "binary backslash op"},	{1, A_VALUE, ERR_NONE,	"plus", "unary + op"},	{0, 0, 0, NULL, NULL}};static STRINGHEAD objectnames;	/* names of objects */static STRINGHEAD elements;	/* element names for parts of objects */static OBJECTACTIONS **objects; /* table of actions for objects */#define OBJALLOC 16static long maxobjcount = 0;static VALUE objpowi(VALUE *vp, NUMBER *q);static BOOL objtest(OBJECT *op);static BOOL objcmp(OBJECT *op1, OBJECT *op2);static void objprint(OBJECT *op);/* * Show all the routine names available for objects. */voidshowobjfuncs(void){	register struct objectinfo *oip;	printf("\nThe following object routines are definable.\n");	printf("Note: xx represents the actual object type name.\n\n");	printf("Name	Args	Comments\n");	for (oip = objectinfo; oip->name; oip++) {		printf("xx_%-8s %d	%s\n", oip->name, oip->args,			oip->comment ? oip->comment : "");	}	printf("\n");}/* * Call the appropriate user-defined routine to handle an object action. * Returns the value that the routine returned. */VALUEobjcall(int action, VALUE *v1, VALUE *v2, VALUE *v3){	FUNC *fp;		/* function to call */	static OBJECTACTIONS *oap; /* object to call for */	struct objectinfo *oip; /* information about action */	long index;		/* index of function (negative if undefined) */	VALUE val;		/* return value */	VALUE tmp;		/* temp value */	char name[SYMBOLSIZE+1+1];	/* full name of user routine to call */	size_t namestr_len;	/* length of the namestr() return string */	char *namestr_ret;	/* namestr() return string */	size_t opi_name_len;	/* length of the oip name */	/* initialize VALUEs */	val.v_subtype = V_NOSUBTYPE;	tmp.v_subtype = V_NOSUBTYPE;	if ((unsigned)action > OBJ_MAXFUNC) {		math_error("Illegal action for object call");		/*NOTREACHED*/	}	oip = &objectinfo[action];	if (v1->v_type == V_OBJ) {		oap = v1->v_obj->o_actions;	} else if (v2->v_type == V_OBJ) {		oap = v2->v_obj->o_actions;	} else {		math_error("Object routine called with non-object");		/*NOTREACHED*/	}	index = oap->oa_indices[action];	if (index < 0) {		namestr_ret = namestr(&objectnames, oap->oa_index);		if (namestr_ret == NULL) {			math_error("namestr returned NULL!!!");			/*NOTREACHED*/		}		namestr_len = strlen(namestr_ret);		opi_name_len = strlen(oip->name);		if (namestr_len > (size_t)SYMBOLSIZE-1-opi_name_len) {			math_error("namestr returned a strong too long!!!");			/*NOTREACHED*/		}		name[0] = '\0';		strncpy(name, namestr_ret, namestr_len+1);		strcat(name, "_");		strncat(name, oip->name, opi_name_len+1);		index = adduserfunc(name);		oap->oa_indices[action] = index;	}	fp = NULL;	if (index >= 0)		fp = findfunc(index);	if (fp == NULL) {		switch (oip->error) {		case ERR_PRINT:			objprint(v1->v_obj);			val.v_type = V_NULL;			break;		case ERR_CMP:			val.v_type = V_INT;			if (v1->v_type != v2->v_type) {				val.v_int = 1;				return val;			}			val.v_int = objcmp(v1->v_obj, v2->v_obj);			break;		case ERR_TEST:			val.v_type = V_INT;			val.v_int = objtest(v1->v_obj);			break;		case ERR_POW:			if (v2->v_type != V_NUM) {				math_error("Non-real power");				/*NOTREACHED*/			}			val = objpowi(v1, v2->v_num);			break;		case ERR_ONE:			val.v_type = V_NUM;			val.v_num = qlink(&_qone_);			break;		case ERR_INC:			tmp.v_type = V_NUM;			tmp.v_num = &_qone_;			val = objcall(OBJ_ADD, v1, &tmp, NULL_VALUE);			break;		case ERR_DEC:			tmp.v_type = V_NUM;			tmp.v_num = &_qone_;			val = objcall(OBJ_SUB, v1, &tmp, NULL_VALUE);			break;		case ERR_SQUARE:			val = objcall(OBJ_MUL, v1, v1, NULL_VALUE);			break;		case ERR_VALUE:			copyvalue(v1, &val);			break;		case ERR_ASSIGN:			copyvalue(v2, &tmp);			tmp.v_subtype |= v1->v_subtype;			freevalue(v1);			*v1 = tmp;			val.v_type = V_NULL;			break;		default:			math_error("Function \"%s\" is undefined", namefunc(index));			/*NOTREACHED*/		}		return val;	}	switch (oip->args) {	case 0:		break;	case 1:		++stack;		stack->v_addr = v1;		stack->v_type = V_ADDR;		break;	case 2:		++stack;		stack->v_addr = v1;		stack->v_type = V_ADDR;		++stack;		stack->v_addr = v2;		stack->v_type = V_ADDR;		break;	case 3:		++stack;		stack->v_addr = v1;		stack->v_type = V_ADDR;		++stack;		stack->v_addr = v2;		stack->v_type = V_ADDR;		++stack;		stack->v_addr = v3;		stack->v_type = V_ADDR;		break;	default:		math_error("Bad number of args to calculate");		/*NOTREACHED*/	}	calculate(fp, oip->args);	switch (oip->retval) {	case A_VALUE:		return *stack--;	case A_UNDEF:		freevalue(stack--);		val.v_type = V_NULL;		break;	case A_INT:		if ((stack->v_type != V_NUM) || qisfrac(stack->v_num)) {			math_error("Integer return value required");			/*NOTREACHED*/		}		index = qtoi(stack->v_num);		qfree(stack->v_num);		stack--;		val.v_type = V_INT;		val.v_int = index;		break;	default:		math_error("Bad object return");		/*NOTREACHED*/	}	return val;}/* * Print the elements of an object in short and unambiguous format. * This is the default routine if the user's is not defined. * * given: *	op		object being printed */static voidobjprint(OBJECT *op){	int count;		/* number of elements */	int i;			/* index */	count = op->o_actions->oa_count;	math_fmt("obj %s {", namestr(&objectnames, op->o_actions->oa_index));	for (i = 0; i < count; i++) {		if (i)			math_str(", ");		printvalue(&op->o_table[i], PRINT_SHORT | PRINT_UNAMBIG);	}	math_chr('}');}/* * Test an object for being "nonzero". * This is the default routine if the user's is not defined. * Returns TRUE if any of the elements are "nonzero". */static BOOLobjtest(OBJECT *op){	int i;			/* loop counter */	i = op->o_actions->oa_count;	while (--i >= 0) {		if (testvalue(&op->o_table[i]))			return TRUE;	}	return FALSE;}/* * Compare two objects for equality, returning TRUE if they differ. * This is the default routine if the user's is not defined. * For equality, all elements must be equal. */static BOOLobjcmp(OBJECT *op1, OBJECT *op2){	int i;			/* loop counter */	if (op1->o_actions != op2->o_actions)		return TRUE;

⌨️ 快捷键说明

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