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

📄 value.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * value - generic value manipulation routines * * 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.10 $ * @(#) $Id: value.c,v 29.10 2006/08/20 15:01:30 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/RCS/value.c,v $ * * Under source code control:	1990/02/15 01:48:25 * File existed as early as:	before 1990 * * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/ */#include <stdio.h>#include <sys/types.h>#include "value.h"#include "opcodes.h"#include "func.h"#include "symbol.h"#include "string.h"#include "zrand.h"#include "zrandom.h"#include "cmath.h"#include "nametype.h"#include "file.h"#include "config.h"#define LINELEN 80		/* length of a typical tty line *//* * Free a value and set its type to undefined. * * given: *	vp		value to be freed */voidfreevalue(VALUE *vp){	int type;		/* type of value being freed */	type = vp->v_type;	vp->v_type = V_NULL;	vp->v_subtype = V_NOSUBTYPE;	if (type <= 0)		return;	switch (type) {	case V_ADDR:	case V_OCTET:	case V_NBLOCK:	case V_FILE:	case V_VPTR:	case V_OPTR:	case V_SPTR:	case V_NPTR:		/* nothing to free */		break;	case V_STR:		sfree(vp->v_str);		break;	case V_NUM:		qfree(vp->v_num);		break;	case V_COM:		comfree(vp->v_com);		break;	case V_MAT:		matfree(vp->v_mat);		break;	case V_LIST:		listfree(vp->v_list);		break;	case V_ASSOC:		assocfree(vp->v_assoc);		break;	case V_OBJ:		objfree(vp->v_obj);		break;	case V_RAND:		randfree(vp->v_rand);		break;	case V_RANDOM:		randomfree(vp->v_random);		break;	case V_CONFIG:		config_free(vp->v_config);		break;	case V_HASH:		hash_free(vp->v_hash);		break;	case V_BLOCK:		blk_free(vp->v_block);		break;	default:		math_error("Freeing unknown value type");		/*NOTREACHED*/	}}/* * Set protection status for a value and all of its components */voidprotecttodepth(VALUE *vp, int sts, int depth){	VALUE *vq;	int i;	LISTELEM *ep;	ASSOC *ap;	if (vp->v_type == V_NBLOCK) {		if (sts > 0)			vp->v_nblock->subtype |= sts;		else if (sts < 0)			vp->v_nblock->subtype &= ~(-sts);		else vp->v_nblock->subtype = 0;		return;	}	if (sts > 0)		vp->v_subtype |= sts;	else if (sts < 0)		vp->v_subtype &= ~(-sts);	else		vp->v_subtype = 0;	if (depth > 0) {	    switch(vp->v_type) {	    case V_MAT:		    vq = vp->v_mat->m_table;		    i = vp->v_mat->m_size;		    while (i-- > 0)			    protecttodepth(vq++, sts, depth - 1);		    break;	    case V_LIST:		    for (ep = vp->v_list->l_first; ep; ep = ep->e_next)			    protecttodepth(&ep->e_value, sts, depth - 1);		    break;	    case V_OBJ:		    vq = vp->v_obj->o_table;		    i = vp->v_obj->o_actions->oa_count;		    while (i-- > 0)			    protecttodepth(vq++, sts, depth - 1);		    break;	    case V_ASSOC:		    ap = vp->v_assoc;		    for (i = 0; i < ap->a_count; i++)			    protecttodepth(assocfindex(ap, i), sts, depth - 1);	    }	}}/* * Copy a value from one location to another. * This overwrites the specified new value without checking it. * * given: *	oldvp		value to be copied from *	newvp		value to be copied into */voidcopyvalue(VALUE *oldvp, VALUE *newvp){	newvp->v_type = oldvp->v_type;	if (oldvp->v_type >= 0) {		switch (oldvp->v_type) {		case V_NULL:		case V_ADDR:		case V_VPTR:		case V_OPTR:		case V_SPTR:		case V_NPTR:			*newvp = *oldvp;			break;		case V_FILE:			newvp->v_file = oldvp->v_file;			break;		case V_NUM:			newvp->v_num = qlink(oldvp->v_num);			break;		case V_COM:			newvp->v_com = clink(oldvp->v_com);			break;		case V_STR:			newvp->v_str = slink(oldvp->v_str);			break;		case V_MAT:			newvp->v_mat = matcopy(oldvp->v_mat);			break;		case V_LIST:			newvp->v_list = listcopy(oldvp->v_list);			break;		case V_ASSOC:			newvp->v_assoc = assoccopy(oldvp->v_assoc);			break;		case V_OBJ:			newvp->v_obj = objcopy(oldvp->v_obj);			break;		case V_RAND:			newvp->v_rand = randcopy(oldvp->v_rand);			break;		case V_RANDOM:			newvp->v_random = randomcopy(oldvp->v_random);			break;		case V_CONFIG:			newvp->v_config = config_copy(oldvp->v_config);			break;		case V_HASH:			newvp->v_hash = hash_copy(oldvp->v_hash);			break;		case V_BLOCK:			newvp->v_block = blk_copy(oldvp->v_block);			break;		case V_OCTET:			newvp->v_type = V_NUM;			newvp->v_num = itoq((long) *oldvp->v_octet);			break;		case V_NBLOCK:			newvp->v_nblock = oldvp->v_nblock;			break;		default:			math_error("Copying unknown value type");			/*NOTREACHED*/		}	}	newvp->v_subtype = oldvp->v_subtype;}/* * copy the low order 8 bits of a value to an octet */voidcopy2octet(VALUE *vp, OCTET *op){	USB8 oval;	/* low order 8 bits to store into OCTET */	NUMBER *q;	HALF h;	if (vp->v_type == V_ADDR)		vp = vp->v_addr;	oval = 0;	/*	 * we can (at the moment) only store certain types	 * values into an OCTET, so get the low order 8 bits	 * of these particular value types	 */	h = 0;	switch(vp->v_type) {	case V_NULL:		/* nothing to store ... so do nothing */		return;	case V_INT:		oval = (USB8)(vp->v_int & 0xff);		break;	case V_NUM:		if (qisint(vp->v_num)) {			/* use low order 8 bits of integer value */			h = vp->v_num->num.v[0];		} else {			/* use low order 8 bits of int(value) */			q = qint(vp->v_num);			h = q->num.v[0];			qfree(q);		}		if (qisneg(vp->v_num))			h = -h;		oval = (USB8) h;		break;	case V_COM:		if (cisint(vp->v_com)) {			/* use low order 8 bits of integer value */			h = vp->v_com->real->num.v[0];		} else {			/* use low order 8 bits of int(value) */			q = qint(vp->v_com->real);			h = q->num.v[0];			qfree(q);		}		if (qisneg(vp->v_com->real))			h = -h;		oval = (USB8) h;		break;	case V_STR:		oval = (USB8) vp->v_str->s_str[0];		break;	case V_BLOCK:		oval = (USB8) vp->v_block->data[0];		break;	case V_OCTET:		oval = *vp->v_octet;		break;	case V_NBLOCK:		if (vp->v_nblock->blk->data == NULL)			return;		oval = (USB8) vp->v_nblock->blk->data[0];		break;	default:		math_error("invalid assignment into an OCTET");		break;	}	*op = oval;}/* * Negate an arbitrary value. * Result is placed in the indicated location. */voidnegvalue(VALUE *vp, VALUE *vres){	vres->v_type = vp->v_type;	vres->v_subtype = V_NOSUBTYPE;	switch (vp->v_type) {	case V_NUM:		vres->v_num = qneg(vp->v_num);		return;	case V_COM:		vres->v_com = c_neg(vp->v_com);		return;	case V_MAT:		vres->v_mat = matneg(vp->v_mat);		return;	case V_STR:		vres->v_str = stringneg(vp->v_str);		if (vres->v_str == NULL)			*vres = error_value(E_STRNEG);		return;	case V_OCTET:		vres->v_type = V_NUM;		vres->v_subtype = V_NOSUBTYPE;		vres->v_num = itoq(- (long) *vp->v_octet);		return;	case V_OBJ:		*vres = objcall(OBJ_NEG, vp, NULL_VALUE, NULL_VALUE);		return;	default:		if (vp->v_type <= 0)			return;		*vres = error_value(E_NEG);		return;	}}/* * Add two arbitrary values together. * Result is placed in the indicated location. */voidaddvalue(VALUE *v1, VALUE *v2, VALUE *vres){	COMPLEX *c;	VALUE tmp;	NUMBER *q;	long i;	vres->v_subtype = V_NOSUBTYPE;	if (v1->v_type == V_LIST) {		tmp.v_type = V_NULL;		addlistitems(v1->v_list, &tmp);		addvalue(&tmp, v2, vres);		return;	}	if (v2->v_type == V_LIST) {		copyvalue(v1, vres);		addlistitems(v2->v_list, vres);		return;	}	if (v1->v_type == V_NULL) {		copyvalue(v2, vres);		return;	}	if (v2->v_type == V_NULL) {		copyvalue(v1, vres);		return;	}	vres->v_type = v1->v_type;	switch (TWOVAL(v1->v_type, v2->v_type)) {	case TWOVAL(V_NUM, V_NUM):		vres->v_num = qqadd(v1->v_num, v2->v_num);		return;	case TWOVAL(V_COM, V_NUM):		vres->v_com = c_addq(v1->v_com, v2->v_num);		return;	case TWOVAL(V_NUM, V_COM):		vres->v_com = c_addq(v2->v_com, v1->v_num);		vres->v_type = V_COM;		return;	case TWOVAL(V_COM, V_COM):		vres->v_com = c_add(v1->v_com, v2->v_com);		c = vres->v_com;		if (!cisreal(c))			return;		vres->v_num = qlink(c->real);		vres->v_type = V_NUM;		comfree(c);		return;	case TWOVAL(V_MAT, V_MAT):		vres->v_mat = matadd(v1->v_mat, v2->v_mat);		return;	case TWOVAL(V_STR, V_STR):		vres->v_str = stringadd(v1->v_str, v2->v_str);		if (vres->v_str == NULL)			*vres = error_value(E_STRADD);		return;	case TWOVAL(V_VPTR, V_NUM):		q = v2->v_num;		if (qisfrac(q)) {			math_error("Adding non-integer to address");			/*NOTREACHED*/		}		i = qtoi(q);		vres->v_addr = v1->v_addr + i;		vres->v_type = V_VPTR;		return;	case TWOVAL(V_OPTR, V_NUM):		q = v2->v_num;		if (qisfrac(q)) {			math_error("Adding non-integer to address");			/*NOTREACHED*/		}		i = qtoi(q);		vres->v_octet = v1->v_octet + i;		vres->v_type = V_OPTR;		return;	default:		if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ)) {			if (v1->v_type < 0)				return;			if (v2->v_type > 0)				*vres = error_value(E_ADD);			else				vres->v_type = v2->v_type;			return;		}		*vres = objcall(OBJ_ADD, v1, v2, NULL_VALUE);		return;	}}/* * Subtract one arbitrary value from another one. * Result is placed in the indicated location. */voidsubvalue(VALUE *v1, VALUE *v2, VALUE *vres){	COMPLEX *c;	NUMBER *q;	int i;	vres->v_type = v1->v_type;	vres->v_subtype = V_NOSUBTYPE;	switch (TWOVAL(v1->v_type, v2->v_type)) {	case TWOVAL(V_NUM, V_NUM):		vres->v_num = qsub(v1->v_num, v2->v_num);		return;	case TWOVAL(V_COM, V_NUM):		vres->v_com = c_subq(v1->v_com, v2->v_num);		return;	case TWOVAL(V_NUM, V_COM):		c = c_subq(v2->v_com, v1->v_num);		vres->v_type = V_COM;		vres->v_com = c_neg(c);		comfree(c);		return;	case TWOVAL(V_COM, V_COM):		vres->v_com = c_sub(v1->v_com, v2->v_com);		c = vres->v_com;		if (!cisreal(c))			return;		vres->v_num = qlink(c->real);		vres->v_type = V_NUM;		comfree(c);		return;	case TWOVAL(V_MAT, V_MAT):		vres->v_mat = matsub(v1->v_mat, v2->v_mat);		return;	case TWOVAL(V_STR, V_STR):		vres->v_str = stringsub(v1->v_str, v2->v_str);		if (vres->v_str == NULL)			*vres = error_value(E_STRSUB);		return;	case TWOVAL(V_VPTR, V_NUM):		q = v2->v_num;		if (qisfrac(q)) {			math_error("Subtracting non-integer from address");			/*NOTREACHED*/		}		i = qtoi(q);		vres->v_addr = v1->v_addr - i;		vres->v_type = V_VPTR;		return;	case TWOVAL(V_OPTR, V_NUM):		q = v2->v_num;		if (qisfrac(q)) {			math_error("Adding non-integer to address");			/*NOTREACHED*/		}		i = qtoi(q);		vres->v_octet = v1->v_octet - i;		vres->v_type = V_OPTR;		return;	case TWOVAL(V_VPTR, V_VPTR):		vres->v_type = V_NUM;		vres->v_num = itoq(v1->v_addr - v2->v_addr);		return;	case TWOVAL(V_OPTR, V_OPTR):		vres->v_type = V_NUM;		vres->v_num = itoq(v1->v_octet - v2->v_octet);		return;	default:		if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ)) {			if (v1->v_type <= 0)				return;			if (v2->v_type <= 0) {				vres->v_type = v2->v_type;				return;			}			*vres = error_value(E_SUB);			return;		}		*vres = objcall(OBJ_SUB, v1, v2, NULL_VALUE);		return;	}}/* * Multiply two arbitrary values together. * Result is placed in the indicated location. */voidmulvalue(VALUE *v1, VALUE *v2, VALUE *vres){	COMPLEX *c;	vres->v_type = v1->v_type;	vres->v_subtype = V_NOSUBTYPE;	switch (TWOVAL(v1->v_type, v2->v_type)) {	case TWOVAL(V_NUM, V_NUM):		vres->v_num = qmul(v1->v_num, v2->v_num);		return;	case TWOVAL(V_COM, V_NUM):		vres->v_com = c_mulq(v1->v_com, v2->v_num);		break;	case TWOVAL(V_NUM, V_COM):		vres->v_com = c_mulq(v2->v_com, v1->v_num);		vres->v_type = V_COM;		break;	case TWOVAL(V_COM, V_COM):		vres->v_com = c_mul(v1->v_com, v2->v_com);		break;	case TWOVAL(V_MAT, V_MAT):		vres->v_mat = matmul(v1->v_mat, v2->v_mat);		return;	case TWOVAL(V_MAT, V_NUM):	case TWOVAL(V_MAT, V_COM):		vres->v_mat = matmulval(v1->v_mat, v2);		return;	case TWOVAL(V_NUM, V_MAT):	case TWOVAL(V_COM, V_MAT):		vres->v_mat = matmulval(v2->v_mat, v1);		vres->v_type = V_MAT;		return;	case TWOVAL(V_NUM, V_STR):		vres->v_type = V_STR;		vres->v_str = stringmul(v1->v_num, v2->v_str);		if (vres->v_str == NULL)			*vres = error_value(E_STRMUL);		return;	case TWOVAL(V_STR, V_NUM):		vres->v_str= stringmul(v2->v_num, v1->v_str);		if (vres->v_str == NULL)			*vres = error_value(E_STRMUL);		return;	default:		if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ)) {			if (v1->v_type <= 0)				return;			if (v2->v_type <= 0) {				vres->v_type = v2->v_type;				return;			}			*vres = error_value(E_MUL);			return;		}		*vres = objcall(OBJ_MUL, v1, v2, NULL_VALUE);		return;	}	c = vres->v_com;	if (cisreal(c)) {		vres->v_num = qlink(c->real);		vres->v_type = V_NUM;		comfree(c);	}}/* * Square an arbitrary value. * Result is placed in the indicated location. */voidsquarevalue(VALUE *vp, VALUE *vres){	COMPLEX *c;	vres->v_type = vp->v_type;	vres->v_subtype = V_NOSUBTYPE;	switch (vp->v_type) {	case V_NUM:		vres->v_num = qsquare(vp->v_num);		return;	case V_COM:		vres->v_com = c_square(vp->v_com);		c = vres->v_com;		if (!cisreal(c))			return;		vres->v_num = qlink(c->real);		vres->v_type = V_NUM;		comfree(c);		return;	case V_MAT:		vres->v_mat = matsquare(vp->v_mat);		return;	case V_OBJ:		*vres = objcall(OBJ_SQUARE, vp, NULL_VALUE, NULL_VALUE);		return;	default:		if (vp->v_type <= 0) {			vres->v_type = vp->v_type;			return;		}		*vres = error_value(E_SQUARE);		return;	}}/* * Invert an arbitrary value. * Result is placed in the indicated location. */voidinvertvalue(VALUE *vp, VALUE *vres){	NUMBER *q1, *q2;	vres->v_type = vp->v_type;	vres->v_subtype = V_NOSUBTYPE;	switch (vp->v_type) {	case V_NUM:		if (qiszero(vp->v_num))			*vres = error_value(E_1OVER0);		else			vres->v_num = qinv(vp->v_num);		return;	case V_COM:		vres->v_com = c_inv(vp->v_com);		return;	case V_MAT:		vres->v_mat = matinv(vp->v_mat);		return;	case V_OCTET:		if (*vp->v_octet == 0) {			*vres = error_value(E_1OVER0);			return;		}		q1 = itoq((long) *vp->v_octet);		q2 = qinv(q1);		qfree(q1);		vres->v_num = q2;		vres->v_type = V_NUM;		return;	case V_OBJ:		*vres = objcall(OBJ_INV, vp, NULL_VALUE, NULL_VALUE);		return;	default:		if (vp->v_type == -E_1OVER0) {			vres->v_type = V_NUM;			vres->v_num = qlink(&_qzero_);			return;		}		if (vp->v_type <= 0)			return;		*vres = error_value(E_INV);		return;	}}/* * "AND" two arbitrary values together. * Result is placed in the indicated location. */voidandvalue(VALUE *v1, VALUE *v2, VALUE *vres){	vres->v_subtype = V_NOSUBTYPE;	if (v1->v_type == V_NULL) {		copyvalue(v2, vres);		return;	}	if (v2->v_type == V_NULL) {		copyvalue(v1, vres);

⌨️ 快捷键说明

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