Pristine Ack-5.5
[Ack-5.5.git] / util / ack / rmach.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  *
5  */
6
7 #include "ack.h"
8 #include <em_path.h>
9 #include "list.h"
10 #include "trans.h"
11 #include "grows.h"
12 #include "dmach.h"
13 #include "data.h"
14 #include <stdio.h>
15
16 #ifndef NORCSID
17 static char rcs_id[] = "$Id: rmach.c,v 2.17 1994/06/24 10:13:02 ceriel Exp $" ;
18 static char rcs_dmach[] = RCS_DMACH ;
19 #endif
20
21 /************************************************************************/
22 /*                                                                      */
23 /*           Read machine definitions and transformations               */
24 /*                                                                      */
25 /************************************************************************/
26
27 #define COMMENT '#'
28
29 #define VAR     "var"
30 #define PASS    "name"
31 #define IN      "from"
32 #define OUT     "to"
33 #define RES     "outfile"
34 #define PROG    "program"
35 #define MAPF    "mapflag"
36 #define ARGS    "args"
37 #define STD_IN  "stdin"
38 #define STD_OUT "stdout"
39 #define PREP    "prep"
40 #define OPT     "optimizer"
41 #define LINKER  "linker"
42 #define COMBINER "combiner"
43 #define PRIO    "priority"
44 #define RUNT    "rts"
45 #define NEEDT   "need"
46 #define CALL    "callname"
47 #define END     "end"
48
49 extern growstring scanb();
50 extern growstring scanvars();
51
52 int getline() ;
53 int getinchar() ;
54 static char *ty_name ;
55 static char *bol ;
56
57
58 static char *inname ;
59
60 setlist(name) char *name ; {
61         /* Name is sought in the internal tables,
62            if not present, the a file of that name is sought
63            in first the current and then the EM Lib directory
64         */
65
66         inname=name ;
67         open_in(name) ;
68         while ( getline() ) {
69                 if ( strcmp(VAR,ty_name)==0 ) {
70                         doassign(bol,(char *)0,0) ;
71                 } else
72                 if ( strcmp(CALL,ty_name)==0 ) {
73                         if ( callname && strcmp(bol,callname)==0 ) {
74                                 callname= (char *)0 ;
75 #ifdef DEBUG
76                                 if ( debug>=3 ) {
77                                         vprint("found call name\n");
78                                 }
79 #endif
80                         }
81                 } else
82                 if ( strcmp(PASS,ty_name)==0 ) {
83                         intrf() ;
84                 } else
85                         error("unknown keyword %s",ty_name) ;
86         }
87         close_in();
88 #ifdef DEBUG
89         if ( debug>=3 ) vprint("End %s\n",name) ;
90 #endif
91 }
92
93 static int inoptlist(nm)
94         char *nm ;
95 {
96         register char *p=Optlist ;
97
98         while ( p && *p ) {
99                 register char *q=nm ;
100
101                 while ( *q!='\0' && *q++==*p ) p++ ;
102                 if ( *q=='\0' && ( *p=='\0' || *p==',' ) ) return 1 ;
103                 while ( *p!='\0' && *p++!=',' ) /* nothing */ ;
104         }
105         return 0;
106 }
107
108 intrf() {
109         register trf *new ;
110         growstring bline ;
111         int twice ;
112         int name_seen=0 ;
113
114         new= (trf *)getcore(sizeof *new) ;
115         new->t_name= keeps(bol) ;
116         for (;;) {
117                 if ( !getline() ) {
118                         fuerror("unexpected EOF on %s",inname) ;
119                 }
120                 twice= NO ;
121                 if ( strcmp(ty_name,IN)==0 ) {
122                         if ( new->t_in ) twice=YES ;
123                         new->t_in= keeps(bol);
124                 } else
125                 if ( strcmp(ty_name,OUT)==0 ) {
126                         if ( new->t_out ) twice=YES ;
127                         new->t_out= keeps(bol);
128                 } else
129                 if ( strcmp(ty_name,PROG)==0 ) {
130                         if ( new->t_prog ) twice=YES ;
131                         bline= scanb(bol);                /* Scan for \ */
132                       new->t_prog= gr_final(&bline);
133                 } else
134                 if ( strcmp(ty_name,MAPF)==0 ) {
135                         /* First read the mapflags line
136                                 and scan for backslashes */
137                         bline= scanb(bol) ;
138                         l_add(&new->t_mapf,gr_final(&bline)) ;
139                 } else
140                 if ( strcmp(ty_name,ARGS)==0 ) {
141                         if ( new->t_argd ) twice=YES ;
142                         bline= scanb(bol) ;
143                         new->t_argd= keeps(gr_start(bline)) ;
144                         gr_throw(&bline) ;
145                 } else
146                 if ( strcmp(ty_name,STD_IN)==0 ) {
147                         if ( new->t_stdin ) twice=YES ;
148                         new->t_stdin= YES ;
149                 } else
150                 if ( strcmp(ty_name,STD_OUT)==0 ) {
151                         if ( new->t_stdout ) twice=YES ;
152                         new->t_stdout= YES ;
153                 } else
154                 if ( strcmp(ty_name,PREP)==0 ) {
155                         if ( strcmp(bol,"always")==0 ) {
156                                 if ( new->t_prep ) twice=YES ;
157                                 new->t_prep=YES ;
158                         } else
159                         if ( strcmp(bol,"cond")==0 ) {
160                                 if ( new->t_prep ) twice=YES ;
161                                 new->t_prep=MAYBE ;
162                         } else
163                         if ( strcmp(bol,"is")==0 ) {
164                                 if ( new->t_isprep ) twice=YES ;
165                                 new->t_isprep= YES ;
166                         } else
167                         {
168                                 fuerror("illegal preprocessor spec in %s: %s",
169                                         inname,bol) ;
170                         }
171                 } else
172                 if ( strcmp(ty_name,OPT)==0 ) {
173                         if ( new->t_optim ) twice=YES ;
174                         new->t_optim= atoi(bol) ;
175                         if (new->t_optim <= 0) new->t_optim = 1;
176                 } else
177                 if ( strcmp(ty_name,LINKER)==0 ) {
178                         if ( new->t_linker ) twice=YES ;
179                         new->t_linker= YES ;
180                         new->t_combine= YES ;
181                 } else
182                 if ( strcmp(ty_name,COMBINER)==0 ) {
183                         if ( new->t_combine ) twice=YES ;
184                         new->t_combine= YES ;
185                 } else
186                 if ( strcmp(ty_name,PRIO)==0 ) {
187                         new->t_priority= atoi(bol) ;
188                 } else
189                 if ( strcmp(ty_name,RUNT)==0 ) {
190                         if ( new->t_rts ) twice=YES ;
191                         new->t_rts= keeps(bol) ;
192                 } else
193                 if ( strcmp(ty_name,NEEDT)==0 ) {
194                         if ( new->t_needed ) twice=YES ;
195                         new->t_needed= keeps(bol) ;
196                 } else
197                 if ( strcmp(ty_name,RES)==0 ) {
198                         if ( new->t_outfile ) twice=YES ;
199                         new->t_outfile= keeps(bol) ;
200                 } else
201                 if ( strcmp(ty_name,CALL)==0 ) {
202                         if ( callname && strcmp(bol,callname)==0 ) {
203                                 name_seen=1 ;
204                                 callname= (char *)0 ;
205 #ifdef DEBUG
206                                 if ( debug>=3 ) {
207                                         vprint("found call name in %s\n",
208                                                 new->t_name) ;
209                                 }
210 #endif
211                         }
212                 } else
213                 if ( strcmp(ty_name,END)==0 ) {
214                         break ;
215                 } else {
216                         fuerror("illegal keyword %s %s",ty_name,bol);
217                 }
218                 if ( twice ) {
219                         werror("%s: specified twice for %s",
220                                 ty_name, new->t_name) ;
221                 }
222         }
223         if ( ! ( new->t_name && new->t_out && new->t_prog ) ) {
224                 fuerror("insufficient specification for %s in %s",
225                         new->t_name,inname) ;
226         }
227         if ( ! new->t_argd ) new->t_argd="" ;
228         /* Warning, side effect */
229         if ( name_seen && new->t_rts ) {
230                 if ( rts && strcmp(rts,new->t_rts)!=0 ) {
231                         error("Attempt to use two run-time systems, %s and %s",
232                                 rts, new->t_rts) ;
233                 }
234                 rts= new->t_rts ;
235                 keephead(rts) ; keeptail(rts) ;
236         }
237 #ifdef DEBUG
238         if ( debug>=3 ) {
239                 register list_elem *elem ;
240                 vprint("%s: from %s to %s '%s'\n",
241                         new->t_name,new->t_in ? new->t_in : "(null)",new->t_out,new->t_prog) ;
242                 vprint("\targs: ") ; prns(new->t_argd) ;
243                 scanlist( l_first(new->t_mapf), elem ) {
244                         vprint("\t%s\n",l_content(*elem)) ;
245                 }
246                 if ( new->t_rts ) vprint("\trts: %s\n",new->t_rts) ;
247                 if ( new->t_needed ) vprint("\tneeded: %s\n",new->t_needed) ;
248         }
249 #endif
250         if ( new->t_optim && 
251              ( new->t_optim <= Optlevel || inoptlist(new->t_name) ) ) {
252                 new->t_optim = Optlevel;
253         }
254         l_add(&tr_list,(char *)new) ;
255 }
256
257 /************************** IO from core or file *******************/
258
259 static  int             incore ;
260 static  growstring      rline ;
261 static  FILE            *infile ;
262 static  char            *inptr ;
263 char                    *em_dir = EM_DIR;
264
265 open_in(name) register char *name ; {
266         register dmach *cmac ;
267
268         gr_init(&rline) ;
269         for ( cmac= massoc ; cmac->ma_index!= -1 ; cmac++ ) {
270                 if ( strcmp(name,cmac->ma_name)==0 ) {
271                         incore=YES ;
272                         inptr= &intable[cmac->ma_index] ;
273                         return ;
274                 }
275         }
276         /* Not in core */
277         incore= NO ;
278         /* Try to read EM_DIR/lib/MACH/descr */
279         gr_cat(&rline,em_dir) ;
280         gr_cat(&rline,"/lib/") ; gr_cat(&rline,name) ;
281         gr_cat(&rline,"/descr") ;
282         infile= fopen(gr_start(rline),"r") ;
283         if ( !infile ) {
284                 gr_throw(&rline) ;
285                 gr_cat(&rline,em_dir) ; gr_cat(&rline,"/") ;
286                 gr_cat(&rline,ACK_PATH); gr_cat(&rline,"/") ;
287                 gr_cat(&rline,name) ;
288                 infile= fopen(gr_start(rline),"r") ;
289         }
290         if ( !infile ) {
291                 infile= fopen(name,"r") ;
292         }
293         if ( infile==NULL ) {
294                 fuerror("Cannot find description for %s",name) ;
295         }
296 }
297
298 close_in() {
299         if ( !incore ) fclose(infile) ;
300         gr_throw(&rline) ;
301 }
302
303 char *readline() {
304         /* Get a line from the input,
305            return 0 if at end,
306            The line is stored in a volatile buffer,
307            a pointer to the line is returned.
308         */
309         register int nchar ;
310         enum { BOL, ESCAPE, SKIPPING, MOL } state = BOL ;
311
312         gr_throw(&rline) ;
313         for (;;) {
314                 nchar= getinchar() ;
315                 if ( nchar==EOF ) {
316                         if ( state!=BOL ) {
317                                 werror("incomplete line in %s", inname) ;
318                         }
319                         return 0 ;
320                 }
321                 if ( state==SKIPPING ) {
322                         if ( nchar=='\n' ) {
323                                 state= MOL ;
324                         } else {
325                                 continue ;
326                         }
327                 }
328                 if ( state==ESCAPE ) {
329                         switch( nchar ) {
330                         case '\n' :
331                                 break ;
332                         default :
333                                 gr_add(&rline,BSLASH) ;
334                         case COMMENT :
335                         case BSLASH :
336                                 gr_add(&rline,nchar) ;
337                                 break ;
338                         }
339                         state= MOL ;
340                         continue ;
341                 }
342                 switch ( nchar ) {
343                 case '\n' :     gr_add(&rline,0) ;
344                                 return gr_start(rline) ;
345                 case COMMENT :  state= SKIPPING ;
346                                 break ;
347                 case BSLASH :   state= ESCAPE ;
348                                 break ;
349                 default :       gr_add(&rline,nchar) ;
350                                 state= MOL ;
351                 }
352         }
353 }
354
355 int getinchar() {
356         register int token ;
357
358         if ( incore ) {
359                 if ( *inptr==0 ) return EOF ;
360                 return *inptr++ ;
361         }
362         token= getc(infile) ;
363         if ( (token>=0177 || token <=0 ) && token !=EOF ) {
364                 fuerror("Non-ascii character in description file %s",inname);
365         }
366         return token ;
367 }
368
369 int getline() {
370         register char *c_ptr ;
371
372         do {
373                 if ( (c_ptr=readline())==(char *)0 ) return 0 ;
374                 ty_name= skipblank(c_ptr) ;
375         } while ( *ty_name==0 ) ;
376         c_ptr= firstblank(ty_name) ;
377         if ( *c_ptr ) {
378                 *c_ptr++ =0 ;
379                 c_ptr= skipblank(c_ptr) ;
380         }
381         bol= c_ptr ;
382         return 1 ;
383 }