Pristine Ack-5.5
[Ack-5.5.git] / util / ack / main.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 "list.h"
9 #include "trans.h"
10 #include <local.h>
11 #include "data.h"
12 #include <signal.h>
13
14 #ifndef NORCSID
15 static char rcs_id[] = "$Id: main.c,v 2.21 1994/06/24 10:12:52 ceriel Exp $" ;
16 static char rcs_ack[] = RCS_ACK ;
17 #endif
18
19 static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 } ;
20 static int arg_count;
21
22 extern  char    *getenv();
23
24 main(argc,argv) char **argv ; {
25         register list_elem *elem ;
26         register char *frontend ;
27         register int *n_sig ;
28         register trf *phase ;
29
30         progname=argv[0];
31         varinit();
32         vieuwargs(argc,argv);
33         if ( (frontend=getenv("ACKFE")) ) {
34                 setlist(frontend) ;
35         } else {
36                 setlist(FRONTENDS);
37         }
38         if ( callname ) {
39                 if ( machine ) {
40                         fuerror("can not produce code for both %s and %s",
41                                 callname,machine) ;
42                 }
43                 machine= callname ;
44         }
45         if ( !machine && ! (machine=getenv("ACKM")) ) {
46 #ifdef ACKM
47                 machine= ACKM;          /* The default machine */
48 #else
49                 fuerror("No machine specified") ;
50 #endif
51         }
52         setlist(machine);
53         /* Find the linker, needed for argument building */
54         scanlist(l_first(tr_list),elem) {
55                 if ( t_cont(*elem)->t_linker ) {
56                         linker= t_cont(*elem) ;
57                 }
58         }
59         transini();
60         scanneeds();
61         sprintf(template,TMPNAME,getpid()) ;
62         if ( n_error && !k_flag ) exit(n_error) ;
63
64         for ( n_sig=sigs ; *n_sig ; n_sig++ ) {
65                 if ( signal(*n_sig,noodstop)==SIG_IGN ) {
66                         signal(*n_sig,SIG_IGN) ;
67                 }
68         }
69
70         scanlist ( l_first(arguments), elem ) {
71                 arg_count++;
72         }
73
74         scanlist ( l_first(arguments), elem ) {
75                 if ( !process(l_content(*elem)) && !k_flag ) exit(1) ;
76         }
77         orig.p_path= (char *)0 ;
78         if ( !rts ) rts="." ;
79         setsvar(keeps(RTS),rts) ;
80         if ( linker ) getmapflags(linker) ;
81
82         scanlist(l_first(tr_list),elem) {
83                 phase=t_cont(*elem) ;
84                 if ( phase->t_combine && phase->t_do ) {
85                         if ( phase->t_blocked ) {
86 #ifdef DEBUG
87                                 if ( debug ) {
88                                         vprint("phase %s is blocked\n",
89                                                 phase->t_name) ;
90                                 }
91 #endif
92                                 disc_inputs(phase) ;
93                                 continue ;
94                         }
95                         orig.p_keep=YES ;
96                         orig.p_keeps=NO ;
97                         orig.p_path=phase->t_origname ;
98                         if ( p_basename ) throws(p_basename) ;
99                         if ( orig.p_path ) {
100                                 p_basename= keeps(basename(orig.p_path)) ;
101                         } else {
102                                 p_basename=0 ;
103                         }
104                         if ( !startrf(phase) && !k_flag ) exit(1) ;
105                 }
106         }
107
108         if ( n_error ) exit(n_error) ;
109
110         exit(0) ;
111 }
112
113 char *srcvar() {
114         return orig.p_path ;
115 }
116
117 char *getsuffix() {
118         return strrindex(orig.p_path, SUFCHAR) ;
119 }
120
121 varinit() {
122         /* initialize the string variables */
123         register char *envstr ;
124         extern char *em_dir;
125
126         if ( envstr=getenv("ACKDIR") ) {
127                 em_dir = keeps(envstr);
128         }
129         setsvar(keeps(HOME),em_dir) ;
130         setpvar(keeps(SRC),srcvar)  ;
131         setpvar(keeps(SUFFIX),getsuffix) ;
132 }
133
134 /************************* flag processing ***********************/
135
136 vieuwargs(argc,argv) char **argv ; {
137         register char *argp;
138         register int nextarg ;
139         register int eaten ;
140         int hide ;
141
142         firstarg(argv[0]) ;
143
144         nextarg= 1 ;
145
146         while ( nextarg<argc ) {
147                 argp= argv[nextarg] ;
148                 nextarg++ ;
149                 if ( argp[0]!='-' || argp[1]=='l' ) {
150                         /* Not a flag, or a library */
151                         l_add(&arguments,argp) ;
152                         continue ;
153                 }
154
155                 /* Flags */
156                 hide=NO ; /* Do not hide this flags to the phases */
157                 eaten=0 ; /* Did not 'eat' tail of flag yet */
158                 switch ( argp[1] ) {
159            case 'm':    if ( machine ) fuerror("Two machines?") ;
160                         machine= &argp[2];
161                         if (*machine == '\0') {
162                                 fuerror("-m needs machine name");
163                         }
164                         eaten=1 ;
165                         break ;
166            case 'o':    if ( nextarg>=argc ) {
167                                 fuerror("-o can't be the last flag") ;
168                         }
169                         if ( outfile ) fuerror("Two results?") ;
170                         outfile= argv[nextarg++] ;
171                         hide=YES ;
172                         break ;
173            case 'O':    Optlevel = atoi(&argp[2]);
174                         if (! Optlevel) Optlevel = 1;
175                         Optlist= &argp[2] ;
176                         eaten=1 ;
177                         break ;
178            case 'v':    if ( argp[2] ) {
179                                 v_flag += atoi(&argp[2]) ;
180                                 eaten=1 ;
181                         } else {
182                                 v_flag++ ;
183                         }
184 #ifdef DEBUG
185                         if ( v_flag>=3 ) debug=v_flag-2 ;
186 #endif
187                         break ;
188            case 'c':    if ( stopsuffix ) fuerror("Two -c flags") ;
189                         stopsuffix= &argp[2]; eaten=1;
190                         if ( *stopsuffix && *stopsuffix!=SUFCHAR ) {
191                                 fuerror("-c flag has invalid tail") ;
192                         }
193                         break ;
194            case 'k':    k_flag++ ;
195                         break ;
196            case 't':    t_flag++ ;
197                         break ;
198            case 'R':    eaten=1;
199                         break ;
200            case 'r':    if ( argp[2]!=SUFCHAR ) {
201                                 error("-r must be followed by %c",SUFCHAR) ;
202                         }
203                         keeptail(&argp[2]); eaten=1 ;
204                         break ;
205            case '.':    if ( rts ) {
206                                 if ( strcmp(rts,&argp[1])!=0 )
207                                         fuerror("Two run-time systems?") ;
208                         } else {
209                                 rts= &argp[1] ;
210                                 keephead(rts) ; keeptail(rts) ;
211                         }
212                         eaten=1 ;
213                         break ;
214            case  0 :    nill_flag++ ; eaten++ ;
215                         hide=YES ;
216                         break;
217            case 'w':    w_flag++;
218                         break ;
219            default:     /* The flag is not recognized,
220                            put it on the list for the sub-processes
221                         */
222 #ifdef DEBUG
223                         if ( debug ) {
224                                 vprint("Flag %s: phase dependent\n",argp) ;
225                         }
226 #endif
227                         l_add(&flags,keeps(argp)) ;
228                         eaten=1 ;
229                         hide=YES ;
230                 }
231                 if ( !hide ) {
232                         register char *tokeep ;
233                         tokeep=keeps(argp) ;
234                         if ( argp[1]=='R' ) {
235                                 do_Rflag(tokeep); 
236                         } else {
237                                 *tokeep |= NO_SCAN ;
238                         }
239                         l_add(&flags,tokeep) ;
240                 }
241                 if ( argp[2] && !eaten ) {
242                         werror("Unexpected characters at end of %s",argp) ;
243                 }
244         }
245         return ;
246 }
247
248 firstarg(argp) register char *argp ; {
249         register char *name ;
250
251         name=strrindex(argp,'/') ;
252         if ( name && *(name+1) ) {
253                 name++ ;
254         } else {
255                 name= argp ;
256         }
257         callname= name;
258 }
259
260 /************************* argument processing ***********************/
261
262 process(arg) char *arg ; {
263         /* Process files & library arguments */
264         trf *phase ;
265         register trf *tmp ;
266
267 #ifdef DEBUG
268         if ( debug ) vprint("Processing %s\n",arg) ;
269 #endif
270         p_suffix= strrindex(arg,SUFCHAR) ;
271         orig.p_keep= YES ;      /* Don't throw away the original ! */
272         orig.p_keeps= NO;
273         orig.p_path= arg ;
274         if ( arg[0]=='-' || !p_suffix ) {
275                 if ( linker ) add_input(&orig,linker) ;
276                 return 1 ;
277         }
278         if ( p_basename ) throws(p_basename) ;
279         p_basename= keeps(basename(arg)) ;
280         /* Try to find a path through the transformations */
281         switch( getpath(&phase) ) {
282         case F_NOPATH :
283                 error("Cannot produce the desired file from %s",arg) ;
284                 if ( linker ) add_input(&orig,linker) ;
285                 return 1 ;
286         case F_NOMATCH :
287                 if ( stopsuffix ) werror("Unknown suffix in %s",arg) ;
288                 if ( linker ) add_input(&orig,linker) ;
289                 return 1 ;
290         case F_OK :
291                 break ;
292         }
293         if ( !phase ) return 1 ;
294         for ( tmp=phase ; tmp ; tmp=tmp->t_next )
295         if ( !tmp->t_visited ) {
296                 /* The flags are set up once.
297                    At the first time each phase is in a list.
298                    The program name and flags may already be touched
299                    by vieuwargs.
300                 */
301                 tmp->t_visited=YES ;
302                 if ( tmp->t_priority<0 )
303                         werror("Using phase %s (negative priority)",
304                                 tmp->t_name) ;
305                 if ( !rts && tmp->t_rts ) rts= tmp->t_rts ;
306                 if ( tmp->t_needed ) {
307                         add_head(tmp->t_needed) ;
308                         add_tail(tmp->t_needed) ;
309                 }
310         }
311         if ( phase->t_combine ) {
312                 add_input(&orig,phase) ;
313                 return 1 ;
314         }
315         in= orig ;
316         if ( !nill_flag && arg_count > 1 ) {
317                 printf("%s\n",arg) ;
318         }
319         return startrf(phase) ;
320 }
321
322 int startrf(first) trf *first ; {
323         /* Start the transformations at the indicated phase */
324         register trf *phase ;
325
326         phase=first ;
327         for(;;) {
328                 int do_preprocess = 0;
329                 int only_prep = 0;
330
331                 switch ( phase->t_prep ) {
332                         /* BEWARE, sign extension */
333                 case NO :    break ;
334                 default :    if ( !mayprep() ) break ;
335                 case YES:    do_preprocess = 1;
336                              break;
337                 }
338                 if ( cpp_trafo && stopsuffix &&
339                      strcmp(cpp_trafo->t_out,stopsuffix)==0 ) {
340                         /* user explicitly asked for preprocessing */
341                         do_preprocess = 1;
342                         only_prep = 1;
343                 }
344
345                 if (do_preprocess && !transform(cpp_trafo) ) {
346                                    n_error++ ;
347 #ifdef DEBUG
348                                    vprint("Pre-processor failed\n") ;
349 #endif
350                                    return 0 ;
351                 }
352                 if ( only_prep ) {
353                         break ;
354                 }
355                 if ( !transform(phase) ) {
356                         n_error++ ;
357                         block(phase->t_next) ;
358 #ifdef DEBUG
359                         if ( debug ) {
360                                 if ( !orig.p_path ) {
361                                         vprint("phase %s failed\n",
362                                                 phase->t_name ) ;
363                                 } else {
364                                         vprint("phase %s for %s failed\n",
365                                                 phase->t_name,orig.p_path) ;
366                                 }
367                         }
368 #endif
369                         return 0 ;
370                 }
371                 first=NO ;
372                 phase=phase->t_next ;
373                 if ( !phase ) {
374 #ifdef DEBUG
375 if ( debug ) vprint("Transformation sequence complete for %s\n",
376                                 orig.p_path) ;
377 #endif
378                         /* No more work on this file */
379                         if ( !in.p_keep ) {
380                                 fatal("attempt to discard the result file") ;
381                         }
382                         if ( in.p_keeps ) throws(in.p_path) ;
383                         in.p_keep=NO ; in.p_keeps=NO ; in.p_path= (char *) 0 ;
384                         return 1 ;
385                 }
386                 if ( phase->t_combine ) {
387                         add_input(&in,phase) ;
388                         break ;
389                 }
390         }
391         return 1 ;
392 }
393
394 block(first) trf *first ; {
395         /* One of the input files of this phase could not be produced,
396            block all combiners taking their input from this one.
397         */
398         register trf *phase ;
399         for ( phase=first ; phase ; phase=phase->t_next ) {
400                 if ( phase->t_combine ) phase->t_blocked=YES ;
401         }
402 }
403 mayprep() {
404         int file ;
405         char fc ;
406         file=open(in.p_path,0);
407         if ( file<0 ) return 0 ;
408         if ( read(file,&fc,1)!=1 ) fc=0 ;
409         close(file) ;
410         return fc=='#' ;
411 }
412
413 keephead(suffix) char *suffix ; {
414         l_add(&head_list, suffix) ;
415 }
416
417 keeptail(suffix) char *suffix ; {
418         l_add(&tail_list, suffix) ;
419 }
420
421 scanneeds() {
422         register list_elem *elem ;
423         scanlist(l_first(head_list), elem) { setneeds(l_content(*elem),0) ; }
424         l_clear(&head_list) ;
425         scanlist(l_first(tail_list), elem) { setneeds(l_content(*elem),1) ; }
426         l_clear(&tail_list) ;
427 }
428
429 setneeds(suffix,tail) char *suffix ; {
430         trf *phase ;
431
432         p_suffix= suffix ;
433         switch ( getpath(&phase) ) {
434         case F_OK :
435                 for ( ; phase ; phase= phase->t_next ) {
436                         if ( phase->t_needed ) {
437                                 if ( tail )
438                                         add_tail(phase->t_needed) ;
439                                 else
440                                         add_head(phase->t_needed) ;
441                         }
442                 }
443                 break ;
444         case F_NOMATCH :
445                 werror("\"%s\": unrecognized suffix",suffix) ;
446                 break ;
447         case F_NOPATH :
448                 werror("sorry, cannot produce the desired file(s) from %s files",
449                         suffix) ;
450                 break ;
451         }
452 }