#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 staticchar *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 #ifdef ANSIPROT int hex(QELT *), cmdh(void), cmdhlp(void), remark(char *), qsys(char *); int qsave(char *); int hexinput(QELT *, QELT *, QELT *), cmddig(QELT *); int cmddm(QELT *), cmdtm(QELT *), cmdem(QELT *); int take(char *), mxit(void), bits(qcmplx *), cmp(QELT *, QELT *, QELT *); int intcvts (QELT *, QELT *), todouble (QELT *, QELT *); struct symbol *parser(void); /* parser returns pointer to symbol */ int init(void), abmac(void), zgets(char *, int), prhlst(struct symbol *); int qmovz(QELT *, QELT *); int zpdtr(QELT *, QELT *, QELT *), zpdtri(QELT *, QELT *, QELT *); int makec( qcmplx *, qcmplx *, qcmplx * ); int getre( qcmplx *, qcmplx * ); int getim( qcmplx *, qcmplx * ); int qcarg( qcmplx *, qcmplx * ); int qccabs( qcmplx *, qcmplx * ); int qcconj( qcmplx *, qcmplx * ); int qchyp1f1( qcmplx *, qcmplx *, qcmplx *, qcmplx *); int qcerf( qcmplx *, qcmplx * ); int qcerfw( qcmplx *, qcmplx * ); int tolongdouble (qcmplx *, qcmplx *); double fabs(double); #else/* not ANSIPROT */ int hex(), cmdh(), cmdhlp(); int cmddm(), cmdtm(), cmdem(); int qtoe(), etoq(); int take(), mxit(), bits(); int cmddig(), qfloor(); int qsave(), qsys(); int makec(), getre(), getim(), qccabs(), qcarg(), qcconj(); int qcsqrt(), qclog(), qcexp(), qcsin(), qccos(), qcatan(); int qcasin(), qcacos(), qctan(), qccot(), qcpow(); int qfac(), qcgamma(), qclgam(); struct symbol *parser(); /* parser returns pointer to symbol */ int qmovz(), shup1(), shdn1(), qtoe113(), e113toq(), qtoe64(), e64toq(); int e24toq(), qtoe24(); int init(), abmac(), zgets(), prhlst(), asctoq(); int qcmov(), qtoasc(), qcneg(), qcadd(), qcsub(), qcmul(), qcdiv(); int qcabs(), qatn2(), shdn1(), shup1(), qmovz(); int qchyp1f1(), qcerf(), qcerfw(), qcpolylog(); int tolongdouble(); double fabs(); #endif/* not ANSIPROT */
/* the symbol table of key words */ struct funent keytbl[] = {
{"\0", ILLEG, 0},
}; #endif/* SALONE */
/* Number of decimals to display */ #if NQ > 12 #define DEFDIS 70 #else #define DEFDIS 41 #endif staticint ndigits = DEFDIS;
/* Menu stack */ struct funent *menstk[5]; int menptr = 0;
/* Take file stack */
FILE *takstk[10]; int takptr = -1;
/* size of the expression scan list: */ #define NSCAN 20
/* previous token, saved for syntax checking: */ struct symbol *lastok = 0;
/* Cope with strong type checking rules. */ staticunion
{ struct varent *pvar; struct funent *pfun; struct strent *pstr; struct symbol *psym;
} pvfs;
/* variables used by parser: */ staticchar str[128] = {0}; int uposs = 0; /* possible unary operator */
/* numeric value of symbol */ union
{ unsignedshort s[4]; double d;
} nc;
static QELT qnc[2*NQ] = {0}; char lc[40] = { '\n' }; /* ASCII string of token symbol */ staticchar line[LINLEN] = { '\n','\0' }; /* input command line */ staticchar maclin[LINLEN] = { '\n','\0' }; /* macro command */ char *interl = line; /* pointer into line */ externchar *interl; staticint maccnt = 0; /* number of times to execute macro command */ staticint comptr = 0; /* comma stack pointer */ static qcmplx comstk[6]; /* comma argument stack */ staticint narptr = 0; /* pointer to number of args */ staticint 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: */ registerstruct symbol **as;
/* array of attributes of operators parsed: */ int ascopr[NSCAN];
/* current place in ascopr: */ registerint *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
qcmplx acc; /* the accumulator, for arithmetic */ int accflg; /* flags accumulator in use */
qcmplx val; /* value to be combined into accumulator */ registerstruct symbol *psym; /* pointer to symbol just parsed */ struct varent *pvar; /* pointer to an indirect variable symbol */ struct funent *pfun; /* pointer to a function symbol */ int att; /* attributes of symbol just parsed */ int i; /* counter */ int offset; /* parenthesis level */ int lhsflg; /* kluge to detect illegal assignments */ 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.r ); /* Clear the accumulator */
qclear( acc.i );
offset = 0; /* Parenthesis level zero */
comptr = 0; /* Start of comma stack */
narptr = -1; /* Start of function arg counter stack */
/* psym = (struct symbol *)&contbl[0]; */
pvfs.pvar = &contbl[0];
psym = pvfs.psym; for( i=0; i<NCONST; i++ )
{
psym->attrib = CONST; /* clearing the busy bit */
++psym;
} /* psym = (struct symbol *)&temp[0]; */
pvfs.pvar = &temp[0];
psym = pvfs.psym; for( i=0; i<NTEMP; i++ )
{
psym->attrib = VAR | TEMP; /* clearing the busy bit */
++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 */
qmov( qpi, qcpi );
qclear( &qcpi[NQ] );
qclear( qci );
qmov( qone, &qci[NQ] );
/* 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 *apointertotherestoftheinputline. *Asecondargumentisalsopassed:theaddress *ofthelasttokenparsed.
*/ if( att & COMMAN )
{ /* pfun = (struct funent *)psym; */
pvfs.psym = psym;
pfun = pvfs.pfun;
( *(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;
}
/* deal with operators */ if( att & OPR )
{
att &= 0xf; /* expression cannot end with an operator other than *(,),BOL,orafunction
*/ 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( (unsignedshort )lastok->attrib
== (unsignedshort)(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 *thingontheline
*/ if( (accflg == 0) && (as >= ascsym) && (((*as)->attrib & FUNC) == 0 ))
{
pvar = (struct varent *)*as;
qcmov( (qcmplx *) pvar->value, &acc );
--as;
accflg = 1;
}
/* handle beginning of line type cases, where the symbol *listascsym[]maybeempty.
*/ switch( *ao )
{ case BOL:
qtoasc( acc.r, str, ndigits );
printf( "%s\n", str ); /* This is the answer */ if( savfil )
fprintf( savfil, "%s\n", str );
qtoasc( acc.i, str, ndigits ); if( acc.i[0] == 0 )
str[0] = '+';
printf( "%si\n", str ); /* imaginary part */ if( savfil )
fprintf( savfil, "%si\n", str ); goto getcmd; /* all finished */ case UMINUS:
qcneg( &acc ); goto nochg; /* caseCOMP: acc=~acc; gotonochg;
*/ default: ;
} /* Now it is illegal for symbol list to be empty, *becausewearegoingtoneedasymbolbelow.
*/ 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.r );
qclear( val.i );
} else
qcmov( (qcmplx *) 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)
{ case0:
( *(pfun->fun) )(&acc, &acc); break; case1:
( *(pfun->fun) )(&acc,&comstk[comptr-1],&acc); break; case2:
( *(pfun->fun) )(&acc, &comstk[comptr-2],
&comstk[comptr-1],&acc); break; case3:
( *(pfun->fun) )(&acc, &comstk[comptr-3],
&comstk[comptr-2], &comstk[comptr-1],&acc); break; case4:
( *(pfun->fun) )(&acc, &comstk[comptr-4],
&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;
qcmov( &acc, (qcmplx *) pvar->value ); break; case PLUS:
qcadd( &acc, &val, &acc ); break; case MINUS:
qcsub( &acc, &val, &acc ); break; case MULT:
qcmul( &acc, &val, &acc ); break; case DIV: if( (acc.r[1] == 0) && (acc.i[1] == 0) )
{ /* divzer: */
errcod = 10; goto synerr;
}
qcdiv( &acc, &val, &acc ); break; /* caseMOD: if(acc==0) gotodivzer; acc=val%acc;break; caseLOR: acc|=val;break; caseLXOR: acc^=val;break; caseLAND: acc&=val;break;
*/ case EOE: if( narptr < 0 )
{
errcod = 18; goto synerr;
}
narstk[narptr] += 1;
qcmov( &acc, &comstk[comptr++] ); /* printf( "\ncomptr: %d narptr: %d %d\n", comptr, narptr, acc );*/
qcmov( &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;
} /* 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;
qcmov( &acc, (qcmplx *) 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 */
#if USE_READLINE if (takptr < 0)
{ if (line_read)
{
free (line_read);
line_read = (char *)NULL;
} /* Get a line from the user. */
line_read = readline (""); /* If the line has any text in it, save it on the history. */ if (line_read && *line_read)
add_history (line_read); /* Copy to local buffer. */
strcpy(line,line_read);
} else #endif
zgets( line, TRUE ); /* keyboard input for other systems: */
mstart:
uposs = 1; /* unary operators possible at start of line */
}
finstr:
*(--plc) = '\0';
pstr->attrib |= BUSY; /* psym = (struct symbol *)pstr; */
pvfs.pstr = pstr;
psym = pvfs.psym; 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 */
pvfs.pfun = menstk[menptr];
psym = pvfs.psym;
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' );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.