home *** CD-ROM | disk | FTP | other *** search
- /* calc.c */
- /* Keyboard command interpreter */
- /* Copyright 1985 by S. L. Moshier */
-
- #include <stdio.h>
- #include "qhead.h"
-
- /*
- *#include "config.h"
- */
-
- /* 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 printf: */
- #define INIPRINTF 0
-
- #if DECPDP
- #define TRUE 1
- #endif
-
-
- 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();
- /* I/O log file: */
- static char *savnam = 0;
- static FILE *savfil = 0;
-
-
- #include "qcalc.h"
-
- /* space for double precision numbers */
- static int vsp = 13;
- static short vs[22][NQ] = {0};
-
- /* the symbol table of temporary variables: */
-
- #define NTEMP 4
- struct varent temp[NTEMP] = {
- "T", OPR | TEMP, &vs[14][0],
- "T", OPR | TEMP, &vs[15][0],
- "T", OPR | TEMP, &vs[16][0],
- "\0", OPR | TEMP, &vs[17][0]
- };
-
- /* 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 short qpi[];
- struct varent indtbl[] = {
- "t", VAR | IND, &vs[21][0],
- "u", VAR | IND, &vs[20][0],
- "v", VAR | IND, &vs[19][0],
- "w", VAR | IND, &vs[18][0],
- "x", VAR | IND, &vs[10][0],
- "y", VAR | IND, &vs[11][0],
- "z", VAR | IND, &vs[12][0],
- "pi", VAR | IND, &qpi[0],
- "\0", ILLEG, 0
- };
-
- /* the symbol table of constants: */
-
- #define NCONST 10
- struct varent contbl[NCONST] = {
- "C",CONST,&vs[0][0],
- "C",CONST,&vs[1][0],
- "C",CONST,&vs[2][0],
- "C",CONST,&vs[3][0],
- "C",CONST,&vs[4][0],
- "C",CONST,&vs[5][0],
- "C",CONST,&vs[6][0],
- "C",CONST,&vs[7][0],
- "C",CONST,&vs[8][0],
- "\0",CONST,&vs[9][0]
- };
-
- /* the symbol table of string variables: */
-
- static char strngs[4][40] = {0};
-
- #define NSTRNG 5
- struct strent strtbl[NSTRNG] = {
- #if DECPDP
- &strngs[0][0], VAR | STRING, &strngs[0][0],
- &strngs[1][0], VAR | STRING, &strngs[1][0],
- &strngs[2][0], VAR | STRING, &strngs[2][0],
- &strngs[3][0], VAR | STRING, &strngs[3][0],
- #else
- &strngs[0][0], VAR | STRING, &strngs[0][0],
- &strngs[1][0], VAR | STRING, &strngs[1][0],
- &strngs[2][0], VAR | STRING, &strngs[2][0],
- &strngs[3][0], VAR | STRING, &strngs[3][0],
- #endif
- "\0",ILLEG,0,
- };
-
-
- /* Help messages */
- #if INTHELP
- static 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 SALONE
- int hex(), cmdh(), cmdhlp();
- /*int view();*/
- int cmddm(), cmdtm(), cmdem();
- /*int printf();*/
- int take(), mxit(), exit(), bits();
- int cmddig(), qfloor(), todbl();
- int qsqrt(), qlog(), qexp(), qtanh(), qpow();
- int qsave(), qsys();
- /*
- int qsin(), qcos(), qatn(), qjn(), qyn();
- int qasin(), qtan(), qcosh(), qsinh(), qasinh(), qacosh();
- int qacos(), qatanh(), qcot(), qgamma(), qcbrt(), qfac();
- */
- /* log10(), exp10(), ndtr(), ndtri();*/
-
- struct funent funtbl[] = {
- "h", OPR | FUNC, cmdh,
- "help", OPR | FUNC, cmdhlp,
- "hex", OPR | FUNC, hex,
- /*"view", OPR | FUNC, view,*/
- /*
- "acos", OPR | FUNC, qacos,
- "acosh", OPR | FUNC, qacosh,
- "asin", OPR | FUNC, qasin,
- "asinh", OPR | FUNC, qasinh,
- "atan", OPR | FUNC, qatn,
- "atanh", OPR | FUNC, qatanh,
- "cbrt", OPR | FUNC, qcbrt,
- "cos", OPR | FUNC, qcos,
- "cosh", OPR | FUNC, qcosh,
- "cot", OPR | FUNC, qcot,
- */
- "exp", OPR | FUNC, qexp,
- /*"fac", OPR | FUNC, qfac,*/
- "floor", OPR | FUNC, qfloor,
- /*
- "gamma", OPR | FUNC, qgamma,
- "jv", OPR | FUNC, qjn,
- "yn", OPR | FUNC, qyn,
- "logten", OPR | FUNC, qlog10,
- "expten", OPR | FUNC, qexp10,
- */
- "log", OPR | FUNC, qlog,
- /*
- "ndtr", OPR | FUNC, ndtr,
- "ndtri", OPR | FUNC, ndtri,
- */
- "pow", OPR | FUNC, qpow,
- /*
- "sin", OPR | FUNC, qsin,
- "sinh", OPR | FUNC, qsinh,
- */
- "sqrt", OPR | FUNC, qsqrt,
- /*"tan", OPR | FUNC, qtan,*/
- "tanh", OPR | FUNC, qtanh,
- "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,
- "save", OPR | FUNC | COMMAN, qsave,
- "system", OPR | FUNC | COMMAN, qsys,
- "exit", OPR | FUNC, mxit,
- "\0", OPR | FUNC, 0
- };
-
- /* the symbol table of key words */
- struct funent keytbl[] = {
- "\0", ILLEG, 0
- };
- #endif
-
- /* Number of decimals to display */
- #define DEFDIS 70
- static 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 */
- double nc = 0; /* numeric value of symbol */
- static short qnc[NQ] = {0};
- 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 int comstk[5][NQ] = {0}; /* 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 */
-
- 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 */
- #else
- int asclev[NSCAN];
- int *al;
- int symval;
- #endif
-
- short acc[NQ]; /* the accumulator, for arithmetic */
- int accflg; /* flags accumulator in use */
- int val[NQ]; /* 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 *tsym; /* pointer to temporary symbol */
- 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 */
- qclear(acc); /* 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;
- }
-
- psym = (struct symbol *)&strtbl[0];
- for( i=0; i<NSTRNG; i++ )
- {
- psym->attrib = STRING | VAR;
- ++psym;
- }
-
- /* 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;
- qmov( pvar->value, acc );
- --as;
- accflg = 1;
- }
-
- /* handle beginning of line type cases, where the symbol
- * list ascsym[] may be empty.
- */
- switch( *ao )
- {
- case BOL:
- qtoasc( acc, str, ndigits );
- printf( "%s\n", str ); /* This is the answer */
- if( savfil )
- fprintf( savfil, "%s\n", str );
- goto getcmd; /* all finished */
- case UMINUS:
- qneg( 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 )
- qclear( val );
- else
- qmov( pvar->value, val );
-
- /* 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:
- ( *(pfun->fun) )(acc, acc);
- break;
- case 1:
- ( *(pfun->fun) )(acc,comstk[comptr-1],acc);
- break;
- case 2:
- ( *(pfun->fun) )(acc, comstk[comptr-2],
- comstk[comptr-1],acc);
- break;
- case 3:
- ( *(pfun->fun) )(acc, comstk[comptr-3],
- comstk[comptr-2], comstk[comptr-1],acc);
- 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;
- qmov( acc, pvar->value );
- break;
- case PLUS:
- qadd( acc, val, acc ); break;
- case MINUS:
- qsub( acc, val, acc ); break;
- case MULT:
- qmul( acc, val, acc ); break;
- case DIV:
- if( acc[1] == 0 )
- {
- divzer:
- errcod = 10;
- goto synerr;
- }
- qdiv( 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;
- qmov( acc, comstk[comptr++] );
- /* printf( "\ncomptr: %d narptr: %d %d\n", comptr, narptr, acc );*/
- qmov( val, acc );
- 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;
- }
- noval:
- /* 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;
- qmov( acc, pvar->value );
- /*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 INTHELP
- printf( "%s ", intmsg[errcod] );
- #endif
- printf( " error %d\n", errcod );
- if( savfil )
- fprintf( savfil, " 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[40] = {0};
-
- struct symbol *parser( )
- {
- register struct symbol *psym;
- register char *pline;
- struct varent *pvar;
- struct strent *pstr;
- char *cp, *plc, *pn;
- int i;
- /* 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("* ");
- if( savfil )
- fprintf( savfil, "* " );
- }
- /* 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 == '.') )
- {
- nc = 0.0; /* initialize numeric input to zero */
- qclear( qnc );
- /*******/
- 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;
- nc = (nc * 16.0) + i;
- etoq( &nc, qnc );
- }
- goto numdon;
- }
- else
- {
- while( ISOCTAL( *pline ) )
- {
- i = *pline++ & 0xff - 060;
- nc = ( nc * 8.0) + i;
- etoq( &nc, qnc );
- }
- 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;
- asctoq( number, qnc );
- /* sscanf( number, "%le", &nc );*/
- }
- /* 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;
- if( qcmp( pvar->value, qnc) == 0 )
- {
- 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;
- qmov( qnc, pvar->value );
- 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:
- plc = (char *)(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) = '\0';
- pstr->attrib |= BUSY;
- 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;
- else
- pdon3: uposs = 1;
-
- interl = pline;
- return( psym );
- } /* end of parser */
-
- /* exit from current menu */
-
- cmdex()
- {
-
- if( menptr == 0 )
- {
- printf( "Main menu is active.\n" );
- }
- else
- --menptr;
-
- cmdh();
- return(0);
- }
-
-
- /* gets() */
-
- 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 */
- if( savfil )
- fprintf( savfil, "%s\n", gline );
- }
-
-
- /* help function */
- 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);
- }
-
-
- cmdh()
- {
-
- prhlst( menstk[menptr] );
- printf( "\n" );
- return(0.0);
- }
-
- /* print keyword spellings */
-
- prhlst(ps)
- register struct symbol *ps;
- {
- register int j, k;
- int m;
-
- 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;
- }
- }
-
-
- #if SALONE
- init(){}
- #endif
-
-
- /* macro commands */
-
- /* define macro */
- cmddm(arg)
- int arg;
- {
-
- zgets( maclin, TRUE );
- return(0.0);
- }
-
- /* type (i.e., display) macro */
- cmdtm(arg)
- int arg;
- {
-
- printf( "%s\n", maclin );
- return(0.0);
- }
-
- /* execute macro # times */
- cmdem( arg )
- int *arg;
- {
- double dn;
- int n;
-
- qtoe( arg, &dn );
- n = dn;
- if( n <= 0 )
- n = 1;
- maccnt = n;
- return( n );
- }
-
-
- /* open a take file */
-
- take( fname )
- char *fname;
- {
- FILE *f;
- register int i;
-
- while( *fname == ' ' )
- fname += 1;
- f = fopen( fname, "r" );
-
- if( f == 0 )
- {
- takerr:
- printf( "Can't open take file %s\n", fname );
- takptr = -1; /* terminate all take file input */
- return(-1);
- }
- takptr += 1;
- takstk[ takptr ] = f;
- printf( "Running %s\n", fname );
- return(0.0);
- }
-
-
- /* abort macro execution */
- abmac()
- {
-
- maccnt = 0;
- interl = line;
- }
-
-
- /* display integer part in hex, octal, and decimal
- */
-
- hex(qx)
- short *qx;
- {
- long z;
- double x;
- double fabs();
-
- qtoe( qx, &x );
- if( fabs(x) >= 2.147483648e9 )
- {
- printf( "hex: too large\n" );
- return(x);
- }
-
- z = x;
- printf( "0%lo 0x%lx %ld.\n", z, z, z );
- return(x);
- }
-
-
- int bits( x )
- short x[];
- {
- int i, j;
-
- j = 0;
- for( i=0; i<NQ; i++ )
- {
- printf( "0x%04x,", x[i] & 0xffff );
- if( ++j > 7 )
- {
- j = 0;
- printf( "\n" );
- }
- }
- printf( "\n" );
-
- /* display IEEE format double precision version */
- todbl( x );
-
- return(0);
- }
-
-
- /* Exit to monitor. */
- mxit()
- {
-
- if( savfil )
- fclose( savfil );
- exit(0);
- }
-
-
- cmddig( x )
- short x[];
- {
- double dx;
-
- qtoe( x, &dx );
- ndigits = dx;
- if( ndigits <= 0 )
- ndigits = DEFDIS;
- return(0);
- }
-
-
-
- todbl( u )
- short u[];
- {
- short x[NQ+1];
- long e;
- int i;
-
- qmovz( u, x );
- shup1(x);
- shup1(x);
- shup1(x);
- shup1(x);
- shup1(x);
-
- e = x[1];
- e = e - 040001 + 0x3ff;
- if( e < -101 )
- {
- qclear(x );
- goto display;
- }
- /* denormalize if exponent is nonpositive */
- if( e <= 0 )
- {
- while( e <= 0 )
- {
- shdn1(x);
- e += 1;
- }
- e = 0;
- }
- e = (e << 4) & 0x7ff0;
- if( x[0] )
- e |= 0x8000;
- x[2] &= 0xf;
- x[2] |= e;
-
- display:
-
- for( i=0; i<6; i++ )
- printf( "%04x ", x[7-i] & 0xffff );
- printf( "\n" );
-
- qtoe( u, x );
- for( i=0; i<4; i++ )
- printf( "%04x ", x[i] & 0xffff );
- printf( "\n" );
- }
-
-
- qsave(x)
- char *x;
- {
-
- if( savfil )
- fclose( savfil );
- while( *x == ' ' )
- x += 1;
- if( *x == '\0' )
- savnam = "calc.sav";
- else
- savnam = x;
- savfil = fopen( savnam, "w" );
- if( savfil <= 0 )
- printf( "Error opening %s\n", savnam );
- }
-
-
-
- qsys(x)
- char *x;
- {
-
- system( x+1 );
- cmdh();
- }
-