| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512 | /* calc.c *//* Keyboard command interpreter	*//* by Stephen L. Moshier *//* 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>#include <string.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 "dcalc.h"/* #include "ehead.h" */#include <math.h>/* int strlen(), strcmp(); */int system();/* space for working precision numbers */static 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 double PI;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,	&PI},{"\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#ifdef ANSIPROTdouble floor ( double );int dprec ( void );#elsedouble floor();int dprec();#endif/*	the symbol table of functions:	*/#if SALONE#ifdef ANSIPROTextern double floor ( double );extern double log ( double );extern double pow ( double, double );extern double sqrt ( double );extern double tanh ( double );extern double exp ( double );extern double fabs ( double );extern double hypot ( double, double );extern double frexp ( double, int * );extern double ldexp ( double, int );extern double incbet ( double, double, double );extern double incbi ( double, double, double );extern double sin ( double );extern double cos ( double );extern double atan ( double );extern double atan2 ( double, double );extern double gamma ( double );extern double lgam ( double );double zfrexp ( double );double zldexp ( double, double );double makenan ( double );double makeinfinity ( double );double hex ( double );double hexinput ( double, double );double cmdh ( void );double cmdhlp ( void );double init ( void );double cmddm ( void );double cmdtm ( void );double cmdem ( double );double take ( char * );double mxit ( void );double bits ( double );double csys ( char * );double cmddig ( double );double prhlst ( void * );double abmac ( void );double ifrac ( double );double xcmpl ( double, double );void exit ( int );#elsevoid exit();double hex(), hexinput(), cmdh(), cmdhlp(), init();double cmddm(), cmdtm(), cmdem();double take(), mxit(), bits(), csys();double cmddig(), prhlst(), abmac();double ifrac(), xcmpl();double floor(), log(), pow(), sqrt(), tanh(), exp(), fabs(), hypot();double frexp(), zfrexp(), ldexp(), zldexp(), makenan(), makeinfinity();double incbet(), incbi(), sin(), cos(), atan(), atan2(), gamma(), lgam();#define GLIBC2 0#if GLIBC2double lgamma();#endif#endif /* not ANSIPROT */struct funent funtbl[] = {{"h",		OPR | FUNC, cmdh},{"help",	OPR | FUNC, cmdhlp},{"hex",		OPR | FUNC, hex},{"hexinput",		OPR | FUNC, hexinput},/*"view",		OPR | FUNC, view,*/{"exp",		OPR | FUNC, exp},{"floor",	OPR | FUNC, floor},{"log",		OPR | FUNC, log},{"pow",		OPR | FUNC, pow},{"sqrt",	OPR | FUNC, sqrt},{"tanh",	OPR | FUNC, tanh},{"sin",		OPR | FUNC, sin},{"cos",		OPR | FUNC, cos},{"atan",	OPR | FUNC, atan},{"atantwo",	OPR | FUNC, atan2},{"tanh",	OPR | FUNC, tanh},{"gamma",	OPR | FUNC, gamma},#if GLIBC2{"lgamma",	OPR | FUNC, lgamma},#else{"lgam",	OPR | FUNC, lgam},#endif{"incbet",	OPR | FUNC, incbet},{"incbi",	OPR | FUNC, incbi},{"fabs",	OPR | FUNC, fabs},{"hypot",	OPR | FUNC, hypot},{"ldexp",	OPR | FUNC, zldexp},{"frexp",	OPR | FUNC, zfrexp},{"nan",	        OPR | FUNC, makenan},{"infinity",	OPR | FUNC, makeinfinity},{"ifrac",	OPR | FUNC, ifrac},{"cmp",		OPR | FUNC, xcmpl},{"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 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 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;#endifdouble acc;	/* the accumulator, for arithmetic */int accflg;	/* flags accumulator in use	*/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.0;	/* 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", acc );#if 0#if NE == 6		e64toasc( &acc, str, 100 );#else		e113toasc( &acc, str, 100 );#endif#endif		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.0;	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.0 )			{/*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;register char *pline;struct varent *pvar;struct strent *pstr;char *cp, *plc, *pn;long lnc;int i;double tem;/* reference for old Whitesmiths compiler: *//* *extern FILE *stdout; */pline = interl;		/* get current location in command string	*//*	If at beginning of string, must ask for more input	*/if( pline == line )	{	if( maccnt > 0 )		{		--maccnt;		cp = maclin;		plc = pline;		while( (*plc++ = *cp++) != 0 )			;		goto mstart;		}	if( takptr < 0 )		{	/* no take file active: prompt keyboard input */		printf("* ");		}/* 	Various ways of typing in a command line. *//* * Old Whitesmiths call to print "*" immediately * use RT11 .GTLIN to get command string * from command file or terminal *//* *	fflush(stdout); *	gtlin(line); */ 	zgets( line, TRUE );	/* keyboard input for other systems: */mstart:	uposs = 1;	/* unary operators possible at start of line */	}ignore:/* Skip over spaces */while( *pline == ' ' )	++pline;/* unary minus after operator */if( uposs && (*pline == '-') )	{	psym = &oprtbl[2];	/* UMINUS */	++pline;	goto pdon3;	}	/* COMP *//*if( uposs && (*pline == '~') )	{	psym = &oprtbl[3];	++pline;	goto pdon3;	}*/if( uposs && (*pline == '+') )	/* ignore leading plus sign */	{	++pline;	goto ignore;	}/* end of null terminated input */if( (*pline == '\n') || (*pline == '\0') || (*pline == '\r') )	{	pline = line;	goto endlin;	}if( *pline == ';' )	{	++pline;endlin:	psym = &oprtbl[1];	/* EOL */	goto pdon2;	}/*						parser()	*//* Test for numeric input */if( (ISDIGIT(*pline)) || (*pline == '.') )	{	lnc = 0;	/* initialize numeric input to zero */	qnc = 0.0;	if( *pline == '0' )		{ /* leading "0" may mean octal or hex radix */		++pline;		if( *pline == '.' )			goto decimal; /* 0.ddd */		/* leading "0x" means hexadecimal radix */		if( (*pline == 'x') || (*pline == 'X') )			{			++pline;			while( ISXDIGIT(*pline) )				{				i = *pline++ & 0xff;				if( i >= 'a' )					i -= 047;				if( i >= 'A' )					i -= 07;				i -= 060;				lnc = (lnc << 4) + i;				qnc = lnc;				}			goto numdon;			}		else			{			while( ISOCTAL( *pline ) )				{				i = ((*pline++) & 0xff) - 060;				lnc = (lnc << 3) + i;				qnc = lnc;				}			goto numdon;			}		}	else		{		/* no leading "0" means decimal radix *//******/decimal:		pn = number;		while( (ISDIGIT(*pline)) || (*pline == '.') )			*pn++ = *pline++;/* get possible exponent field */		if( (*pline == 'e') || (*pline == 'E') )			*pn++ = *pline++;		else			goto numcvt;		if( (*pline == '-') || (*pline == '+') )			*pn++ = *pline++;		while( ISDIGIT(*pline) )			*pn++ = *pline++;numcvt:		*pn++ = ' ';		*pn++ = 0;#if 0#if NE == 6		asctoe64( number, &qnc );#else		asctoe113( number, &qnc );#endif#endif		sscanf( number, "%le", &qnc );		}/* output the number	*/numdon:	/* search the symbol table of constants 	*/	pvar = &contbl[0];	for( i=0; i<NCONST; i++ )		{		if( (pvar->attrib & BUSY) == 0 )			goto confnd;		tem = *pvar->value;		if( tem == qnc )			{			psym = (struct symbol *)pvar;			goto pdon2;			}		++pvar;		}	printf( "no room for constant\n" );	psym = (struct symbol *)&contbl[0];	goto pdon2;confnd:	pvar->spel= contbl[0].spel;	pvar->attrib = CONST | BUSY;	*pvar->value = qnc;	psym = (struct symbol *)pvar;	goto pdon2;	}/* check for operators */psym = &oprtbl[3];for( i=0; i<NOPR; i++ )	{	if( *pline == *(psym->spel) )		goto pdon1;	++psym;	}/* if quoted, it is a string variable */if( *pline == '"' )	{	/* find an empty slot for the string */	pstr = strtbl;	/* string table	*/	for( i=0; i<NSTRNG-1; i++ ) 		{		if( (pstr->attrib & BUSY) == 0 )			goto fndstr;		++pstr;		}	printf( "No room for string\n" );	pstr->attrib |= ILLEG;	psym = (struct symbol *)pstr;	goto pdon0;fndstr:	pstr->attrib |= BUSY;	plc = pstr->string;	++pline;	for( i=0; i<39; i++ )		{		*plc++ = *pline;		if( (*pline == '\n') || (*pline == '\0') || (*pline == '\r') )			{illstr:			pstr = &strtbl[NSTRNG-1];			pstr->attrib |= ILLEG;			printf( "Missing string terminator\n" );			psym = (struct symbol *)pstr;			goto pdon0;			}		if( *pline++ == '"' )			goto finstr;		}	goto illstr;	/* no terminator found */finstr:	--plc;	*plc = '\0';	psym = (struct symbol *)pstr;	goto pdon2;	}/* If none of the above, search function and symbol tables:	*//* copy character string to array lc[] */plc = &lc[0];while( ISALPHA(*pline) )	{	/* convert to lower case characters */	if( ISUPPER( *pline ) )		*pline += 040;	*plc++ = *pline++;	}*plc = 0;	/* Null terminate the output string *//*						parser()	*/psym = (struct symbol *)menstk[menptr];	/* function table	*/plc = &lc[0];cp = psym->spel;do	{	if( strcmp( plc, cp ) == 0 )		goto pdon3;	/* following unary minus is possible */	++psym;	cp = psym->spel;	}while( *cp != '\0' );psym = (struct symbol *)&indtbl[0];	/* indirect symbol table */plc = &lc[0];cp = psym->spel;do	{	if( strcmp( plc, cp ) == 0 )		goto pdon2;	++psym;	cp = psym->spel;	}while( *cp != '\0' );pdon0:pline = line;	/* scrub line if illegal symbol */goto pdon2;pdon1:++pline;if( (psym->attrib & 0xf) == RPAREN )pdon2:	uposs = 0;elsepdon3:	uposs = 1;interl = pline;return( psym );}		/* end of parser *//*	exit from current menu */double cmdex(){if( menptr == 0 )	{	printf( "Main menu is active.\n" );	}else	--menptr;cmdh();return(0.0);}/*			gets()		*/void zgets( gline, echo )char *gline;int echo;{register char *pline;register int i;scrub:pline = gline;getsl:	if( (pline - gline) >= LINLEN )		{		printf( "\nLine too long\n *" );		goto scrub;		}	if( takptr < 0 )		{	/* get character from keyboard *//*if DECPDP		gtlin( gline );		return(0);else*/		*pline = getchar();/*endif*/		}	else		{	/* get a character from take file */		i = fgetc( takstk[takptr] );		if( i == -1 )			{	/* end of take file */			if( takptr >= 0 )				{	/* close file and bump take stack */				fclose( takstk[takptr] );				takptr -= 1;				}			if( takptr < 0 )	/* no more take files:   */				printf( "*" ); /* prompt keyboard input */			goto scrub;	/* start a new input line */			}		*pline = i;		}	*pline &= 0x7f;	/* xon or xoff characters need filtering out. */	if ( *pline == XON || *pline == XOFF )		goto getsl;	/*	control U or control C	*/	if( (*pline == 025) || (*pline == 03) )		{		printf( "\n" );		goto scrub;		}	/*  Backspace or rubout */	if( (*pline == 010) || (*pline == 0177) )		{		pline -= 1;		if( pline >= gline )			{			if ( echo )				printf( "\010\040\010" );			goto getsl;			}		else			goto scrub;		}	if ( echo )		printf( "%c", *pline );	if( (*pline != '\n') && (*pline != '\r') )		{		++pline;		goto getsl;		}	*pline = 0;	if ( echo )		printf( "%c", '\n' );	/* \r already echoed */}/*		help function  */double cmdhlp(){printf( "%s", idterp );printf( "\nFunctions:\n" );prhlst( &funtbl[0] );printf( "\nVariables:\n" );prhlst( &indtbl[0] );printf( "\nOperators:\n" );prhlst( &oprtbl[2] );printf("\n");return(0.0);}double cmdh(){prhlst( menstk[menptr] );printf( "\n" );return(0.0);}/* print keyword spellings */double prhlst(vps)void *vps;{register int j, k;int m;register struct symbol *ps = vps;j = 0;while( *(ps->spel) != '\0' )	{	k = strlen( ps->spel )  -  1;/* size of a tab field is 2**3 chars */	m = ((k >> 3) + 1) << 3;	j += m;	if( j > 72 )		{		printf( "\n" );		j = m;		}	printf( "%s\t", ps->spel );	++ps;	}return(0.0);}#if SALONEdouble init(){/* Set coprocessor to double precision. */dprec();return 0.0;}#endif/*	macro commands *//*	define macro */double cmddm(){zgets( maclin, TRUE );return(0.0);}/*	type (i.e., display) macro */double cmdtm(){printf( "%s\n", maclin );return 0.0;}/*	execute macro # times */double cmdem( arg )double arg;{double f;long n;f = floor(arg);n = f;if( n <= 0 )	n = 1;maccnt = n;return(0.0);}/* open a take file */double take( fname )char *fname;{FILE *f;while( *fname == ' ' )	fname += 1;f = fopen( fname, "r" );if( f == 0 )	{	printf( "Can't open take file %s\n", fname );	takptr = -1;	/* terminate all take file input */	return 0.0;	}takptr += 1;takstk[ takptr ]  =  f;printf( "Running %s\n", fname );return(0.0);}/*	abort macro execution */double abmac(){maccnt = 0;interl = line;return(0.0);}/* display integer part in hex, octal, and decimal */double hex(qx)double qx;{double f;long z;f = floor(qx);z = f;printf( "0%lo  0x%lx  %ld.\n", z, z, z );return(qx);}#define NASC 16double bits( x )double x;{union  {    double d;    short i[4];  } du;union  {    float f;    short i[2];  } df;int i;du.d = x;printf( "double: " );for( i=0; i<4; i++ )	printf( "0x%04x,", du.i[i] & 0xffff );printf( "\n" );df.f = (float) x;printf( "float: " );for( i=0; i<2; i++ )	printf( "0x%04x,", df.i[i] & 0xffff );printf( "\n" );return(x);}/* Exit to monitor. */double mxit(){exit(0);return(0.0);}double cmddig( x )double x;{double f;long lx;f = floor(x);lx = f;ndigits = lx;if( ndigits <= 0 )	ndigits = DEFDIS;return(f);}double csys(x)char *x;{system( x+1 );cmdh();return(0.0);}double ifrac(x)double x;{unsigned long lx;long double y, z;z = floor(x);lx = z;y = x - z;printf( " int = %lx\n", lx );return(y);}double xcmpl(x,y)double x,y;{double ans;ans = -2.0;if( x == y )	{	printf( "x == y " );	ans = 0.0;	}if( x < y )	{	printf( "x < y" );	ans = -1.0;	}if( x > y )	{	printf( "x > y" );	ans = 1.0;	}return( ans );}extern double INFINITY, NAN;double makenan(x)double x;{return(NAN);}double makeinfinity(x)double x;{return(INFINITY);}double zfrexp(x)double x;{double y;int e;y = frexp(x, &e);printf("exponent = %d, significand = ", e );return(y);}double zldexp(x,e)double x, e;{double y;int i;i = e;y = ldexp(x,i);return(y);}double hexinput(a, b)double a,b;{union  {    double d;    unsigned short i[4];  } u;unsigned long l;#ifdef IBMPCl = a;u.i[3] = l >> 16;u.i[2] = l;l = b;u.i[1] = l >> 16;u.i[0] = l;#endif#ifdef DECl = a;u.i[3] = l >> 16;u.i[2] = l;l = b;u.i[1] = l >> 16;u.i[0] = l;#endif#ifdef MIEEEl = a;u.i[0] = l >> 16;u.i[1] = l;l = b;u.i[2] = l >> 16;u.i[3] = l;#endif#ifdef UNKl = a;u.i[0] = l >> 16;u.i[1] = l;l = b;u.i[2] = l >> 16;u.i[3] = l;#endifreturn(u.d);}
 |