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

📄 interp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
    int collen;		/* length of string */    int row, col;	/* integer values   */    struct ent *ep = (struct ent *)0;	/* selected entry   */    if (((row = (int) floor (rowdoub)) >= 0)     && (row < maxrows)				/* in range */     && ((collen = strlen (colstr)) <= 2)	/* not too long */     && ((col = atocol (colstr, collen)) >= 0)     && (col < maxcols))			/* in range */    {	ep = *ATBL(tbl, row, col);    }    xfree (colstr);    return (ep);}/* * Given a string representing a column name and a value which is a column * number, return the selected cell's numeric value, if any. */doubledonval (colstr, rowdoub)    char *colstr;    double rowdoub;{    struct ent *ep;    return (((ep = getent (colstr, rowdoub)) && ((ep -> flags) & is_valid)) ?	    (ep -> v) : (double)0);}/* *	The list routines (e.g. dolmax) are called with an LMAX enode. *	The left pointer is a chain of ELIST nodes, the right pointer *	is a value. */doubledolmax(ep)struct enode *ep;{	register int count = 0;	register double maxval = 0; /* Assignment to shut up lint */	register struct enode *p;	register double v;	for (p = ep; p; p = p->e.o.left) {		v = eval(p->e.o.right);		if (!count || v > maxval) {			maxval = v; count++;		}	}	if (count) return maxval;	else return (double)0;}doubledolmin(ep)struct enode *ep;{	register int count = 0;	register double minval = 0; /* Assignment to shut up lint */	register struct enode *p;	register double v;	for (p = ep; p; p = p->e.o.left) {		v = eval(p->e.o.right);		if (!count || v < minval) {			minval = v; count++;		}	}	if (count) return minval;	else return (double)0;}double eval(e)register struct enode *e;{    if (e == (struct enode *)0) return (double)0;    switch (e->op) {	case '+':	return (eval(e->e.o.left) + eval(e->e.o.right));	case '-':	return (eval(e->e.o.left) - eval(e->e.o.right));	case '*':	return (eval(e->e.o.left) * eval(e->e.o.right));	case '/':       return (eval(e->e.o.left) / eval(e->e.o.right));	case '%':     {	double num, denom;			num = floor(eval(e->e.o.left));			denom = floor(eval (e->e.o.right));			return denom ? num - floor(num/denom)*denom : (double)0; }	case '^':	return (fn2_eval(pow,eval(e->e.o.left),eval(e->e.o.right)));	case '<':	return (eval(e->e.o.left) < eval(e->e.o.right));	case '=':	return (eval(e->e.o.left) == eval(e->e.o.right));	case '>':	return (eval(e->e.o.left) > eval(e->e.o.right));	case '&':	return (eval(e->e.o.left) && eval(e->e.o.right));	case '|':	return (eval(e->e.o.left) || eval(e->e.o.right));	case IF:	case '?':	return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)						: eval(e->e.o.right->e.o.right);	case 'm':	return (-eval(e->e.o.right));	case 'f':	return (eval(e->e.o.right));	case '~':	return (eval(e->e.o.right) == 0.0);	case 'k':	return (e->e.k);	case 'v':	return (e->e.v.vp->v);	case INDEX:	case LOOKUP:	case HLOOKUP:	case VLOOKUP:	    {	register r,c;		register maxr, maxc;		register minr, minc;		maxr = e->e.o.right->e.r.right.vp -> row;		maxc = e->e.o.right->e.r.right.vp -> col;		minr = e->e.o.right->e.r.left.vp -> row;		minc = e->e.o.right->e.r.left.vp -> col;		if (minr>maxr) r = maxr, maxr = minr, minr = r;		if (minc>maxc) c = maxc, maxc = minc, minc = c;		switch(e->op){		case LOOKUP:		    return dolookup(e->e.o.left, minr, minc, maxr, maxc,				     minr==maxr, minc==maxc);		case HLOOKUP:	            return dolookup(e->e.o.left->e.o.left, minr,minc,maxr,maxc,			(int) eval(e->e.o.left->e.o.right), 0);		case VLOOKUP:	            return dolookup(e->e.o.left->e.o.left, minr,minc,maxr,maxc,			0, (int) eval(e->e.o.left->e.o.right));		case INDEX:		    return doindex(eval(e->e.o.left), minr, minc, maxr, maxc);		}	    }	case REDUCE | '+': 	case REDUCE | '*': 	case REDUCE | 'a': 	case REDUCE | 'c': 	case REDUCE | 's':	case REDUCE | MAX:	case REDUCE | MIN:	    {	register r,c;		register maxr, maxc;		register minr, minc;		maxr = e->e.r.right.vp -> row;		maxc = e->e.r.right.vp -> col;		minr = e->e.r.left.vp -> row;		minc = e->e.r.left.vp -> col;		if (minr>maxr) r = maxr, maxr = minr, minr = r;		if (minc>maxc) c = maxc, maxc = minc, minc = c;	        switch (e->op) {	            case REDUCE | '+': return dosum(minr, minc, maxr, maxc); 	            case REDUCE | '*': return doprod(minr, minc, maxr, maxc); 	            case REDUCE | 'a': return doavg(minr, minc, maxr, maxc); 	            case REDUCE | 'c': return docount(minr, minc, maxr, maxc); 	            case REDUCE | 's': return dostddev(minr, minc, maxr, maxc); 	            case REDUCE | MAX: return domax(minr, minc, maxr, maxc); 	            case REDUCE | MIN: return domin(minr, minc, maxr, maxc);		}	    }	case ABS:	 return (fn1_eval( fabs, eval(e->e.o.right)));	case ACOS:	 return (fn1_eval( acos, eval(e->e.o.right)));	case ASIN:	 return (fn1_eval( asin, eval(e->e.o.right)));	case ATAN:	 return (fn1_eval( atan, eval(e->e.o.right)));	case ATAN2:	 return (fn2_eval( atan2, eval(e->e.o.left), eval(e->e.o.right)));	case CEIL:	 return (fn1_eval( ceil, eval(e->e.o.right)));	case COS:	 return (fn1_eval( cos, eval(e->e.o.right)));	case EXP:	 return (fn1_eval( exp, eval(e->e.o.right)));	case FABS:	 return (fn1_eval( fabs, eval(e->e.o.right)));	case FLOOR:	 return (fn1_eval( floor, eval(e->e.o.right)));	case HYPOT:	 return (fn2_eval( hypot, eval(e->e.o.left), eval(e->e.o.right)));	case LOG:	 return (fn1_eval( log, eval(e->e.o.right)));	case LOG10:	 return (fn1_eval( log10, eval(e->e.o.right)));	case POW:	 return (fn2_eval( pow, eval(e->e.o.left), eval(e->e.o.right)));	case SIN:	 return (fn1_eval( sin, eval(e->e.o.right)));	case SQRT:	 return (fn1_eval( sqrt, eval(e->e.o.right)));	case TAN:	 return (fn1_eval( tan, eval(e->e.o.right)));	case DTR:	 return (dtr(eval(e->e.o.right)));	case RTD:	 return (rtd(eval(e->e.o.right)));	case RND:	 {			    double temp;			    temp = eval(e->e.o.right);			    return(temp-floor(temp) < 0.5 ?					     floor(temp) : ceil(temp));			} 	case ROUND:	{			    double temp = eval(e->e.o.left);			    int prec = (int) eval(e->e.o.right), scal = 1;			    while (prec-- > 0) scal *= 10;			    temp *= scal;			    temp = ((temp-floor(temp)) < 0.5 ?				    floor(temp) : ceil(temp));			    return(temp / scal);			}	case FV:	case PV:	case PMT:	return(finfunc(e->op,eval(e->e.o.left),				   eval(e->e.o.right->e.o.left),				      eval(e->e.o.right->e.o.right)));	case HOUR:	 return (dotime(HOUR, eval(e->e.o.right)));	case MINUTE:	 return (dotime(MINUTE, eval(e->e.o.right)));	case SECOND:	 return (dotime(SECOND, eval(e->e.o.right)));	case MONTH:	 return (dotime(MONTH, eval(e->e.o.right)));	case DAY:	 return (dotime(DAY, eval(e->e.o.right)));	case YEAR:	 return (dotime(YEAR, eval(e->e.o.right)));	case NOW:	 return (dotime(NOW, (double)0.0));	case DTS:	 return (dodts((int)eval(e->e.o.left),				 (int)eval(e->e.o.right->e.o.left),				 (int)eval(e->e.o.right->e.o.right)));	case TTS:	 return (dotts((int)eval(e->e.o.left),				 (int)eval(e->e.o.right->e.o.left),				 (int)eval(e->e.o.right->e.o.right)));	case STON:	 return (doston(seval(e->e.o.right)));	case EQS:        return (doeqs(seval(e->e.o.right),seval(e->e.o.left)));	case LMAX:	 return dolmax(e);	case LMIN:	 return dolmin(e);	case NVAL:       return (donval(seval(e->e.o.left),eval(e->e.o.right)));	default:	 error ("Illegal numeric expression");			 exprerr = 1;    }    return((double)0.0);}#ifdef SIGVOIDvoid#endifeval_fpe(signo) /* Trap for FPE errors in eval */int signo;{#ifdef IEEE_MATH	(void)fpsetsticky((fp_except)0); 		/* Clear exception */#endif /* IEEE_MATH */	longjmp(fpe_save, 1);}double fn1_eval(fn, arg)double (*fn)();double arg;{	double res;	errno = 0;	res = (*fn)(arg);	if(errno)	  eval_fpe(0);	return res;}double fn2_eval(fn, arg1, arg2)double (*fn)();double arg1, arg2;{	double res;	errno = 0;	res = (*fn)(arg1, arg2);	if(errno) 	    eval_fpe(0);	return res;}/*  * Rules for string functions: * Take string arguments which they xfree. * All returned strings are assumed to be xalloced. */char *docat(s1, s2)register char *s1, *s2;{    register char *p;    char *arg1, *arg2;    if (!s1 && !s2)	return((char *)0);    arg1 = s1 ? s1 : "";    arg2 = s2 ? s2 : "";    p = xmalloc((unsigned)(strlen(arg1)+strlen(arg2)+1));    (void) strcpy(p, arg1);    (void) strcat(p, arg2);    if (s1)        xfree(s1);    if (s2)        xfree(s2);    return(p);}char *dodate(tloc)long tloc;{    char *tp;    char *p;    tp = ctime(&tloc);    tp[24] = '\0';    p = xmalloc((unsigned)25);    (void) strcpy(p, tp);    return(p);}char *dofmt(fmtstr, v)char *fmtstr;double v;{    char buff[FBUFLEN];    char *p;    if (!fmtstr)	return((char *)0);    (void)sprintf(buff, fmtstr, v);    p = xmalloc((unsigned)(strlen(buff)+1));    (void) strcpy(p, buff);    xfree(fmtstr);    return(p);}/* * Given a command name and a value, run the command with the given value and * read and return its first output line (only) as an allocated string, always * a copy of prevstr, which is set appropriately first unless external * functions are disabled, in which case the previous value is used.  The * handling of prevstr and freeing of command is tricky.  Returning an * allocated string in all cases, even if null, insures cell expressions are * written to files, etc. */#ifdef VMSchar *doext(command, value)char *command;double value;{    error("Warning: External functions unavailable on VMS");    if (command)	xfree(command);    return (strcpy (xmalloc((unsigned) 1), "\0"));}#else /* VMS */char *doext (command, value)char   *command;double value;{    static char *prevstr = (char *)0;	/* previous result */    char buff[FBUFLEN];		/* command line/return, not permanently alloc */    if (!prevstr) {	prevstr = xmalloc((unsigned)1);	*prevstr = '\0';    }    if (!extfunc)    {	error ("Warning: external functions disabled; using %s value",		prevstr ? "previous" : "null");	if (command) xfree (command);    } else {	if (prevstr) xfree (prevstr);		/* no longer needed */	prevstr = '\0';	if ((! command) || (! *command)) {	    error ("Warning: external function given null command name");	    if (command) xfree (command);	} else {	    FILE *pp;	    (void) sprintf (buff, "%s %g", command, value); /* build cmd line */	    xfree (command);	    error ("Running external function...");	    (void) refresh();	    if ((pp = popen (buff, "r")) == (FILE *) NULL)	/* run it */		error ("Warning: running \"%s\" failed", buff);	    else {		if (fgets (buff, sizeof(buff)-1, pp) == NULL)	/* one line */		    error ("Warning: external function returned nothing");		else {		    char *cp;		    error ("");				/* erase notice */		    buff[sizeof(buff)-1] = '\0';		    if (cp = strchr (buff, '\n'))	/* contains newline */			*cp = '\0';			/* end string there */		    (void) strcpy (prevstr = 			 xmalloc ((unsigned) (strlen (buff) + 1)), buff);			 /* save alloc'd copy */		}		(void) pclose (pp);	    } /* else */	} /* else */    } /* else */    return (strcpy (xmalloc ((unsigned) (strlen (prevstr) + 1)), prevstr));}#endif /* VMS *//* * Given a string representing a column name and a value which is a column * number, return the selected cell's string value, if any.  Even if none, * still allocate and return a null string so the cell has a label value so * the expression is saved in a file, etc. */char *dosval (colstr, rowdoub)    char *colstr;    double rowdoub;{    struct ent *ep;    char *label;    label = (ep = getent (colstr, rowdoub)) ? (ep -> label) : "";    return (strcpy (xmalloc ((unsigned) (strlen (label) + 1)), label));}/* * Substring:  Note that v1 and v2 are one-based to users, but zero-based * when calling this routine. */char *dosubstr(s, v1, v2)char *s;register int v1,v2;{    register char *s1, *s2;    char *p;    if (!s)	return((char *)0);    if (v2 >= strlen (s))		/* past end */	v2 =  strlen (s) - 1;		/* to end   */    if (v1 < 0 || v1 > v2) {		/* out of range, return null string */	xfree(s);	p = xmalloc((unsigned)1);	p[0] = '\0';	return(p);    }    s2 = p = xmalloc((unsigned)(v2-v1+2));    s1 = &s[v1];    for(; v1 <= v2; s1++, s2++, v1++)	*s2 = *s1;    *s2 = '\0';    xfree(s);    return(p);}char *seval(se)register struct enode *se;{    register char *p;    if (se == (struct enode *)0) return (char *)0;    switch (se->op) {	case O_SCONST: p = xmalloc((unsigned)(strlen(se->e.s)+1));		     (void) strcpy(p, se->e.s);		     return(p);	case O_VAR:    {			struct ent *ep;			ep = se->e.v.vp;			if (!ep->label)			    return((char *)0);			p = xmalloc((unsigned)(strlen(ep->label)+1));			(void) strcpy(p, ep->label);			return(p);		     }	case '#':    return(docat(seval(se->e.o.left), seval(se->e.o.right)));	case 'f':    return(seval(se->e.o.right));	case IF:	case '?':    return(eval(se->e.o.left) ? seval(se->e.o.right->e.o.left)					     : seval(se->e.o.right->e.o.right));	case DATE:   return(dodate((long)(eval(se->e.o.right))));	case FMT:    return(dofmt(seval(se->e.o.left), eval(se->e.o.right))); 	case STINDEX: 		{	register r,c; 		register maxr, maxc; 		register minr, minc; 		maxr = se->e.o.right->e.r.right.vp -> row; 		maxc = se->e.o.right->e.r.right.vp -> col; 		minr = se->e.o.right->e.r.left.vp -> row; 		minc = se->e.o.right->e.r.left.vp -> col; 		if (minr>maxr) r = maxr, maxr = minr, minr = r; 		if (minc>maxc) c = maxc, maxc = minc, minc = c; 	        return dostindex(eval(se->e.o.left), minr, minc, maxr, maxc);		}	case EXT:    return(doext(seval(se->e.o.left), eval(se->e.o.right)));	case SVAL:   return(dosval(seval(se->e.o.left), eval(se->e.o.right)));	case SUBSTR: return(dosubstr(seval(se->e.o.left),			    (int)eval(se->e.o.right->e.o.left) - 1,			    (int)eval(se->e.o.right->e.o.right) - 1));	default:		     error ("Illegal string expression");		     exprerr = 1;		     return((char *)0);	}}/* * The graph formed by cell expressions which use other cells's values is not * evaluated "bottom up".  The whole table is merely re-evaluated cell by cell, * top to bottom, left to right, in RealEvalAll().  Each cell's expression uses * constants in other cells.  However, RealEvalAll() notices when a cell gets a * new numeric or string value, and reports if this happens for any cell. * EvalAll() repeats calling RealEvalAll() until there are no changes or the * evaluation count expires. */int propagation = 10;	/* max number of times to try calculation */voidsetiterations(i)int i;{	if(i<1) {		error("iteration count must be at least 1");		propagation = 1;		}	else propagation = i;}voidEvalAll () {      int lastcnt, repct = 0;       while ((lastcnt = RealEvalAll()) && (repct++ <= propagation));     if((propagation>1)&& (lastcnt >0 )) 	    error("Still changing after %d iterations",propagation-1);}

⌨️ 快捷键说明

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