#ifndef NORCSID static char rcsidp5[] = "$Header$"; #endif #include "parser.h" #include "Lpars.h" FILE *ofile; outputnopt() { openofile("dfa.c"); outdfa(); installofile(); openofile("trans.c"); outdotrans(); installofile(); openofile("incalls.r"); outputincalls(); installofile(); } static char ofilename[80]; static char ofiletemp[80]; PRIVATE openofile(filename) char *filename; { char *strcpy(), *strcat(); strcpy(ofilename,filename); strcpy(ofiletemp,filename); strcat(ofiletemp,".new"); if((ofile=fopen(ofiletemp,"w"))==NULL) { fprintf(stderr,"Fatal Error: cannot open output file %s\n",ofiletemp); sys_stop(S_EXIT); } } PRIVATE installofile() { /* * if contents of newly generated ofiletemp is different * from that of ofilename then copy over old file else * delete newly generated file */ register FILE *f1, *f2; register int c1, c2; fclose(ofile); if((f1 = fopen(ofiletemp,"r")) == NULL) { fprintf(stderr,"Fatal Error: cannont reopen file %s\n",ofiletemp); sys_stop(S_EXIT); } if((f2 = fopen(ofilename,"r")) == NULL) { fclose(f1); RENAME(ofiletemp,ofilename); return; } do { c1 = getc(f1); c2 = getc(f2); } while (c1 == c2 && c1 != EOF); fclose(f1); fclose(f2); if (c1 != c2) { RENAME(ofiletemp,ofilename); } else UNLINK(ofiletemp); } PRIVATE UNLINK(x) char *x; { /* Must remove the file "x" */ unlink(x); /* systemcall to remove file */ } PRIVATE RENAME(x,y) char *x, *y; { /* Must move the file "x" to the file "y" */ unlink(y); if(link(x,y)!=0) { fprintf(stderr,"Cannot link to %s",y); sys_stop(S_EXIT); } unlink(x); } # define MAXOPCODE 255 # define EMPTY -1 int *next, *check, *base; unsigned currsize; /* current size of next and check arrays */ int maxpos = 0; /* highest used position in these arrayes */ PRIVATE increase_next(size) int size; { /* realloc arrays next and check so they are at least * of size 'size' */ char *Realloc(); unsigned newsize = currsize; register int i; do { newsize *= 2; } while (newsizecurrsize) increase_next(o); if(n[o]!=EMPTY) goto nextpos; } } /* found a place */ base[state]=b; for(i=0;imaxpos) maxpos = o; next[o] = row[i]; check[o] = state; } return; nextpos: ++b; } } PRIVATE outdfa() { register int s,i; register struct state *p; int nout, ncpy, ngto; int row[MAXOPCODE]; int numinrow; int numentries = 0; fprintf(ofile,"#include \"nopt.h\"\n"); fprintf(ofile,"\n"); fprintf(ofile,"int OO_maxreplacement = %d;\n", maxreplacement); fprintf(ofile,"\n"); /* find how many entries in dfa */ for(s=0;s<=higheststate;s++) for(p=states[s];p!=(struct state *)NULL;p=p->next) numentries++; /* start with next and check arrays twice this size */ currsize = 2 * numentries; next = (int *)Malloc(currsize*sizeof(int)); check = (int *)Malloc(currsize*sizeof(int)); base = (int *)Malloc(((unsigned)(higheststate+1))*sizeof(int)); /* fill next array with EMPTY */ for(i=0;inext) { numinrow++; row[p->op->id_opcode] = p->goto_state; } /* look for a place to store row */ if(numinrow) store_row(s,row); else base[s] = EMPTY; } /* give some statistics on size of dfa */ printf("Number of patterns: %d\n", numpatterns); printf("Longest pattern: %d\n", maxpattern); printf("Longest replacement: %d\n", maxreplacement); printf("Dfa contains %d states and %d distinct state/opcode pairs\n", higheststate+1,numentries); printf("Compacted using row displacement into %d entries\n",maxpos); /* output the arrays */ fprintf(ofile,"struct dfa OO_checknext[] = {\n"); for(i=0;i<=maxpos;i++) { fprintf(ofile,"\t/* %4d */\t",i); fprintf(ofile,"{%4d,%4d},\n", check[i], next[i]); } fprintf(ofile,"};\n\n"); fprintf(ofile,"struct dfa *OO_base[] = {\n"); for(s=0;s<=higheststate;s++) { fprintf(ofile,"\t/* %4d: ",s); outmnems(patterns[s]); fprintf(ofile,"*/\t"); if(base[s]==EMPTY) fprintf(ofile,"0,\n"); else fprintf(ofile,"&OO_checknext[%4d],\n", base[s]); } fprintf(ofile,"};\n\n"); fprintf(ofile,"struct dodefault OO_default[] = {\n"); for(s=0;s<=higheststate;s++) { fprintf(ofile,"\t/* %4d: ",s); outmnems(patterns[s]); fprintf(ofile,"*/\t"); findfail(s,&nout,&ncpy,&ngto); fprintf(ofile,"{%4d,%4d},\n", nout,ngto); } fprintf(ofile,"};\n\n"); } PRIVATE outmnems(l) struct mnems l; { int i; for(i=1;i<=l.m_len;i++) fprintf(ofile,"%s ",l.m_elems[i-1]->op_code->id_text); } PRIVATE int sametest(s1,s2,e1,e2) int s1,s2; struct exp_node *e1,*e2; { /* retrun 1 if tests are identical */ if(e1) { if(!e2) return 0; if(e1->node_type!=e2->node_type) return 0; switch(e1->node_type) { case LOGAND: case LOGOR: case BITAND: case BITOR: case XOR: case MINUS: case PLUS: case TIMES: case DIV: case MOD: case EQ: case NE: case LT: case LE: case GT: case GE: case LSHIFT: case RSHIFT: case COMMA: case SAMESIGN: case SFIT: case UFIT: case ROTATE: case SAMEEXT: case SAMENAM: return (sametest(e1->exp_left,e2->exp_left) && sametest(e1->exp_right,e2->exp_right)); case NOT: case COMP: case UPLUS: case UMINUS: return sametest(e1->exp_left,e2->exp_left); case DEFINED: case UNDEFINED: case INT: return (e1->leaf_val == e2->leaf_val); case PATARG: /* depends on pattern !! */ if (e1->leaf_val != e2->leaf_val) return 0; return (patterns[s1].m_elems[e1->leaf_val-1]-> op_code->id_argfmt == patterns[s1].m_elems[e2->leaf_val-1]-> op_code->id_argfmt); case PSIZE: case WSIZE: return 1; } } else return (e2==0); } PRIVATE int samerepl(s1,s2,r1,r2) int s1,s2; struct mnems r1,r2; { /* return 1 if replacements are identical */ register int i; register struct mnem_elem *m1,*m2; if (r1.m_len != r2.m_len) return 0; /* different length */ for(i=0;iop_code!=m2->op_code) return 0; if(!sametest(s1,s2,m1->arg,m2->arg)) return 0; } return 1; } PRIVATE int samecode(s1,s2) int s1,s2; { /* return 1 if replacement code of state s1 and s2 are identical */ register struct action *a1,*a2; if (patterns[s1].m_len != patterns[s2].m_len) return 0; a1 = actions[s1]; a2 = actions[s2]; while(a1) { if(!a2) return 0; /* a2 is shorter */ if(!samerepl(s1,s2,a1->replacement,a2->replacement)) return 0; if(!sametest(s1,s2,a1->test,a2->test)) return 0; a1 = a1->next; a2 = a2->next; } if(a2) return 0; /* a2 is longer */ return 1; } PRIVATE outdotrans() { register int s,t; struct action *a; int seennontested; int *farray; fprintf(ofile,"#include \"nopt.h\"\n\n"); /* keep track of which procedure used for each state */ farray = (int *)Malloc((unsigned)(higheststate+1)*sizeof(int)); for(s=0;s<=higheststate;s++) farray[s] = EMPTY; /* output the functions avoiding duplicates */ for(s=0;s<=higheststate;s++) { if(actions[s]!=(struct action *)NULL) { /* first look for a previous identical function */ for(t=0;tnext) { if(a->test!=(struct exp_node *)NULL) { fprintf(ofile,"\tif("); outexp(a->test,s); fprintf(ofile,") {\n"); outoneaction(s,a); fprintf(ofile,"\t\treturn;\n"); fprintf(ofile,"\t}\n"); } else { if(seennontested) { fprintf(stderr,"parser: more than one untested action on state %d\n",s); nerrors++; } seennontested++; outoneaction(s,a); } } fprintf(ofile,"}\n"); } next_func: continue; } /* output the array itself */ fprintf(ofile,"\n\nint (*OO_ftrans[])()=\n{\n"); for(s=0;s<=higheststate;s++) { if(farray[s]!=EMPTY) fprintf(ofile,"\tdo%dtrans,\n",farray[s]); else fprintf(ofile,"\t0,\n"); } fprintf(ofile,"};\n"); } PRIVATE outoneaction(s,a) int s; struct action *a; { fprintf(ofile,"\t\t/* -> "); outmnems(a->replacement); fprintf(ofile," */\n"); fprintf(ofile,"#ifdef STATS\n"); fprintf(ofile,"\t\tif(OO_wrstats) fprintf(stderr,\"%d\\n\");\n",a->linenum); fprintf(ofile,"#endif\n"); outrepl(s,a->replacement); findworst(patterns[s],a->replacement); } PRIVATE outrepl(state,repl) int state; struct mnems repl; { /* /* Contruct =r1 r2 ... rn and put on output queue. */ int n = repl.m_len; int i; for(i=1;i<=n;i++) { struct mnem_elem *ri = repl.m_elems[i-1]; char *mnem = ri->op_code->id_text; switch(ri->op_code->id_argfmt) { case NOARG: fprintf(ofile,"\t\tEM_mkop(GETNXTREPL(),op_%s);\n",mnem); break; case CST: fprintf(ofile,"\t\tEM_mkcst(GETNXTREPL(),op_%s,",mnem); fprintf(ofile,"(arith)"); outexp(ri->arg,state); fprintf(ofile,");\n"); break; case CSTOPT: if(ri->arg) { fprintf(ofile,"\t\tEM_mkcst(GETNXTREPL(),op_%s,",mnem); fprintf(ofile,"(arith)"); outexp(ri->arg,state); } else { fprintf(ofile,"\t\tEM_mknarg(GETNXTREPL(),op_%s);\n",mnem); } fprintf(ofile,");\n"); break; case LAB: fprintf(ofile,"\t\tEM_mkilb(GETNXTREPL(),op_%s,",mnem); outexp(ri->arg,state); fprintf(ofile,");\n"); break; case DEFILB: fprintf(ofile,"\t\tEM_mkdefilb(GETNXTREPL(),op_%s,",mnem); outexp(ri->arg,state); fprintf(ofile,");\n"); break; case PNAM: fprintf(ofile,"\t\tEM_mkpro(GETNXTREPL(),op_%s,",mnem); outexp(ri->arg,state); fprintf(ofile,");\n"); break; case EXT: fprintf(ofile,"\t\tOO_mkext(GETNXTREPL(),op_%s,",mnem); outexp(ri->arg,state); fprintf(ofile,");\n"); break; } } } PRIVATE outexp(e,state) struct exp_node *e; int state; { switch(e->node_type) { case LOGAND: case LOGOR: case BITAND: case BITOR: case XOR: case MINUS: case PLUS: case TIMES: case DIV: case MOD: case EQ: case NE: case LT: case LE: case GT: case GE: case LSHIFT: case RSHIFT: fprintf(ofile,"("); outexp(e->exp_left,state); outop(e->node_type); outexp(e->exp_right,state); fprintf(ofile,")"); break; case NOT: case COMP: case UPLUS: case UMINUS: fprintf(ofile,"("); outop(e->node_type); outexp(e->exp_left,state); fprintf(ofile,")"); break; case DEFINED: fprintf(ofile,"DEFINED(patt[%d])",e->leaf_val-1); break; case UNDEFINED: fprintf(ofile,"!DEFINED(patt[%d])",e->leaf_val-1); break; case COMMA: outext(e->exp_left); fprintf(ofile,","); fprintf(ofile,"(arith)"); outexp(e->exp_right,state); break; case SAMESIGN: case SFIT: case UFIT: case ROTATE: outop(e->node_type); fprintf(ofile,"(arith)"); outexp(e->exp_left,state); fprintf(ofile,","); fprintf(ofile,"(arith)"); outexp(e->exp_right,state); fprintf(ofile,")"); break; case SAMEEXT: case SAMENAM: outop(e->node_type); outext(e->exp_left); fprintf(ofile,","); outext(e->exp_right); fprintf(ofile,")"); break; case PATARG: switch(patterns[state].m_elems[e->leaf_val-1]->op_code->id_argfmt) { case NOARG: fprintf(stderr,"error: mnem %d has no argument\n",e->leaf_val); nerrors++; break; case CST: case CSTOPT: fprintf(ofile,"CST(patt[%d])",e->leaf_val-1); break; case LAB: fprintf(ofile,"LAB(patt[%d])",e->leaf_val-1); break; case DEFILB: fprintf(ofile,"DEFILB(patt[%d])",e->leaf_val-1); break; case PNAM: fprintf(ofile,"PNAM(patt[%d])",e->leaf_val-1); break; case EXT: fprintf(ofile,"OO_offset(patt+%d)",e->leaf_val-1); break; } break; case PSIZE: fprintf(ofile,"OO_PSIZE"); break; case WSIZE: fprintf(ofile,"OO_WSIZE"); break; case INT: fprintf(ofile,"%d",e->leaf_val); break; } } PRIVATE outext(e) struct exp_node *e; { if(e->node_type!=PATARG) { fprintf(stderr,"Internal error in outext of parser\n"); nerrors++; } fprintf(ofile,"patt+%d",e->leaf_val-1); } PRIVATE outop(op) int op; { switch(op) { case LOGAND: fprintf(ofile,"&&"); break; case LOGOR: fprintf(ofile,"||"); break; case BITAND: fprintf(ofile,"&"); break; case BITOR: fprintf(ofile,"|"); break; case XOR: fprintf(ofile,"^"); break; case MINUS: fprintf(ofile,"-"); break; case PLUS: fprintf(ofile,"+"); break; case TIMES: fprintf(ofile,"*"); break; case DIV: fprintf(ofile,"/"); break; case MOD: fprintf(ofile,"%%"); break; case EQ: fprintf(ofile,"=="); break; case NE: fprintf(ofile,"!="); break; case LT: fprintf(ofile,"<"); break; case LE: fprintf(ofile,"<="); break; case GT: fprintf(ofile,">"); break; case GE: fprintf(ofile,">="); break; case LSHIFT: fprintf(ofile,"<<"); break; case RSHIFT: fprintf(ofile,">>"); break; case NOT: fprintf(ofile,"!"); break; case COMP: fprintf(ofile,"~"); break; case UPLUS: fprintf(ofile,"+"); break; case UMINUS: fprintf(ofile,"-"); break; case SAMESIGN: fprintf(ofile,"OO_signsame("); break; case SFIT: fprintf(ofile,"OO_sfit("); break; case UFIT: fprintf(ofile,"OO_ufit("); break; case ROTATE: fprintf(ofile,"OO_rotate("); break; case SAMEEXT: fprintf(ofile,"OO_extsame("); break; case SAMENAM: fprintf(ofile,"OO_namsame("); break; } }