#ifndef NORCSID static char rcsid2[] = "$Header$"; #endif #include "nopt.h" extern struct dfa OO_checknext[]; /* Initialized in dfa.c */ extern struct dfa *OO_base[]; /* Initialized in dfa.c */ extern struct dodefault OO_default[]; /* Initialized in dfa.c */ extern int OO_maxpattern; /* Initialized in dfa.c */ extern int OO_maxreplacement; /* Initialized in dfa.c */ extern int (*OO_ftrans[])(); /* Initialized in trans.c */ extern char em_mnem[][4]; extern char em_pseu[][4]; int OO_state = 0; p_instr OO_buffer; p_instr OO_patternqueue; p_instr OO_nxtpatt; p_instr OO_endbackup; p_instr OO_nxtrepl; static p_instr OO_replqueue; static char *filename; static char *strqueue; static char *nextstr; static char *laststr; arith OO_WSIZE; /* wordlength */ arith OO_DWSIZE; /* 2*wordlength */ arith OO_PSIZE; /* pointer length */ #ifdef STATS int OO_wrstats = 1; /* pattern statistics output */ #endif #ifdef DEBUG #define printstate(s) dumpstate(s) #else #define printstate(s) #endif DEBUG /**** WHICH IS FASTER? **** #define BTSCPY(pp,qq,i,p,q,n) btscpy(p,q,(n)*sizeof(struct e_instr)) **************************/ #define BTSCPY(pp,qq,i,p,q,n) for(pp=(p),qq=(q),i=(n);i--;*pp++ = *qq++) O_init(wsize,psize) arith wsize, psize; { allocmem(); C_init(wsize,psize); OO_WSIZE = wsize; OO_DWSIZE = 2*wsize; OO_PSIZE = psize; } O_open(fname) char *fname; { filename = fname; return(C_open(fname)); } O_magic() { C_magic(); } O_close() { C_close(); } OO_dfa(last) register int last; { register struct dfa *b; register struct dodefault *d; register int (*f)(); for(;;) { printstate("OO_dfa"); if((b=OO_base[OO_state]) && ((b += last)->check==OO_state)) { if(f=OO_ftrans[OO_state = b->next]) (*f)(); } else if (OO_state) { /* consult default entry */ d = &OO_default[OO_state]; if(!OO_endbackup) OO_endbackup = OO_nxtpatt; OO_nxtpatt--; OO_patternqueue += d->numout; if(f=OO_ftrans[OO_state = d->next]) (*f)(); } else OO_flush(); if (!OO_endbackup) return; last = (OO_nxtpatt++)->em_opcode; if (OO_nxtpatt >= OO_endbackup) OO_endbackup = 0; } } PRIVATE fatal(s,a) char *s; int a; { fprint(STDERR, "%s: ", filename ? filename : "standard input"); fprint(STDERR,s,a); fprint(STDERR,"\n"); sys_stop(S_EXIT); } PRIVATE allocmem() { /* Allocate memory for queues on heap */ OO_buffer = (p_instr) Malloc((unsigned)(MAXBUFFER*sizeof(struct e_instr))); OO_patternqueue = OO_nxtpatt = OO_buffer; OO_replqueue = (p_instr) Malloc((unsigned)OO_maxreplacement*sizeof(struct e_instr)); OO_nxtrepl = OO_replqueue; nextstr = strqueue = (char *)Malloc(MAXSTRING*sizeof(char)); laststr = strqueue + MAXSTRING - 1; } char * OO_freestr(str) char *str; { register char *s = str; register char *res; while (*s++); again: if ((s-str) > (laststr-nextstr)) { unsigned newsize = (laststr - strqueue + 1)*2; res = Realloc(strqueue,newsize); laststr = res + newsize - 1; nextstr = res + (nextstr - strqueue); strqueue = res; #ifdef DEBUG fprintf(stderr,"Warning: Reallocated string area."); fprintf(stderr,"New size is %d bytes\n", newsize); #endif goto again; } res=nextstr; for(s=str;*nextstr++ = *s++;); return(res); } OO_flush() { /* /* Output all instructions waiting in the output queue and free their /* storage including the saved strings. */ register p_instr p,q; register int i,n; printstate("Flush"); for(p=OO_buffer;pem_opcode!=OTHER) C_out(p); if(OO_endbackup) { n = OO_endbackup-OO_nxtpatt; BTSCPY(p,q,i,OO_buffer,OO_nxtpatt,n); OO_endbackup = OO_buffer + n; } else nextstr = strqueue; OO_patternqueue = OO_nxtpatt = OO_buffer; } p_instr OO_halfflush() { /* /* Called when buffer full, flush half the buffer and move the /* the pattern pointers to the new positions. Return a pointer /* to the new nxtpatt position and increment it. /* Note that OO_endbackup is always NIL (i.e. there are no /* instructions on the backup queue) when this is invoked. */ register int i,n; register p_instr p,q; printstate("Half flush"); n = MAXBUFFER / 2; for(p=OO_buffer,i=n;i--;) C_out(p++); /* now copy the rest of buffer and pattern back */ BTSCPY(p,q,i,OO_buffer,OO_buffer+n,(OO_nxtpatt-OO_buffer)-n); OO_patternqueue -= n; OO_nxtpatt -= n; printstate("after Half flush"); return (OO_nxtpatt++); } OO_mkext(p,opcode,arg,off) register p_instr p; int opcode; p_instr arg; arith off; { switch(arg->em_argtype) { case cst_ptyp: EM_mkcst(p,opcode,off); break; case sof_ptyp: EM_mksof(p,opcode,arg->em_dnam,off); break; case nof_ptyp: EM_mknof(p,opcode,arg->em_dlb,off); break; default: fatal("Unexpected type %d in outext",arg->em_argtype); } } OO_mkrepl(lrepl,diff,numbkup) int lrepl,diff,numbkup; { /* copy the replacement queue into the buffer queue */ /* then move the pattern queue back n places */ register p_instr p,q; register int i; printstate("Before backup"); if(OO_endbackup) { /* move the region between OO_nxtpatt and OO_endbackup */ if (diff > 0) { /* move left by diff */ BTSCPY(p,q,i,OO_nxtpatt-diff,OO_nxtpatt,OO_endbackup-OO_nxtpatt); OO_nxtpatt -= diff; OO_endbackup -= diff; } else if (diff < 0) { /* move right by diff */ /* careful of overflowing buffer!! */ if ((OO_nxtpatt-diff)> (OO_buffer+MAXBUFFER) ) OO_halfflush(); /* cannot use btscpy as strings may overlap */ p = (q=OO_endbackup-1) - diff; while(q>=OO_nxtpatt) *p-- = *q--; OO_nxtpatt -= diff; OO_endbackup -= diff; } } /* copy the replacement */ if (lrepl) { BTSCPY(p,q,i,OO_patternqueue,OO_replqueue,lrepl); OO_nxtrepl = OO_replqueue; OO_patternqueue += lrepl; } /* now move the position of interest back nunbkup instructions */ if ((OO_patternqueue-OO_buffer) < numbkup) numbkup = (OO_patternqueue-OO_buffer); OO_nxtpatt = OO_patternqueue -= numbkup; if(!OO_endbackup && numbkup) OO_endbackup = OO_patternqueue+numbkup; OO_state = 0; printstate("After backup"); } #ifdef DEBUG dumpstate(mess) char *mess; { p_instr p; fprintf(stderr,"%s - state(%d): ",mess,OO_state); p = OO_buffer; while(pem_type) { case EM_MNEM: fprintf(stderr,"%s ",em_mnem[p->em_opcode-sp_fmnem]); break; case EM_PSEU: fprintf(stderr,"%s ",em_pseu[p->em_opcode-sp_fpseu]); break; case EM_STARTMES: case EM_MESARG: case EM_ENDMES: fprintf(stderr,"MES "); break; case EM_DEFILB: fprintf(stderr,"%ld ", (long)p->em_ilb); return; case EM_DEFDLB: fprintf(stderr,"%ld ", (long)p->em_dlb); return; case EM_DEFDNAM: fprintf(stderr,"%d ", p->em_dnam); return; case EM_ERROR: case EM_FATAL: case EM_EOF: return; } switch(p->em_argtype) { case 0: break; case cst_ptyp: fprintf(stderr,"%d ",p->em_cst); break; case nof_ptyp: fprintf(stderr,".%d+%d ",p->em_dlb,p->em_off); break; case sof_ptyp: fprintf(stderr,"%s+%d ",p->em_dnam,p->em_off); break; case ilb_ptyp: fprintf(stderr,"*%d ",p->em_ilb); break; case pro_ptyp: fprintf(stderr,"$%s ",p->em_pnam); break; case str_ptyp: case ico_ptyp: case uco_ptyp: fprintf(stderr,"\"%s\"",p->em_string); break; default: fatal(" prtinst - Unregognized arg %d ",p->em_argtype); } } #endif