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

📄 func.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * func - built-in functions implemented here * * Copyright (C) 1999-2006  David I. Bell, Landon Curt Noll and Ernest Bowen * * Primary author:  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.32 $ * @(#) $Id: func.c,v 29.32 2006/12/16 10:46:07 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/RCS/func.c,v $ * * Under source code control:	1990/02/15 01:48:15 * File existed as early as:	before 1990 * * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/ */#include <stdio.h>#include <ctype.h>#include <sys/types.h>#include <errno.h>#if defined(_WIN32)# include <io.h># define _access access#endif#if defined(FUNCLIST)#define CONST /* disabled for FUNCLIST in case NATIVE_CC doesn't have it */#else /* FUNCLIST */#include "have_unistd.h"#if defined(HAVE_UNISTD_H)#include <unistd.h>#endif#include "have_stdlib.h"#if defined(HAVE_STDLIB_H)#include <stdlib.h>#endif#include "have_string.h"#if defined(HAVE_STRING_H)#include <string.h>#endif#include "have_times.h"#if defined(HAVE_TIME_H)#include <time.h>#endif#if defined(HAVE_TIMES_H)#include <times.h>#endif#if defined(HAVE_SYS_TIME_H)#include <sys/time.h>#endif#if defined(HAVE_SYS_TIMES_H)#include <sys/times.h>#endif#include "have_strdup.h"#if !defined(HAVE_STRDUP)# define strdup(x) calc_strdup((CONST char *)(x))#endif#include "have_rusage.h"#if defined(HAVE_GETRUSAGE)# include <sys/resource.h>#endif#include "have_const.h"#include "have_unused.h"#include "calc.h"#include "calcerr.h"#include "opcodes.h"#include "token.h"#include "func.h"#include "string.h"#include "symbol.h"#include "prime.h"#include "file.h"#include "zrand.h"#include "zrandom.h"#include "custom.h"#if defined(CUSTOM)# define E_CUSTOM_ERROR E_NO_C_ARG#else# define E_CUSTOM_ERROR E_NO_CUSTOM#endif/* * forward declarations */static NUMBER *base_value(long mode, int defval);static int strscan(char *s, int count, VALUE **vals);static int filescan(FILEID id, int count, VALUE **vals);static VALUE f_eval(VALUE *vp);static VALUE f_fsize(VALUE *vp);static int malloced_putenv(char *str);/* * external declarations */extern char cmdbuf[];				/* command line expression */extern CONST char *error_table[E__COUNT+2];	/* calc coded error messages */extern void matrandperm(MATRIX *M);extern void listrandperm(LIST *lp);extern int idungetc(FILEID id, int ch);extern LIST* associndices(ASSOC *ap, long index);extern LIST* matindices(MATRIX *mp, long index);/* * malloced environment storage */#define ENV_POOL_CHUNK 10	/* env_pool elements to allocate at a time */struct env_pool {    char *getenv;	/* what getenv() would return, NULL => unused */    char *putenv;	/* pointer given to putenv() */};static int env_pool_cnt = 0;	/* number of env_pool elements in use */static int env_pool_max = 0;	/* number of env_pool elements allocated */static struct env_pool *e_pool = NULL;	/* env_pool elements *//* * user-defined error strings */static short nexterrnum = E_USERDEF;static STRINGHEAD newerrorstr;#endif /* !FUNCLIST *//* * arg count definitions */#define IN 1024		/* maximum number of arguments */#define FE 0x01		/* flag to indicate default epsilon argument */#define FA 0x02		/* preserve addresses of variables *//* * builtins - List of primitive built-in functions */struct builtin {	char *b_name;		/* name of built-in function */	short b_minargs;	/* minimum number of arguments */	short b_maxargs;	/* maximum number of arguments */	short b_flags;		/* special handling flags */	short b_opcode;		/* opcode which makes the call quick */	NUMBER *(*b_numfunc)(); /* routine to calculate numeric function */	VALUE (*b_valfunc)();	/* routine to calculate general values */	char *b_desc;		/* description of function */};#if !defined(FUNCLIST)static VALUEf_eval(VALUE *vp){	FUNC	*oldfunc;	FUNC	*newfunc;	VALUE	result;	char	*str;	size_t	num;	long	temp_stoponerror;	/* temp value of stoponerror */	if (vp->v_type != V_STR)		return error_value(E_EVAL2);	str = vp->v_str->s_str;	num = vp->v_str->s_len;	switch (openstring(str, num)) {	case -2:		return error_value(E_EVAL3);	case -1:		return error_value(E_EVAL4);	}	oldfunc = curfunc;	enterfilescope();	temp_stoponerror = stoponerror;	stoponerror = -1;	if (evaluate(TRUE)) {		stoponerror = temp_stoponerror;		closeinput();		exitfilescope();		freevalue(stack--);		newfunc = curfunc;		curfunc = oldfunc;		result = newfunc->f_savedvalue;		newfunc->f_savedvalue.v_type = V_NULL;		newfunc->f_savedvalue.v_subtype = V_NOSUBTYPE;		freenumbers(newfunc);		if (newfunc != oldfunc)			free(newfunc);		return result;	}	stoponerror = temp_stoponerror;	closeinput();	exitfilescope();	newfunc = curfunc;	curfunc = oldfunc;	freevalue(&newfunc->f_savedvalue);	newfunc->f_savedvalue.v_type = V_NULL;	newfunc->f_savedvalue.v_subtype = V_NOSUBTYPE;	freenumbers(newfunc);	if (newfunc != oldfunc)		free(newfunc);	return error_value(E_EVAL);}static VALUEf_prompt(VALUE *vp){	VALUE result;	char *cp;	char *newcp;	size_t len;	/* initialize VALUE */	result.v_type = V_STR;	result.v_subtype = V_NOSUBTYPE;	openterminal();	printvalue(vp, PRINT_SHORT);	math_flush();	cp = nextline();	closeinput();	if (cp == NULL) {		result.v_type = V_NULL;		return result;	}	if (*cp == '\0') {		result.v_str = slink(&_nullstring_);		return result;	}	len = strlen(cp);	newcp = (char *) malloc(len + 1);	if (newcp == NULL) {		math_error("Cannot allocate string");		/*NOTREACHED*/	}	strncpy(newcp, cp, len+1);	result.v_str = makestring(newcp);	return result;}static VALUEf_display(int count, VALUE **vals){	LEN oldvalue;	VALUE res;	/* initialize VALUE */	res.v_type = V_NUM;	res.v_subtype = V_NOSUBTYPE;	oldvalue = conf->outdigits;	if (count > 0) {		if (vals[0]->v_type != V_NUM || qisfrac(vals[0]->v_num) ||			qisneg(vals[0]->v_num) || zge31b(vals[0]->v_num->num))			fprintf(stderr,			       "Out-of-range arg for display ignored\n");		else			conf->outdigits = (LEN) qtoi(vals[0]->v_num);	}	res.v_num = itoq((long) oldvalue);	return res;}/*ARGSUSED*/static VALUEf_null(int UNUSED count, VALUE UNUSED **vals){	VALUE res;	/* initialize VALUE */	res.v_type = V_NULL;	res.v_subtype = V_NOSUBTYPE;	return res;}static VALUEf_str(VALUE *vp){	VALUE result;	char *cp;	/* initialize VALUE */	result.v_type = V_STR;	result.v_subtype = V_NOSUBTYPE;	switch (vp->v_type) {	case V_STR:		result.v_str = makenewstring(vp->v_str->s_str);		break;	case V_NULL:		result.v_str = slink(&_nullstring_);		break;	case V_OCTET:		result.v_str = charstring(*vp->v_octet);		break;	case V_NUM:		math_divertio();		qprintnum(vp->v_num, MODE_DEFAULT);		cp = math_getdivertedio();		result.v_str = makestring(cp);		break;	case V_COM:		math_divertio();		comprint(vp->v_com);		cp = math_getdivertedio();		result.v_str = makestring(cp);		break;	default:		return error_value(E_STR);	}	return result;}static VALUEf_estr(VALUE *vp){	VALUE result;	char *cp;	/* initialize result */	result.v_type = V_STR;	result.v_subtype = V_NOSUBTYPE;	math_divertio();	printestr(vp);	cp = math_getdivertedio();	result.v_str = makestring(cp);	return result;}static VALUEf_name(VALUE *vp){	VALUE result;	char *cp;	char *name;	/* initialize VALUE */	result.v_type = V_STR;	result.v_subtype = V_NOSUBTYPE;	switch (vp->v_type) {	case V_NBLOCK:		result.v_type = V_STR;		result.v_str = makenewstring(vp->v_nblock->name);		return result;	case V_FILE:		name = findfname(vp->v_file);		if (name == NULL) {			result.v_type = V_NULL;			return result;		}		math_divertio();		math_str(name);		cp = math_getdivertedio();		break;	default:		result.v_type = V_NULL;		return result;	}	result.v_str = makestring(cp);	return result;}static VALUEf_poly(int count, VALUE **vals){	VALUE *x;	VALUE result, tmp;	LIST *clist, *lp;	/* initialize VALUEs */	result.v_subtype = V_NOSUBTYPE;	tmp.v_subtype = V_NOSUBTYPE;	if (vals[0]->v_type == V_LIST) {		clist = vals[0]->v_list;		lp = listalloc();		while (--count > 0) {			if ((*++vals)->v_type == V_LIST)				insertitems(lp, (*vals)->v_list);			else				insertlistlast(lp, *vals);		}		if (!evalpoly(clist, lp->l_first, &result)) {			result.v_type = V_NUM;			result.v_num = qlink(&_qzero_);		}		listfree(lp);		return result;	}	x = vals[--count];	copyvalue(*vals++, &result);	while (--count > 0) {		mulvalue(&result, x, &tmp);		freevalue(&result);		addvalue(*vals++, &tmp, &result);		freevalue(&tmp);	}	return result;}static NUMBER *f_mne(NUMBER *val1, NUMBER *val2, NUMBER *val3){	NUMBER *tmp, *res;	tmp = qsub(val1, val2);	res = itoq((long) !qdivides(tmp, val3));	qfree(tmp);	return res;}static NUMBER *f_isrel(NUMBER *val1, NUMBER *val2){	if (qisfrac(val1) || qisfrac(val2)) {		math_error("Non-integer for isrel");		/*NOTREACHED*/	}	return itoq((long) zrelprime(val1->num, val2->num));}static NUMBER *f_issquare(NUMBER *vp){	return itoq((long) qissquare(vp));}static NUMBER *f_isprime(int count, NUMBER **vals){	NUMBER *err;		/* error return, NULL => use math_error */	/* determine the way we report problems */	if (count == 2) {		if (qisfrac(vals[1])) {			math_error("2nd isprime arg must be an integer");			/*NOTREACHED*/		}		err = vals[1];	} else {		err = NULL;	}	/* firewall - must be an integer */	if (qisfrac(vals[0])) {		if (err) {			return qlink(err);		}		math_error("non-integral arg for builtin function isprime");		/*NOTREACHED*/	}	/* test the integer */	switch (zisprime(vals[0]->num)) {	case 0: return qlink(&_qzero_);	case 1: return qlink(&_qone_);	}	/* error return */	if (!err) {		math_error("isprime argument is an odd value > 2^32");		/*NOTREACHED*/	}	return qlink(err);}static NUMBER *f_nprime(int count, NUMBER **vals){	NUMBER *err;		/* error return, NULL => use math_error */	FULL nxt_prime;		/* next prime or 0 */	/* determine the way we report problems */	if (count == 2) {		if (qisfrac(vals[1])) {			math_error("2nd nextprime arg must be an integer");			/*NOTREACHED*/		}		err = vals[1];	} else {		err = NULL;	}	/* firewall - must be an integer */	if (qisfrac(vals[0])) {		if (err) {			return qlink(err);		}		math_error("non-integral arg 1 for builtin function nextprime");		/*NOTREACHED*/	}	/* test the integer */	nxt_prime = znprime(vals[0]->num);	if (nxt_prime > 1) {		return utoq(nxt_prime);	} else if (nxt_prime == 0) {		/* return 2^32+15 */		return qlink(&_nxtprime_);	}	/* error return */	if (!err) {		math_error("nextprime arg 1 is >= 2^32");		/*NOTREACHED*/	}	return qlink(err);}static NUMBER *f_pprime(int count, NUMBER **vals){	NUMBER *err;		/* error return, NULL => use math_error */	FULL prev_prime;	/* previous prime or 0 */	/* determine the way we report problems */	if (count == 2) {		if (qisfrac(vals[1])) {			math_error("2nd prevprime arg must be an integer");			/*NOTREACHED*/		}		err = vals[1];	} else {		err = NULL;	}	/* firewall - must be an integer */	if (qisfrac(vals[0])) {		if (err) {			return qlink(err);		}		math_error("non-integral arg 1 for builtin function prevprime");		/*NOTREACHED*/	}	/* test the integer */	prev_prime = zpprime(vals[0]->num);	if (prev_prime > 1) {		return utoq(prev_prime);	}	if (prev_prime == 0) {		return qlink(&_qzero_);	}	/* error return */	if (!err) {		if (prev_prime == 0) {			math_error("prevprime arg 1 is <= 2");			/*NOTREACHED*/		} else {			math_error("prevprime arg 1 is >= 2^32");			/*NOTREACHED*/		}	}	return qlink(err);}static NUMBER *f_factor(int count, NUMBER **vals){	NUMBER *err;	/* error return, NULL => use math_error */	ZVALUE limit;	/* highest prime factor in search */	ZVALUE n;	/* number to factor */	NUMBER *factor; /* the prime factor found */	int res;	/* -1 => error, 0 => not found, 1 => factor found */	/*	 * parse args	 */	if (count == 3) {		if (qisfrac(vals[2])) {			math_error("3rd factor arg must be an integer");			/*NOTREACHED*/		}		err = vals[2];	} else {		err = NULL;	}	if (count >= 2) {		if (qisfrac(vals[1])) {			if (err) {				return qlink(err);			}			math_error("non-integral arg 2 for builtin factor");			/*NOTREACHED*/		}		limit = vals[1]->num;	} else {		/* default limit is 2^32-1 */		utoz((FULL)0xffffffff, &limit);	}	if (qisfrac(vals[0])) {		if (count < 2)			zfree(limit);		if (err) {			return qlink(err);		}		math_error("non-integral arg 1 for builtin pfactor");		/*NOTREACHED*/	}	n = vals[0]->num;	/*	 * find the smallest prime factor in the range	 */	factor = qalloc();	res = zfactor(n, limit, &(factor->num));	if (res < 0) {		/* error processing */		if (err) {			return qlink(err);		}		math_error("limit >= 2^32 for builtin factor");		/*NOTREACHED*/	} else if (res == 0) {		if (count < 2)			zfree(limit);

⌨️ 快捷键说明

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