Pristine Ack-5.5
[Ack-5.5.git] / modules / src / em_opt / nopt.c
1 #ifndef NORCSID
2 static char rcsid2[] = "$Id: nopt.c,v 2.16 1994/06/24 11:14:16 ceriel Exp $";
3 #endif
4
5 #include "nopt.h"
6
7 extern struct dfa OO_checknext[];       /* Initialized in dfa.c */
8 extern struct dfa *OO_base[];           /* Initialized in dfa.c */
9 extern struct dodefault OO_default[];   /* Initialized in dfa.c */
10 extern int OO_maxpattern;               /* Initialized in dfa.c */
11 extern int OO_maxreplacement;           /* Initialized in dfa.c */
12 extern int (*OO_ftrans[])();            /* Initialized in trans.c */
13
14 extern char     em_mnem[][4];
15 extern char     em_pseu[][4];
16
17 int OO_state = 0;
18
19 p_instr OO_buffer;
20 p_instr OO_patternqueue;
21 p_instr OO_nxtpatt;
22 p_instr OO_endbackup;
23 p_instr OO_nxtrepl;
24 static p_instr  OO_replqueue;
25
26 static char     *filename;
27 static char     *strqueue;
28 static char     *nextstr;
29 static char     *laststr;
30
31 arith           OO_WSIZE;       /* wordlength */
32 arith           OO_DWSIZE;      /* 2*wordlength */
33 arith           OO_PSIZE;       /* pointer length */
34
35 #ifdef STATS
36 int             OO_wrstats = 1; /* pattern statistics output */
37 #endif
38 #ifdef DEBUG
39 #define printstate(s) dumpstate(s)
40 #else
41 #define printstate(s)
42 #endif /* DEBUG */
43
44 /**** WHICH IS FASTER? ****
45 #define BTSCPY(pp,qq,i,p,q,n) btscpy(p,q,(n)*sizeof(struct e_instr))
46  **************************/
47 #define BTSCPY(pp,qq,i,p,q,n) for(pp=(p),qq=(q),i=(n);i--;*pp++ = *qq++)
48
49 PRIVATE void allocmem();
50
51 void
52 O_init(wsize,psize)
53         arith wsize, psize;
54 {
55         allocmem();
56         C_init(wsize,psize);
57         OO_WSIZE = wsize;
58         OO_DWSIZE = 2*wsize;
59         OO_PSIZE = psize;
60 }
61
62 int
63 O_open(fname)
64         char *fname;
65 {
66         filename = fname;
67         return(C_open(fname));
68 }
69
70 void
71 O_magic()
72 {
73         C_magic();
74 }
75
76 void
77 O_close()
78 {
79         C_close();
80 }
81
82 void
83 OO_dfa(last)
84         register int last;
85 {
86         register struct dfa *b;
87         register struct dodefault *d;
88         register int (*f)();
89         for(;;) {
90                 printstate("OO_dfa");
91                 if((b=OO_base[OO_state]) && ((b += last)->check==OO_state)) {
92                         if(f=OO_ftrans[OO_state = b->next]) (*f)();
93                 }
94                 else if (OO_state) {
95                         /* consult default entry */
96                         d = &OO_default[OO_state];
97                         if(!OO_endbackup) OO_endbackup = OO_nxtpatt;
98                         OO_nxtpatt--;
99                         OO_patternqueue += d->numout;
100                         if(f=OO_ftrans[OO_state = d->next]) (*f)();
101                 }
102                 else OO_flush();
103                 if (!OO_endbackup) return;
104                 last = (OO_nxtpatt++)->em_opcode;
105                 if (OO_nxtpatt >= OO_endbackup)
106                         OO_endbackup = 0;
107         }
108 }
109
110 PRIVATE void
111 fatal(s,a)
112         char *s;
113         int a;
114 {
115         fprint(STDERR, "%s: ", filename ? filename : "standard input");
116         fprint(STDERR,s,a);
117         fprint(STDERR,"\n");
118         sys_stop(S_EXIT);
119 }
120
121 PRIVATE void
122 allocmem()
123 {
124         /* Allocate memory for queues on heap */
125         OO_buffer = (p_instr)
126                 Malloc((unsigned)(MAXBUFFER*sizeof(struct e_instr)));
127         OO_patternqueue = OO_nxtpatt = OO_buffer;
128         OO_replqueue = (p_instr)
129                 Malloc((unsigned)OO_maxreplacement*sizeof(struct e_instr));
130         OO_nxtrepl = OO_replqueue;
131         nextstr = strqueue =
132                 (char *)Malloc(MAXSTRING*sizeof(char));
133         laststr = strqueue + MAXSTRING - 1;
134 }
135
136 char *
137 OO_freestr(str)
138         char *str;
139 {
140         register char *s = str;
141         register char *res;
142         while (*s++);
143  again:
144         if ((s-str) > (laststr-nextstr)) {
145                 unsigned newsize = (laststr - strqueue + 1)*2;
146                 res = Realloc(strqueue,newsize);
147                 laststr = res + newsize - 1;
148                 nextstr = res + (nextstr - strqueue);
149                 strqueue = res;
150 #ifdef DEBUG
151                 fprintf(stderr,"Warning: Reallocated string area.");
152                 fprintf(stderr,"New size is %d bytes\n", newsize);
153 #endif
154                 goto again;
155         }
156         res=nextstr;
157         for(s=str;*nextstr++ = *s++;);
158         return(res);
159 }
160
161 void
162 OO_flush()
163 {
164         /*
165         /* Output all instructions waiting in the output queue and free their
166         /* storage including the saved strings.
167         */
168         register p_instr p,q;
169         register int i,n;
170         printstate("Flush");
171         for(p=OO_buffer;p<OO_patternqueue;p++)
172                 C_out(p);
173         if(p->em_opcode!=OTHER)
174                 C_out(p);
175         if(OO_endbackup) {
176                 n = OO_endbackup-OO_nxtpatt;
177                 BTSCPY(p,q,i,OO_buffer,OO_nxtpatt,n);
178                 OO_endbackup = OO_buffer + n;
179         }
180         else nextstr = strqueue;
181         OO_patternqueue = OO_nxtpatt = OO_buffer;
182 }
183
184 p_instr
185 OO_halfflush()
186 {
187         /*
188         /* Called when buffer full, flush half the buffer and move the
189         /* the pattern pointers to the new positions. Return a pointer
190         /* to the new nxtpatt position and increment it.
191         /* Note that OO_endbackup is always NIL (i.e. there are no
192         /* instructions on the backup queue) when this is invoked.
193         */
194         register int i,n;
195         register p_instr p,q;
196         printstate("Half flush");
197         n = MAXBUFFER / 2;
198         for(p=OO_buffer,i=n;i--;)
199                 C_out(p++);
200         /* now copy the rest of buffer and pattern back */
201         BTSCPY(p,q,i,OO_buffer,OO_buffer+n,(OO_nxtpatt-OO_buffer)-n);
202         OO_patternqueue -= n;
203         OO_nxtpatt -= n;
204         printstate("after Half flush");
205         return (OO_nxtpatt++);
206 }
207
208 void
209 OO_mkext(p,opcode,arg,off)
210         register p_instr p;
211         int opcode;
212         p_instr arg;
213         arith off;
214 {
215         switch(arg->em_argtype) {
216         case cst_ptyp:
217                 EM_mkcst(p,opcode,off);
218                 break;
219         case sof_ptyp:
220                 EM_mksof(p,opcode,arg->em_dnam,off);
221                 break;
222         case nof_ptyp:
223                 EM_mknof(p,opcode,arg->em_dlb,off);
224                 break;
225         default:
226                 fatal("Unexpected type %d in outext",arg->em_argtype);
227         }
228 }
229
230 void
231 OO_mkrepl(lrepl,diff,numbkup)
232         int lrepl,diff,numbkup;
233 {
234         /* copy the replacement queue into the buffer queue */
235         /* then move the pattern queue back n places */
236         register p_instr p,q;
237         register int i;
238         printstate("Before backup");
239         if(OO_endbackup) {
240                 /* move the region between OO_nxtpatt and OO_endbackup */
241                 if (diff > 0) {
242                         /* move left by diff */
243                         BTSCPY(p,q,i,OO_nxtpatt-diff,OO_nxtpatt,OO_endbackup-OO_nxtpatt);
244                         OO_nxtpatt -= diff;
245                         OO_endbackup -= diff;
246                 }
247                 else if (diff < 0) {
248                         /* move right by diff */
249                         /* careful of overflowing buffer!! */
250                         if ((OO_nxtpatt-diff)> (OO_buffer+MAXBUFFER) )
251                                 OO_halfflush();
252                         /* cannot use btscpy as strings may overlap */
253                         p = (q=OO_endbackup-1) - diff;
254                         while(q>=OO_nxtpatt)
255                                 *p-- = *q--;
256                         OO_nxtpatt -= diff;
257                         OO_endbackup -= diff;
258                 }
259         }
260         /* copy the replacement */
261         if (lrepl) {
262                 BTSCPY(p,q,i,OO_patternqueue,OO_replqueue,lrepl);
263                 OO_nxtrepl = OO_replqueue;
264                 OO_patternqueue += lrepl;
265         }
266         /* now move the position of interest back nunbkup instructions */
267         if ((OO_patternqueue-OO_buffer) < numbkup) 
268                 numbkup = (OO_patternqueue-OO_buffer);
269         OO_nxtpatt = OO_patternqueue -= numbkup;
270         if(!OO_endbackup && numbkup)
271                 OO_endbackup = OO_patternqueue+numbkup;
272         OO_state = 0;
273         printstate("After backup");
274 }
275
276 #ifdef DEBUG
277 void
278 dumpstate(mess)
279         char *mess;
280 {
281         p_instr p;
282         fprintf(stderr,"%s - state(%d): ",mess,OO_state);
283         p = OO_buffer;
284         while(p<OO_patternqueue)
285                 prtinst(p++);
286         fprintf(stderr," |==| ");
287         while(p<OO_nxtpatt)
288                 prtinst(p++);
289         fprintf(stderr," |==| ");
290         if(OO_endbackup) {
291                 while(p<OO_endbackup)
292                         prtinst(p++);
293         }
294         fprintf(stderr,"\n");
295 }
296
297 void
298 prtinst(p)
299         p_instr p;
300 {
301         switch(p->em_type) {
302         case EM_MNEM:
303                 fprintf(stderr,"%s ",em_mnem[p->em_opcode-sp_fmnem]);
304                 break;
305         case EM_PSEU:
306                 fprintf(stderr,"%s ",em_pseu[p->em_opcode-sp_fpseu]);
307                 break;
308         case EM_STARTMES:
309         case EM_MESARG:
310         case EM_ENDMES:
311                 fprintf(stderr,"MES ");
312                 break;
313         case EM_DEFILB:
314                 fprintf(stderr,"%ld ", (long)p->em_ilb);
315                 return;
316         case EM_DEFDLB:
317                 fprintf(stderr,"%ld ", (long)p->em_dlb);
318                 return;
319         case EM_DEFDNAM:
320                 fprintf(stderr,"%d ", p->em_dnam);
321                 return;
322         case EM_ERROR:
323         case EM_FATAL:
324         case EM_EOF:
325                 return;
326         }
327         switch(p->em_argtype) {
328         case 0:
329                 break;
330         case cst_ptyp:
331                 fprintf(stderr,"%d ",p->em_cst);
332                 break;
333         case nof_ptyp:
334                 fprintf(stderr,".%d+%d ",p->em_dlb,p->em_off);
335                 break;
336         case sof_ptyp:
337                 fprintf(stderr,"%s+%d ",p->em_dnam,p->em_off);
338                 break;
339         case ilb_ptyp:
340                 fprintf(stderr,"*%d ",p->em_ilb);
341                 break;
342         case pro_ptyp:
343                 fprintf(stderr,"$%s ",p->em_pnam);
344                 break;
345         case str_ptyp:
346         case ico_ptyp:
347         case uco_ptyp:
348                 fprintf(stderr,"\"%s\"",p->em_string);
349                 break;
350         default:
351                 fatal(" prtinst - Unregognized arg %d ",p->em_argtype);
352         }
353 }
354 #endif