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

📄 lcalc.c

📁 128位长双精度型数字运算包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* calc.c *//* Keyboard command interpreter	*//* by Stephen L. Moshier */#include <unistd.h>int system();void e113toasc(), asctoe113(), init();/* length of command line: */#define LINLEN 128#define XON 0x11#define XOFF 0x13#define SALONE 1#define DECPDP 0#define INTLOGIN 0#define INTHELP 1#ifndef TRUE#define TRUE 1#endif/* Initialize squirrel printf: */#define INIPRINTF 0#if DECPDP#define TRUE 1#endif#include <stdio.h>static char idterp[] = {"\n\nSteve Moshier's command interpreter V1.3\n"};#define ISLOWER(c) ((c >= 'a') && (c <= 'z'))#define ISUPPER(c) ((c >= 'A') && (c <= 'Z'))#define ISALPHA(c) (ISLOWER(c) || ISUPPER(c))#define ISDIGIT(c) ((c >= '0') && (c <= '9'))#define ISATF(c) (((c >= 'a')&&(c <= 'f')) || ((c >= 'A')&&(c <= 'F')))#define ISXDIGIT(c) (ISDIGIT(c) || ISATF(c))#define ISOCTAL(c) ((c >= '0') && (c < '8'))#define ISALNUM(c) (ISALPHA(c) || (ISDIGIT(c))FILE *fopen();#include "lcalc.h"#include "ehead.h"/* space for working precision numbers */static long double vs[22];/*	the symbol table of temporary variables: */#define NTEMP 4struct varent temp[NTEMP] = {{"T",	OPR | TEMP, &vs[14]},{"T",	OPR | TEMP, &vs[15]},{"T",	OPR | TEMP, &vs[16]},{"\0",	OPR | TEMP, &vs[17]}};/*	the symbol table of operators		*//* EOL is interpreted on null, newline, or ;	*/struct symbol oprtbl[] = {{"BOL",		OPR | BOL,	0},{"EOL",		OPR | EOL,	0},{"-",		OPR | UMINUS,	8},/*"~",		OPR | COMP,	8,*/{",",		OPR | EOE,	1},{"=",		OPR | EQU,	2},/*"|",		OPR | LOR,	3,*//*"^",		OPR | LXOR,	4,*//*"&",		OPR | LAND,	5,*/{"+",		OPR | PLUS,	6},{"-",		OPR | MINUS, 6},{"*",		OPR | MULT,	7},{"/",		OPR | DIV,	7},/*"%",		OPR | MOD,	7,*/{"(",		OPR | LPAREN,	11},{")",		OPR | RPAREN,	11},{"\0",		ILLEG, 0}};#define NOPR 8/*	the symbol table of indirect variables: */extern long double PIL;struct varent indtbl[] = {{"t",		VAR | IND,	&vs[21]},{"u",		VAR | IND,	&vs[20]},	{"v",		VAR | IND,	&vs[19]},{"w",		VAR | IND,	&vs[18]},	{"x",		VAR | IND,	&vs[10]},{"y",		VAR | IND,	&vs[11]},{"z",		VAR | IND,	&vs[12]},{"pi",		VAR | IND,	&PIL},{"\0",		ILLEG,		0}};/*	the symbol table of constants:	*/#define NCONST 10struct varent contbl[NCONST] = {{"C",CONST,&vs[0]},{"C",CONST,&vs[1]},{"C",CONST,&vs[2]},{"C",CONST,&vs[3]},{"C",CONST,&vs[4]},{"C",CONST,&vs[5]},{"C",CONST,&vs[6]},{"C",CONST,&vs[7]},{"C",CONST,&vs[8]},{"\0",CONST,&vs[9]}};/* the symbol table of string variables: */static char strngs[160] = {0};#define NSTRNG 5struct strent strtbl[NSTRNG] = {{0, VAR | STRING, 0},{0, VAR | STRING, 0},{0, VAR | STRING, 0},{0, VAR | STRING, 0},{"\0",ILLEG,0},};/* Help messages */#if INTHELPstatic char *intmsg[] = {"?","Unkown symbol","Expression ends in illegal operator","Precede ( by operator",")( is illegal","Unmatched )","Missing )","Illegal left hand side","Missing symbol","Must assign to a variable","Divide by zero","Missing symbol","Missing operator","Precede quantity by operator","Quantity preceded by )","Function syntax","Too many function args","No more temps","Arg list"};#endif/*	the symbol table of functions:	*/#if SALONElong double hex(), cmdh(), cmdhlp();long double cmddm(), cmdtm(), cmdem();long double take(), mxit(), bits(), csys();long double cmddig(), prhlst(), abmac();long double ifrac();long double floorl(), logl(), powl(), sqrtl(), tanhl(), expl();long double asinl(), acosl(), atanl(), sinl(), cosl(), tanl();long double sinhl(), asinhl(), coshl(), acoshl(), atanhl(), cbrtl();long double log10l(), exp10l(), log2l(), exp2l(), compare();struct funent funtbl[] = {{"h",		OPR | FUNC, cmdh},{"help",	OPR | FUNC, cmdhlp},{"hex",		OPR | FUNC, hex},/*"view",		OPR | FUNC, view,*/{"asin",		OPR | FUNC, asinl},{"sin",		OPR | FUNC, sinl},{"acos",		OPR | FUNC, acosl},{"cos",		OPR | FUNC, cosl},{"atan",		OPR | FUNC, atanl},{"tan",		OPR | FUNC, tanl},{"asinh",		OPR | FUNC, asinhl},{"sinh",		OPR | FUNC, sinhl},{"acosh",		OPR | FUNC, acoshl},{"cosh",		OPR | FUNC, coshl},{"atanh",		OPR | FUNC, atanhl},{"tanh",		OPR | FUNC, tanhl},{"exp",		OPR | FUNC, expl},{"exptwo",		OPR | FUNC, exp2l},{"expten",		OPR | FUNC, exp10l},{"log",		OPR | FUNC, logl},{"logtwo",		OPR | FUNC, log2l},{"logten",		OPR | FUNC, log10l},{"pow",		OPR | FUNC, powl},{"sqrt",	OPR | FUNC, sqrtl},{"cbrt",	OPR | FUNC, cbrtl},{"ifrac",	OPR | FUNC, ifrac},{"floor",	OPR | FUNC, floorl},{"cmp",	OPR | FUNC, compare},{"bits",	OPR | FUNC, bits},{"digits",	OPR | FUNC, cmddig},{"dm",		OPR | FUNC, cmddm},{"tm",		OPR | FUNC, cmdtm},{"em",		OPR | FUNC, cmdem},{"take",	OPR | FUNC | COMMAN, take},{"system",	OPR | FUNC | COMMAN, csys},{"exit",	OPR | FUNC, mxit},/*"remain",	OPR | FUNC, eremain,*/{"\0",		OPR | FUNC,	0}};/*	the symbol table of key words */struct funent keytbl[] = {{"\0",		ILLEG,	0}};#endifvoid zgets();/* Number of decimals to display */#define DEFDIS 70static int ndigits = DEFDIS;/* Menu stack */struct funent *menstk[5] = {&funtbl[0], NULL, NULL, NULL, NULL};int menptr = 0;/* Take file stack */FILE *takstk[10] = {0};int takptr = -1;/* size of the expression scan list: */#define NSCAN 20/* previous token, saved for syntax checking: */struct symbol *lastok = 0;/*	variables used by parser: */static char str[128] = {0};int uposs = 0;		/* possible unary operator */static long double qnc;char lc[40] = { '\n' };	/*	ASCII string of token	symbol	*/static char line[LINLEN] = { '\n','\0' };	/* input command line */static char maclin[LINLEN] = { '\n','\0' };	/* macro command */char *interl = line;		/* pointer into line */extern char *interl;static int maccnt = 0;	/* number of times to execute macro command */static int comptr = 0;	/* comma stack pointer */static long double comstk[5];	/* comma argument stack */static int narptr = 0;	/* pointer to number of args */static int narstk[5] = {0};	/* stack of number of function args *//*							main()		*//*	Entire program starts here	*/int main(){/*	the scan table:			*//*	array of pointers to symbols which have been parsed:	*/struct symbol *ascsym[NSCAN];/*	current place in ascsym:			*/register struct symbol **as;/*	array of attributes of operators parsed:		*/int ascopr[NSCAN];/*	current place in ascopr:			*/register int *ao;#if LARGEMEM/*	array of precedence levels of operators:		*/long asclev[NSCAN];/*	current place in asclev:			*/long *al;long symval;	/* value of symbol just parsed */#elseint asclev[NSCAN];int *al;int symval;#endiflong double acc;	/* the accumulator, for arithmetic */int accflg;	/* flags accumulator in use	*/long double val;	/* value to be combined into accumulator */register struct symbol *psym;	/* pointer to symbol just parsed */struct varent *pvar;	/* pointer to an indirect variable symbol */struct funent *pfun;	/* pointer to a function symbol */struct strent *pstr;	/* pointer to a string symbol */int att;	/* attributes of symbol just parsed */int i;		/* counter	*/int offset;	/* parenthesis level */int lhsflg;	/* kluge to detect illegal assignments */struct symbol *parser();	/* parser returns pointer to symbol */int errcod;	/* for syntax error printout *//* Perform general initialization */init();menstk[0] = &funtbl[0];menptr = 0;cmdhlp();		/* print out list of symbols *//*	Return here to get next command line to execute	*/getcmd:/* initialize registers and mutable symbols */accflg = 0;	/* Accumulator not in use				*/acc = 0.0L;	/* Clear the accumulator				*/offset = 0;	/* Parenthesis level zero				*/comptr = 0;	/* Start of comma stack					*/narptr = -1;	/* Start of function arg counter stack	*/psym = (struct symbol *)&contbl[0];for( i=0; i<NCONST; i++ )	{	psym->attrib = CONST;	/* clearing the busy bit */	++psym;	}psym = (struct symbol *)&temp[0];for( i=0; i<NTEMP; i++ )	{	psym->attrib = VAR | TEMP;	/* clearing the busy bit */	++psym;	}pstr = &strtbl[0];for( i=0; i<NSTRNG; i++ )	{	pstr->spel = &strngs[ 40*i ];	pstr->attrib = STRING | VAR;	pstr->string = &strngs[ 40*i ];	++pstr;	}/*	List of scanned symbols is empty:	*/as = &ascsym[0];*as = 0;--as;/*	First item in scan list is Beginning of Line operator	*/ao = &ascopr[0];*ao = oprtbl[0].attrib & 0xf;	/* BOL *//*	value of first item: */al = &asclev[0];*al = oprtbl[0].sym;lhsflg = 0;		/* illegal left hand side flag */psym = &oprtbl[0];	/* pointer to current token *//*	get next token from input string	*/gettok:lastok = psym;		/* last token = current token */psym = parser();	/* get a new current token *//*printf( "%s attrib %7o value %7o\n", psym->spel, psym->attrib & 0xffff,		psym->sym );*//* Examine attributes of the symbol returned by the parser	*/att = psym->attrib;if( att == ILLEG )	{	errcod = 1;	goto synerr;	}/*	Push functions onto scan list without analyzing further */if( att & FUNC )	{	/* A command is a function whose argument is	 * a pointer to the rest of the input line.	 * A second argument is also passed: the address	 * of the last token parsed.	 */	if( att & COMMAN )		{		pfun = (struct funent *)psym;		( *(pfun->fun))( interl, lastok );		abmac();	/* scrub the input line */		goto getcmd;	/* and ask for more input */		}	++narptr;	/* offset to number of args */	narstk[narptr] = 0;	i = lastok->attrib & 0xffff; /* attrib=short, i=int */	if( ((i & OPR) == 0)			|| (i == (OPR | RPAREN))			|| (i == (OPR | FUNC)) )		{		errcod = 15;		goto synerr;		}	++lhsflg;	++as;	*as = psym;	++ao;	*ao = FUNC;	++al;	*al = offset + UMINUS;	goto gettok;	}/* deal with operators */if( att & OPR )	{	att &= 0xf;	/* expression cannot end with an operator other than	 * (, ), BOL, or a function	 */	if( (att == RPAREN) || (att == EOL) || (att == EOE))		{		i = lastok->attrib & 0xffff; /* attrib=short, i=int */		if( (i & OPR) 			&& (i != (OPR | RPAREN))			&& (i != (OPR | LPAREN))			&& (i != (OPR | FUNC))			&& (i != (OPR | BOL)) )				{				errcod = 2;				goto synerr;				}		}	++lhsflg;	/* any operator but ( and = is not a legal lhs *//*	operator processing, continued */	switch( att )		{ 	case EOE:		lhsflg = 0;		break; 	case LPAREN:		/* ( must be preceded by an operator of some sort. */		if( ((lastok->attrib & OPR) == 0) )			{			errcod = 3;			goto synerr;			}		/* also, a preceding ) is illegal */		if( (unsigned short )lastok->attrib == (OPR|RPAREN))			{			errcod = 4;			goto synerr;			}		/* Begin looking for illegal left hand sides: */		lhsflg = 0;		offset += RPAREN;	/* new parenthesis level */		goto gettok;	case RPAREN:		offset -= RPAREN;	/* parenthesis level */		if( offset < 0 )			{			errcod = 5;	/* parenthesis error */			goto synerr;			}		goto gettok;	case EOL:		if( offset != 0 )			{			errcod = 6;	/* parenthesis error */			goto synerr;			}		break;	case EQU:		if( --lhsflg )	/* was incremented before switch{} */			{			errcod = 7;			goto synerr;			}	case UMINUS:	case COMP:		goto pshopr;	/* evaluate right to left */	default:	;		}/*	evaluate expression whenever precedence is not increasing	*/symval = psym->sym + offset;while( symval <= *al )	{	/* if just starting, must fill accumulator with last	 * thing on the line	 */	if( (accflg == 0) && (as >= ascsym) && (((*as)->attrib & FUNC) == 0 ))		{		pvar = (struct varent *)*as;/*		if( pvar->attrib & STRING )			strcpy( (char *)&acc, (char *)pvar->value );		else*/			acc = *pvar->value;		--as;		accflg = 1;		}/* handle beginning of line type cases, where the symbol * list ascsym[] may be empty. */	switch( *ao )		{	case BOL:	/*		printf( "%.16e\n", (double )acc ); *//*		e64toasc( &acc, str, 100 );*/		e113toasc( &acc, str, 100 );		printf( "%s\n", str );		goto getcmd;	/* all finished */	case UMINUS:		acc = -acc;		goto nochg;/*	case COMP:		acc = ~acc;		goto nochg;*/	default:	;		}/* Now it is illegal for symbol list to be empty, * because we are going to need a symbol below. */	if( as < &ascsym[0] )		{		errcod = 8;		goto synerr;		}/* get attributes and value of current symbol */	att = (*as)->attrib;	pvar = (struct varent *)*as;	if( att & FUNC )		val = 0.0L;	else		{/*		if( att & STRING )			strcpy( (char *)&val, (char *)pvar->value );		else*/			val = *pvar->value;		}/* Expression evaluation, continued. */	switch( *ao )		{	case FUNC:		pfun = (struct funent *)*as;	/* Call the function with appropriate number of args */	i = narstk[ narptr ];	--narptr;	switch(i)			{			case 0:			acc = ( *(pfun->fun) )(acc);			break;			case 1:			acc = ( *(pfun->fun) )(acc, comstk[comptr-1]);			break;			case 2:			acc = ( *(pfun->fun) )(acc, comstk[comptr-2],				comstk[comptr-1]);			break;			case 3:			acc = ( *(pfun->fun) )(acc, comstk[comptr-3],				comstk[comptr-2], comstk[comptr-1]);			break;			default:			errcod = 16;			goto synerr;			}		comptr -= i;		accflg = 1;	/* in case at end of line */		break;	case EQU:		if( ( att & TEMP) || ((att & VAR) == 0) || (att & STRING) )			{			errcod = 9;			goto synerr;	/* can only assign to a variable */			}		pvar = (struct varent *)*as;		*pvar->value = acc;		break;	case PLUS:		acc = acc + val;	break;	case MINUS:		acc = val - acc;	break;	case MULT:		acc = acc * val;	break;	case DIV:		if( acc == 0.0L )			{/*divzer:*/			errcod = 10;			goto synerr;			}		acc = val / acc;	break;/*	case MOD:		if( acc == 0 )			goto divzer;		acc = val % acc;	break;	case LOR:		acc |= val;		break;	case LXOR:		acc ^= val;		break;	case LAND:		acc &= val;		break;*/	case EOE:		if( narptr < 0 )			{			errcod = 18;			goto synerr;			}		narstk[narptr] += 1;		comstk[comptr++] = acc;/*	printf( "\ncomptr: %d narptr: %d %d\n", comptr, narptr, acc );*/		acc = val;		break;		}/*	expression evaluation, continued		*//* Pop evaluated tokens from scan list:		*/	/* make temporary variable not busy	*/	if( att & TEMP )		(*as)->attrib &= ~BUSY;	if( as < &ascsym[0] )	/* can this happen? */		{		errcod = 11;		goto synerr;		}	--as;nochg:	--ao;	--al;	if( ao < &ascopr[0] )	/* can this happen? */		{		errcod = 12;		goto synerr;		}/* If precedence level will now increase, then			*//* save accumulator in a temporary location			*/	if( symval > *al )		{		/* find a free temp location */		pvar = &temp[0];		for( i=0; i<NTEMP; i++ )			{			if( (pvar->attrib & BUSY) == 0)				goto temfnd;			++pvar;			}		errcod = 17;		printf( "no more temps\n" );		pvar = &temp[0];		goto synerr;	temfnd:		pvar->attrib |= BUSY;		*pvar->value = acc;		/*printf( "temp %d\n", acc );*/		accflg = 0;		++as;	/* push the temp onto the scan list */		*as = (struct symbol *)pvar;		}	}	/* End of evaluation loop *//*	Push operator onto scan list when precedence increases	*/pshopr:	++ao;	*ao = psym->attrib & 0xf;	++al;	*al = psym->sym + offset;	goto gettok;	}	/* end of OPR processing *//* Token was not an operator.  Push symbol onto scan list.	*/if( (lastok->attrib & OPR) == 0 )	{	errcod = 13;	goto synerr;	/* quantities must be preceded by an operator */	}if( (unsigned short )lastok->attrib == (OPR | RPAREN) )	/* ...but not by ) */	{	errcod = 14;	goto synerr;	}++as;*as = psym;goto gettok;synerr:#if INTHELPprintf( "%s ", intmsg[errcod] );#endifprintf( " error %d\n", errcod );abmac();	/* flush the command line */goto getcmd;}	/* end of program *//*						parser()	*//* Get token from input string and identify it.		*/static char number[128];struct symbol *parser( ){register struct symbol *psym;

⌨️ 快捷键说明

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