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 4
- struct 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 10
- struct 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 5
- struct 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 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
- #ifdef ANSIPROT
- double floor ( double );
- int dprec ( void );
- #else
- double floor();
- int dprec();
- #endif
- /* the symbol table of functions: */
- #if SALONE
- #ifdef ANSIPROT
- extern 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 );
- #else
- void 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 GLIBC2
- double 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}
- };
- #endif
- void zgets();
- /* 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 */
- 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 */
- #else
- int asclev[NSCAN];
- int *al;
- int symval;
- #endif
- double 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 INTHELP
- printf( "%s ", intmsg[errcod] );
- #endif
- printf( " 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;
- else
- pdon3: 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 SALONE
- double 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 16
- double 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 IBMPC
- l = a;
- u.i[3] = l >> 16;
- u.i[2] = l;
- l = b;
- u.i[1] = l >> 16;
- u.i[0] = l;
- #endif
- #ifdef DEC
- l = a;
- u.i[3] = l >> 16;
- u.i[2] = l;
- l = b;
- u.i[1] = l >> 16;
- u.i[0] = l;
- #endif
- #ifdef MIEEE
- l = a;
- u.i[0] = l >> 16;
- u.i[1] = l;
- l = b;
- u.i[2] = l >> 16;
- u.i[3] = l;
- #endif
- #ifdef UNK
- l = a;
- u.i[0] = l >> 16;
- u.i[1] = l;
- l = b;
- u.i[2] = l >> 16;
- u.i[3] = l;
- #endif
- return(u.d);
- }
|