Pristine Ack-5.5
[Ack-5.5.git] / util / opt / getline.c
1 #ifndef NORCSID
2 static char rcsid[] = "$Id: getline.c,v 2.7 1994/06/24 10:40:03 ceriel Exp $";
3 #endif
4
5 #include <stdio.h>
6 #include "param.h"
7 #include "types.h"
8 #include "tes.h"
9 #include "line.h"
10 #include "lookup.h"
11 #include "alloc.h"
12 #include "proinf.h"
13 #include <em_spec.h>
14 #include <em_pseu.h>
15 #include <em_flag.h>
16 #include <em_mes.h>
17 #include "ext.h"
18
19 /*
20  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
21  * See the copyright notice in the ACK home directory, in the file "Copyright".
22  *
23  * Author: Hans van Staveren
24  */
25
26
27 static  short   tabval;         /* temp store for shorts */
28 static  offset  tabval2;        /* temp store for offsets */
29 static  char    string[IDL+1];  /* temp store for names */
30
31 /*
32  * The next constants are close to sp_cend for fast switches
33  */
34 #define INST    256     /* instruction:         number in tabval */
35 #define PSEU    257     /* pseudo:              number in tabval */
36 #define ILBX    258     /* label:               number in tabval */
37 #define DLBX    259     /* symbol:              name in string[] */
38 #define CSTX1   260     /* short constant:      stored in tabval */
39 #define CSTX2   261     /* offset:              value in tabval2 */
40 #define VALX1   262     /* symbol+short:        in string[] and tabval */
41 #define VALX2   263     /* symbol+offset:       in string[] and tabval2 */
42 #define ATEOF   264     /* bumped into end of file */
43
44 #define readbyte getchar
45
46 short readshort() {
47         register int l_byte, h_byte;
48
49         l_byte = readbyte();
50         h_byte = readbyte();
51         if ( h_byte>=128 ) h_byte -= 256 ;
52         return l_byte | (h_byte*256) ;
53 }
54
55 #ifdef LONGOFF
56 offset readoffset() {
57         register long l;
58         register int h_byte;
59
60         l = readbyte();
61         l |= ((unsigned) readbyte())*256 ;
62         l |= readbyte()*256L*256L ;
63         h_byte = readbyte() ;
64         if ( h_byte>=128 ) h_byte -= 256 ;
65         return l | (h_byte*256L*256*256L) ;
66 }
67 #endif
68
69 draininput() {
70
71         /*
72          * called when MES ERR is encountered.
73          * Drain input in case it is a pipe.
74          */
75
76         while (getchar() != EOF)
77                 ;
78 }
79
80 short getint() {
81
82         switch(table2()) {
83         default: error("int expected");
84         case CSTX1:
85                 return(tabval);
86         }
87 }
88
89 sym_p getsym(status) int status; {
90
91         switch(table2()) {
92         default:
93                 error("symbol expected");
94         case DLBX:
95                 return(symlookup(string,status,0));
96         case sp_pnam:
97                 return(symlookup(string,status,SYMPRO));
98         }
99 }
100
101 offset getoff() {
102
103         switch (table2()) {
104         default: error("offset expected");
105         case CSTX1:
106                 return((offset) tabval);
107 #ifdef LONGOFF
108         case CSTX2:
109                 return(tabval2);
110 #endif
111         }
112 }
113
114 make_string(n) int n; {
115
116         sprintf(string,".%u",n);
117 }
118
119 inident() {
120         register n;
121         register char *p = string;
122         register c;
123
124         n = getint();
125         while (n--) {
126                 c = readbyte();
127                 if (p<&string[IDL])
128                         *p++ = c;
129         }
130         *p++ = 0;
131 }
132
133 int table3(n) int n; {
134
135         switch (n) {
136         case sp_ilb1:   tabval = readbyte(); return(ILBX);
137         case sp_ilb2:   tabval = readshort(); return(ILBX);
138         case sp_dlb1:   make_string(readbyte()); return(DLBX);
139         case sp_dlb2:   make_string(readshort()); return(DLBX);
140         case sp_dnam:   inident(); return(DLBX);
141         case sp_pnam:   inident(); return(n);
142         case sp_cst2:   tabval = readshort(); return(CSTX1);
143 #ifdef LONGOFF
144         case sp_cst4:   tabval2 = readoffset(); return(CSTX2);
145 #endif
146         case sp_doff:   if (table2()!=DLBX) error("symbol expected");
147                         switch(table2()) {
148                         default:        error("offset expected");
149                         case CSTX1:             return(VALX1);
150 #ifdef LONGOFF
151                         case CSTX2:             return(VALX2);
152 #endif
153                         }
154         default:        return(n);
155         }
156 }
157
158 int table1() {
159         register n;
160
161         n = readbyte();
162         if (n == EOF)
163                 return(ATEOF);
164         if ((n <= sp_lmnem) && (n >= sp_fmnem)) {
165                 tabval = n;
166                 return(INST);
167         }
168         if ((n <= sp_lpseu) && (n >= sp_fpseu)) {
169                 tabval = n;
170                 return(PSEU);
171         }
172         if ((n < sp_filb0 + sp_nilb0) && (n >= sp_filb0)) {
173                 tabval = n - sp_filb0;
174                 return(ILBX);
175         }
176         return(table3(n));
177 }
178
179 int table2() {
180         register n;
181
182         n = readbyte();
183         if ((n < sp_fcst0 + sp_ncst0) && (n >= sp_fcst0)) {
184                 tabval = n - sp_zcst0;
185                 return(CSTX1);
186         }
187         return(table3(n));
188 }
189
190 getlines() {
191         register line_p lnp;
192         register instr;
193
194     for(;;) {
195         linecount++;
196         switch(table1()) {
197         default:
198                 error("unknown instruction byte");
199                 /* NOTREACHED */
200
201         case ATEOF:
202                 if (prodepth!=0)
203                         error("procedure unterminated at eof");
204                 process();
205                 return;
206         case INST:
207                 tstinpro();
208                 instr = tabval;
209                 break;
210         case DLBX:
211                 lnp = newline(OPSYMBOL);
212                 lnp->l_instr = ps_sym;
213                 lnp->l_a.la_sp= symlookup(string,DEFINING,0);
214                 lnp->l_next = curpro.lastline;
215                 curpro.lastline = lnp;
216                 continue;
217         case ILBX:
218                 tstinpro();
219                 lnp = newline(OPNUMLAB);
220                 lnp->l_instr = op_lab;
221                 lnp->l_a.la_np = numlookup((unsigned) tabval);
222                 if (lnp->l_a.la_np->n_line != (line_p) 0)
223                         error("label %u multiple defined",(unsigned) tabval);
224                 lnp->l_a.la_np->n_line = lnp;
225                 lnp->l_next = curpro.lastline;
226                 curpro.lastline = lnp;
227                 continue;
228         case PSEU:
229                 if(inpseudo(tabval))
230                         return;
231                 continue;
232         }
233
234         /*
235          * Now we have an instruction number in instr
236          * There might be an operand, look for it
237          */
238
239         if ((em_flag[instr-sp_fmnem]&EM_PAR)==PAR_NO) {
240                 lnp = newline(OPNO);
241         } else switch(table2()) {
242         default:
243                 error("unknown offset byte");
244         case sp_cend:
245                 lnp = newline(OPNO);
246                 break;
247         case CSTX1:
248                 if ((em_flag[instr-sp_fmnem]&EM_PAR)!= PAR_B) {
249                         if (CANMINI(tabval))
250                                 lnp = newline(tabval+Z_OPMINI);
251                         else {
252                                 lnp = newline(OPSHORT);
253                                 lnp->l_a.la_short = tabval;
254                         }
255                 } else {
256                         lnp = newline(OPNUMLAB);
257                         lnp->l_a.la_np = numlookup((unsigned) tabval);
258                 }
259                 break;
260 #ifdef LONGOFF
261         case CSTX2:
262                 lnp = newline(OPOFFSET);
263                 lnp->l_a.la_offset = tabval2;
264                 break;
265 #endif
266         case ILBX:
267                 tstinpro();
268                 lnp = newline(OPNUMLAB);
269                 lnp->l_a.la_np = numlookup((unsigned) tabval);
270                 break;
271         case DLBX:
272                 lnp = newline(OPSYMBOL);
273                 lnp->l_a.la_sp = symlookup(string,OCCURRING,0);
274                 break;
275         case sp_pnam:
276                 lnp = newline(OPSYMBOL);
277                 lnp->l_a.la_sp = symlookup(string,OCCURRING,SYMPRO);
278                 break;
279         case VALX1:
280                 lnp = newline(OPSVAL);
281                 lnp->l_a.la_sval.lasv_sp = symlookup(string,OCCURRING,0);
282                 lnp->l_a.la_sval.lasv_short = tabval;
283                 break;
284 #ifdef LONGOFF
285         case VALX2:
286                 lnp = newline(OPLVAL);
287                 lnp->l_a.la_lval.lalv_sp = symlookup(string,OCCURRING,0);
288                 lnp->l_a.la_lval.lalv_offset = tabval2;
289                 break;
290 #endif
291         }
292         lnp->l_instr = instr;
293         lnp->l_next = curpro.lastline;
294         curpro.lastline = lnp;
295     }
296 }
297
298 argstring(length,abp) offset length; register argb_p abp; {
299
300         while (length--) {
301                 if (abp->ab_index == NARGBYTES)
302                         abp = abp->ab_next = newargb();
303                 abp->ab_contents[abp->ab_index++] = readbyte();
304         }
305 }
306
307 line_p  arglist(n) int n; {
308         line_p  lnp;
309         register arg_p ap,*app;
310         bool moretocome;
311         offset length;
312
313
314         /*
315          * creates an arglist with n elements
316          * if n == 0 the arglist is variable and terminated by sp_cend
317          */
318
319         lnp = newline(OPLIST);
320         app = &lnp->l_a.la_arg;
321         moretocome = TRUE;
322         do {
323                 switch(table2()) {
324                 default:
325                         error("unknown byte in arglist");
326                 case CSTX1:
327                         tabval2 = (offset) tabval;
328                 case CSTX2:
329                         *app = ap = newarg(ARGOFF);
330                         ap->a_a.a_offset = tabval2;
331                         app = &ap->a_next;
332                         break;
333                 case ILBX:
334                         tstinpro();
335                         *app = ap = newarg(ARGNUM);
336                         ap->a_a.a_np = numlookup((unsigned) tabval);
337                         ap->a_a.a_np->n_flags |= NUMDATA;
338                         app = &ap->a_next;
339                         break;
340                 case DLBX:
341                         *app = ap = newarg(ARGSYM);
342                         ap->a_a.a_sp = symlookup(string,OCCURRING,0);
343                         app = &ap->a_next;
344                         break;
345                 case sp_pnam:
346                         *app = ap = newarg(ARGSYM);
347                         ap->a_a.a_sp = symlookup(string,OCCURRING,SYMPRO);
348                         app = &ap->a_next;
349                         break;
350                 case VALX1:
351                         tabval2 = (offset) tabval;
352                 case VALX2:
353                         *app = ap = newarg(ARGVAL);
354                         ap->a_a.a_val.av_sp = symlookup(string,OCCURRING,0);
355                         ap->a_a.a_val.av_offset = tabval2;
356                         app = &ap->a_next;
357                         break;
358                 case sp_scon:
359                         *app = ap = newarg(ARGSTR);
360                         length = getoff();
361                         argstring(length,&ap->a_a.a_string);
362                         app = &ap->a_next;
363                         break;
364                 case sp_icon:
365                         *app = ap = newarg(ARGICN);
366                         goto casecon;
367                 case sp_ucon:
368                         *app = ap = newarg(ARGUCN);
369                         goto casecon;
370                 case sp_fcon:
371                         *app = ap = newarg(ARGFCN);
372                 casecon:
373                         length = getint();
374                         ap->a_a.a_con.ac_length = (short) length;
375                         argstring(getoff(),&ap->a_a.a_con.ac_con);
376                         app = &ap->a_next;
377                         break;
378                 case sp_cend:
379                         moretocome = FALSE;
380                 }
381                 if (n && (--n) == 0)
382                         moretocome = FALSE;
383         } while (moretocome);
384         return(lnp);
385 }
386
387 offset aoff(ap,n) register arg_p ap; {
388
389         while (n>0) {
390                 if (ap != (arg_p) 0)
391                         ap = ap->a_next;
392                 n--;
393         }
394         if (ap == (arg_p) 0)
395                 error("too few parameters");
396         if (ap->a_typ != ARGOFF)
397                 error("offset expected");
398         return(ap->a_a.a_offset);
399 }
400
401 int inpseudo(n) short n; {
402         register line_p lnp,head,tail;
403         short           n1,n2;
404         proinf savearea;
405 #ifdef PSEUBETWEEN
406         static int pcount=0;
407
408         if (pcount++ >= PSEUBETWEEN && prodepth==0) {
409                 process();
410                 pcount=0;
411         }
412 #endif
413
414         switch(n) {
415         default:
416                 error("unknown pseudo");
417         case ps_bss:
418         case ps_hol:
419                 lnp = arglist(3);
420                 break;
421         case ps_rom:
422         case ps_con:
423                 lnp = arglist(0);
424                 break;
425         case ps_ina:
426         case ps_inp:
427         case ps_exa:
428         case ps_exp:
429                 lnp = newline(OPSYMBOL);
430                 lnp->l_a.la_sp = getsym(NOTHING);
431                 break;
432         case ps_exc:
433                 n1 = getint(); n2 = getint();
434                 if (n1 != 0 && n2 != 0) {
435                         tail = curpro.lastline;
436                         while (--n2) tail = tail->l_next;
437                         head = tail;
438                         while (n1--) head = head->l_next;
439                         lnp = tail->l_next;
440                         tail->l_next = head->l_next;
441                         head->l_next = curpro.lastline;
442                         curpro.lastline = lnp;
443                 }
444                 lnp = newline(OPNO);
445                 break;
446         case ps_mes:
447                 lnp = arglist(0);
448                 switch((int) aoff(lnp->l_a.la_arg,0)) {
449                 case ms_err:
450                         draininput(); exit(-1);
451                 case ms_opt:
452                         nflag = TRUE; break;
453                 case ms_emx:
454                         wordsize = aoff(lnp->l_a.la_arg,1);
455                         pointersize = aoff(lnp->l_a.la_arg,2);
456 #ifndef LONGOFF
457                         if (wordsize>2)
458                                 error("This optimizer cannot handle wordsize>2");
459 #endif
460                         break;
461                 case ms_gto:
462                         curpro.gtoproc=1;
463                         /* Treat as empty mes ms_reg */
464                 case ms_reg:
465                         tstinpro();
466                         regvar(lnp->l_a.la_arg->a_next);
467                         oldline(lnp);
468                         lnp=newline(OPNO);
469                         n=ps_exc;       /* kludge to force out this line */
470                         break;
471                 case ms_tes:
472                         tstinpro();
473                         oldline(lnp);
474                         lnp=newline(OPNO);
475                         n=ps_exc;       /* kludge to force out this line */
476                         break;
477                 }
478                 break;
479         case ps_pro:
480                 if (prodepth>0)
481                         savearea = curpro;
482                 else
483                         process();
484                 curpro.symbol = getsym(DEFINING);
485                 switch(table2()) {
486                 case sp_cend:
487                         curpro.localbytes = (offset) -1;
488                         break;
489                 case CSTX1:
490                         tabval2 = (offset) tabval;
491                 case CSTX2:
492                         curpro.localbytes = tabval2;
493                         break;
494                 default:
495                         error("bad second arg of PRO");
496                 }
497                 prodepth++;
498                 curpro.gtoproc=0;
499                 if (prodepth>1) {
500                         register i;
501
502                         curpro.lastline = (line_p) 0;
503                         curpro.freg = (reg_p) 0;
504                         for(i=0;i<NNUMHASH;i++)
505                                 curpro.numhash[i] = (num_p) 0;
506                         getlines();
507                         curpro = savearea;
508                         prodepth--;
509                 }
510                 return(0);
511         case ps_end:
512                 if (prodepth==0)
513                         error("END misplaced");
514                 switch(table2()) {
515                 case sp_cend:
516                         if (curpro.localbytes == (offset) -1)
517                                 error("bytes for locals still unknown");
518                         break;
519                 case CSTX1:
520                         tabval2 = (offset) tabval;
521                 case CSTX2:
522                         if (curpro.localbytes != (offset) -1 && curpro.localbytes != tabval2)
523                                 error("inconsistency in number of bytes for locals");
524                         curpro.localbytes = tabval2;
525                         break;
526                 }
527                 process();
528                 curpro.symbol = (sym_p) 0;
529                 if (prodepth==1) {
530                         prodepth=0;
531 #ifdef PSEUBETWEEN
532                         pcount=0;
533 #endif
534                         return(0);
535                 } else
536                         return(1);
537         }
538         lnp->l_instr = n;
539         lnp->l_next = curpro.lastline;
540         curpro.lastline = lnp;
541         return(0);
542 }
543
544 tstinpro() {
545
546         if (prodepth==0)
547                 error("This is not allowed outside a procedure");
548 }