int nerrors = 0; /* number of errors */
NODE *NIL; /* pointer which always has 0 in it */
NODE *lastfree; /* pointer to last free node; (for allocator) */
uerror( s, a ) char *s; { /* nonfatal error message */
/* the routine where is different for pass 1 and pass 2;
/* it tells where the error took place */
if( nerrors > 30 ) cerror( "too many errors");
cerror( s, a, b, c ) char *s; { /* compiler error: die */
if( nerrors && nerrors <= 30 ){ /* give the compiler the benefit of the doubt */
fprintf( stderr, "cannot recover from earlier errors: goodbye!\n" );
fprintf( stderr, "compiler error: " );
fprintf( stderr, s, a, b, c );
werror( s, a, b ) char *s; { /* warning */
fprintf( stderr, "warning: " );
fprintf( stderr, s, a, b );
tinit(){ /* initialize expression tree search */
for( p=node; p<= &node[TREESZ-1]; ++p ) p->op = FREE;
# define TNEXT(p) (p== &node[TREESZ-1]?node:p+1)
for( p = TNEXT(q); p!=q; p= TNEXT(p))
if( p->op ==FREE ) return(lastfree=p);
cerror( "out of tree space; simplify expression");
tcheck(){ /* ensure that all nodes have been freed */
for( p=node; p<= &node[TREESZ-1]; ++p )
if( p->op != FREE ) cerror( "wasted space: %o", p );
if( p->op != FREE ) walkf( p, tfree1 );
if( p == 0 ) cerror( "freeing blank tree!");
fwalk( t, f, down ) register NODE *t; int (*f)(); {
(*f)( t, down, &down1, &down2 );
switch( optype( t->op ) ){
fwalk( t->left, f, down1 );
walkf( t, f ) register NODE *t; int (*f)(); {
if( opty != LTYPE ) walkf( t->left, f );
if( opty == BITYPE ) walkf( t->right, f );
struct dopest { int dopeop; char opst[8]; int dopeval; } indope[] = {
UNARY MINUS, "U-", UTYPE,
UNARY CALL, "UCALL", UTYPE|CALLFLG,
UNARY FORTCALL, "UFCALL", UTYPE|CALLFLG,
PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG,
ASG PLUS, "+=", BITYPE|ASGFLG|ASGOPFLG|FLOFLG|SIMPFLG|COMMFLG,
MINUS, "-", BITYPE|FLOFLG|SIMPFLG,
ASG MINUS, "-=", BITYPE|FLOFLG|SIMPFLG|ASGFLG|ASGOPFLG,
MUL, "*", BITYPE|FLOFLG|MULFLG,
ASG MUL, "*=", BITYPE|FLOFLG|MULFLG|ASGFLG|ASGOPFLG,
AND, "&", BITYPE|SIMPFLG|COMMFLG,
ASG AND, "&=", BITYPE|SIMPFLG|COMMFLG|ASGFLG|ASGOPFLG,
ANDAND, "&&", BITYPE|LOGFLG,
OROR, "||", BITYPE|LOGFLG,
ASSIGN, "=", BITYPE|ASGFLG,
DIV, "/", BITYPE|FLOFLG|MULFLG|DIVFLG,
ASG DIV, "/=", BITYPE|FLOFLG|MULFLG|DIVFLG|ASGFLG|ASGOPFLG,
ASG MOD, "%=", BITYPE|DIVFLG|ASGFLG|ASGOPFLG,
ASG LS, "<<=", BITYPE|SHFFLG|ASGFLG|ASGOPFLG,
ASG RS, ">>=", BITYPE|SHFFLG|ASGFLG|ASGOPFLG,
OR, "|", BITYPE|COMMFLG|SIMPFLG,
ASG OR, "|=", BITYPE|COMMFLG|SIMPFLG|ASGFLG|ASGOPFLG,
ER, "^", BITYPE|COMMFLG|SIMPFLG,
ASG ER, "^=", BITYPE|COMMFLG|SIMPFLG|ASGFLG|ASGOPFLG,
INCR, "++", BITYPE|ASGFLG,
DECR, "--", BITYPE|ASGFLG,
CALL, "CALL", BITYPE|CALLFLG,
FORTCALL, "FCALL", BITYPE|CALLFLG,
UGT, "UGT", BITYPE|LOGFLG,
UGE, "UGE", BITYPE|LOGFLG,
ULT, "ULT", BITYPE|LOGFLG,
ULE, "ULE", BITYPE|LOGFLG,
CBRANCH, "CBRANCH", BITYPE,
PMCONV, "PMCONV", BITYPE,
PVCONV, "PVCONV", BITYPE,
RETURN, "RETURN", BITYPE|ASGFLG|ASGOPFLG,
CAST, "CAST", BITYPE|ASGFLG|ASGOPFLG,
STASG, "STASG", BITYPE|ASGFLG,
STCALL, "STCALL", BITYPE|CALLFLG,
UNARY STCALL, "USTCALL", UTYPE|CALLFLG,
register struct dopest *q;
for( q = indope; q->dopeop >= 0; ++q ){
dope[q->dopeop] = q->dopeval;
opst[q->dopeop] = q->opst;
tprint( t ) TWORD t; { /* output a nice description of the type of t */
static char * tnames[] = {
if( ISPTR(t) ) printf( "PTR " );
else if( ISFTN(t) ) printf( "FTN " );
else if( ISARY(t) ) printf( "ARY " );
printf( "%s", tnames[t] );