# ifndef EXIT # define EXIT exit # endif int nerrors = 0; /* number of errors */ NODE *lastfree; /* pointer to last free node; (for allocator) */ # ifndef MYWHERE where(c) { /* print location of error. c is either 'u', 'c', or 'w' */ fprintf( stderr, "%s, line %d: ", ftitle, lineno ); } # endif /* VARARGS1 */ 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 */ ++nerrors; where('u'); fprintf( stderr, s, a ); fprintf( stderr, "\n" ); if( nerrors > 30 ) cerror( "too many errors"); fflush(stderr); } /* VARARGS1 */ lerror( s, a ) char *s, *a; { /* nonfatal error message ** the routine where is different for pass 1 and pass 2; ** it tells where the error took place */ ++nerrors; where('u'); fprintf( stderr, s, a ); fprintf( stderr, "\n" ); if( nerrors > 30 ) cerror( "too many errors"); fflush(stderr); } /* VARARGS1 */ cerror( s, a, b, c ) char *s; { /* compiler error: die */ where('c'); if( nerrors && nerrors <= 30 ) { /* give the compiler the benefit of the doubt */ fprintf( stderr, "cannot recover from earlier errors: goodbye!\n" ); } else { fprintf( stderr, "compiler error: " ); fprintf( stderr, s, a, b, c ); fprintf( stderr, "\n" ); fflush( stdout ); } EXIT(1); } /* VARARGS1 */ werror( s, a, b ) char *s; { /* warning */ where('w'); fprintf( stderr, "warning: " ); fprintf( stderr, s, a, b ); fprintf( stderr, "\n" ); } tinit() { /* initialize expression tree search */ register NODE *p; for( p=node; p<= &node[TREESZ-1]; ++p ) p->in.op = FREE; lastfree = node; } # define TNEXT(p) (p== &node[TREESZ-1]?node:p+1) NODE * talloc() { register NODE *p, *q; q = lastfree; for( p = TNEXT(q); p!=q; p= TNEXT(p)) if( p->in.op ==FREE ) return(lastfree=p); cerror( "out of tree space; simplify expression"); /* NOTREACHED */ } tcheck() { /* ensure that all nodes have been freed */ register NODE *p; if( !nerrors ) for( p=node; p<= &node[TREESZ-1]; ++p ) { if( p->in.op != FREE ) { cerror( "wasted space: %d", p-node ); } } else tinit(); freestr(); } tfree(p) register NODE *p; { /* allow tree fragments to be freed, also */ if( !p ) return; switch( optype( p->tn.op ) ) { case BITYPE: tfree( p->in.right ); case UTYPE: tfree( p->in.left ); } p->in.op = FREE; } int dope[ DSIZE ]; char *opst[DSIZE]; NODE node[TREESZ]; char ftitle[100] = "\"\""; /* title of the file */ extern int lineno; /* line number of the input file */ struct dopest { int dopeop; char opst[8]; int dopeval; } indope[] = { NAME, "NAME", LTYPE, STRING, "STRING", LTYPE, REG, "REG", LTYPE, TEMP, "TEMP", LTYPE, VAUTO, "AUTO", LTYPE, VPARAM, "PARAM", LTYPE, ICON, "ICON", LTYPE, FCON, "FCON", LTYPE, CCODES, "CCODES", LTYPE, UNARY MINUS, "U-", UTYPE, UNARY MUL, "STAR", UTYPE, UNARY AND, "U&", UTYPE, UNARY CALL, "UCALL", UTYPE|CALLFLG, UNARY FORTCALL, "UFCALL", UTYPE|CALLFLG, NOT, "!", UTYPE|LOGFLG, COMPL, "~", UTYPE, INIT, "INIT", UTYPE, CONV, "CONV", UTYPE, 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, QUEST, "?", BITYPE, COLON, ":", BITYPE, ANDAND, "&&", BITYPE|LOGFLG, OROR, "||", BITYPE|LOGFLG, CM, ",", BITYPE, COMOP, ",OP", BITYPE, FREE, "FREE!?!", LTYPE, ASSIGN, "=", BITYPE|ASGFLG, DIV, "/", BITYPE|FLOFLG|MULFLG|DIVFLG, ASG DIV, "/=", BITYPE|FLOFLG|MULFLG|DIVFLG|ASGFLG|ASGOPFLG, MOD, "%", BITYPE|DIVFLG, ASG MOD, "%=", BITYPE|DIVFLG|ASGFLG|ASGOPFLG, LS, "<<", BITYPE|SHFFLG, ASG LS, "<<=", BITYPE|SHFFLG|ASGFLG|ASGOPFLG, RS, ">>", BITYPE|SHFFLG, 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, STREF, "->", BITYPE, CALL, "CALL", BITYPE|CALLFLG, FORTCALL, "FCALL", BITYPE|CALLFLG, EQ, "==", BITYPE|LOGFLG, NE, "!=", BITYPE|LOGFLG, LE, "<=", BITYPE|LOGFLG, LT, "<", BITYPE|LOGFLG, GE, ">", BITYPE|LOGFLG, GT, ">", BITYPE|LOGFLG, UGT, "UGT", BITYPE|LOGFLG, UGE, "UGE", BITYPE|LOGFLG, ULT, "ULT", BITYPE|LOGFLG, ULE, "ULE", BITYPE|LOGFLG, ARS, "A>>", BITYPE, TYPE, "TYPE", LTYPE, LB, "[", BITYPE, CBRANCH, "CBRANCH", BITYPE, GENLAB, "GENLAB", UTYPE, GENUBR, "GENUBR", UTYPE, GENBR, "GENBR", UTYPE, CMP, "CMP", BITYPE, FLD, "FLD", UTYPE, PMUL, "P*", BITYPE, PDIV, "P/", BITYPE, RETURN, "RETURN", BITYPE|ASGFLG, CAST, "CAST", BITYPE|ASGFLG, GOTO, "GOTO", UTYPE, STASG, "STASG", BITYPE, STARG, "STARG", UTYPE, STCALL, "STCALL", BITYPE|CALLFLG, UNARY STCALL, "USTCALL", UTYPE|CALLFLG, RNODE, "RNODE", LTYPE, SNODE, "SNODE", LTYPE, QNODE, "QNODE", LTYPE, MANY, "MANY", BITYPE, FUNARG, "ARG", UTYPE, UOP0, "UOP0", UTYPE|SPFLG, UOP1, "UOP1", UTYPE|SPFLG, UOP2, "UOP2", UTYPE|SPFLG, UOP3, "UOP3", UTYPE|SPFLG, UOP4, "UOP4", UTYPE|SPFLG, UOP5, "UOP5", UTYPE|SPFLG, UOP6, "UOP6", UTYPE|SPFLG, UOP7, "UOP7", UTYPE|SPFLG, UOP8, "UOP8", UTYPE|SPFLG, UOP9, "UOP9", UTYPE|SPFLG, -1, 0 }; mkdope() { register struct dopest *q; for( q = indope; q->dopeop >= 0; ++q ) { dope[q->dopeop] = q->dopeval; opst[q->dopeop] = q->opst; } } #define NTSTRBUF 40 #define TSTRSZ 2048 char itstrbuf[TSTRSZ]; char *tstrbuf[NTSTRBUF] = { itstrbuf }; char **curtstr = tstrbuf; int tstrused; char * tstr( cp ) /* place copy of string into temp storage */ register char *cp; /* strings longer than TSTRSZ will break tstr */ { register int i = strlen( cp ); register char *dp; extern char * malloc(); extern char * strcpy(); if ( tstrused + i >= TSTRSZ ) { if ( ++curtstr >= &tstrbuf[NTSTRBUF] ) cerror( "out of temporary string space" ); tstrused = 0; if ( *curtstr == 0 ) { if ( ( dp = (char *) malloc( TSTRSZ ) ) == 0 ) cerror( "out of memory [tstr()]" ); *curtstr = dp; } } strcpy( dp = *curtstr + tstrused, cp ); tstrused += i + 1; return ( dp ); }