/* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". * */ #include #include #include #include #include #include "ack.h" #include "list.h" #include "trans.h" #include "system.h" #include "print.h" #include #include "data.h" #include static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 } ; static int arg_count; int main(int argc, char *argv[]) { register list_elem *elem ; register char *frontend ; register int *n_sig ; register trf *phase ; progname=argv[0]; varinit(); vieuwargs(argc,argv); if ( (frontend=getenv("ACKFE")) ) { setlist(frontend) ; } else { setlist(FRONTENDS); } if ( callname ) { if ( machine ) { fuerror("can not produce code for both %s and %s", callname,machine) ; } machine= callname ; } if ( !machine && ! (machine=getenv("ACKM")) ) { #ifdef ACKM machine= ACKM; /* The default machine */ #else fuerror("No machine specified") ; #endif } setlist(machine); /* Find the linker, needed for argument building */ scanlist(l_first(tr_list),elem) { if ( t_cont(*elem)->t_linker ) { linker= t_cont(*elem) ; } } transini(); scanneeds(); sprintf(template,TMPNAME,getpid()) ; if ( n_error && !k_flag ) exit(n_error) ; for ( n_sig=sigs ; *n_sig ; n_sig++ ) { if ( signal(*n_sig,noodstop)==SIG_IGN ) { signal(*n_sig,SIG_IGN) ; } } scanlist ( l_first(arguments), elem ) { arg_count++; } scanlist ( l_first(arguments), elem ) { if ( !process(l_content(*elem)) && !k_flag ) exit(1) ; } orig.p_path= (char *)0 ; if ( !rts ) rts="." ; setsvar(keeps(RTS),rts) ; if ( linker ) getmapflags(linker) ; scanlist(l_first(tr_list),elem) { phase=t_cont(*elem) ; if ( phase->t_combine && phase->t_do ) { if ( phase->t_blocked ) { #ifdef DEBUG if ( debug ) { vprint("phase %s is blocked\n", phase->t_name) ; } #endif disc_inputs(phase) ; continue ; } orig.p_keep=YES ; orig.p_keeps=NO ; orig.p_path=phase->t_origname ; if ( p_basename ) throws(p_basename) ; if ( orig.p_path ) { p_basename= keeps(basename(orig.p_path)) ; } else { p_basename=0 ; } if ( !startrf(phase) && !k_flag ) exit(1) ; } } if ( n_error ) exit(n_error) ; exit(0) ; } char *srcvar() { return orig.p_path ; } char *getsuffix() { return strrchr(orig.p_path, SUFCHAR) ; } void varinit() { /* initialize the string variables */ register char *envstr ; extern char *em_dir; if ( (envstr=getenv("ACKDIR")) ) { em_dir = keeps(envstr); } setsvar(keeps(HOME),em_dir) ; setpvar(keeps(SRC),srcvar) ; setpvar(keeps(SUFFIX),getsuffix) ; } /************************* flag processing ***********************/ void vieuwargs(int argc, char *argv[]) { register char *argp; register int nextarg ; register int eaten ; int hide ; firstarg(argv[0]) ; nextarg= 1 ; while ( nextarg=argc ) { fuerror("-o can't be the last flag") ; } if ( outfile ) fuerror("Two results?") ; outfile= argv[nextarg++] ; hide=YES ; break ; case 'O': Optlevel = atoi(&argp[2]); if (! Optlevel) Optlevel = 1; Optlist= &argp[2] ; eaten=1 ; break ; case 'v': if ( argp[2] ) { v_flag += atoi(&argp[2]) ; eaten=1 ; } else { v_flag++ ; } #ifdef DEBUG if ( v_flag>=3 ) debug=v_flag-2 ; #endif break ; case 'c': if ( stopsuffix ) fuerror("Two -c flags") ; stopsuffix= &argp[2]; eaten=1; if ( *stopsuffix && *stopsuffix!=SUFCHAR ) { fuerror("-c flag has invalid tail") ; } break ; case 'k': k_flag++ ; break ; case 't': t_flag++ ; break ; case 'R': eaten=1; break ; case 'r': if ( argp[2]!=SUFCHAR ) { error("-r must be followed by %c",SUFCHAR) ; } keeptail(&argp[2]); eaten=1 ; break ; case '.': if ( rts ) { if ( strcmp(rts,&argp[1])!=0 ) fuerror("Two run-time systems?") ; } else { rts= &argp[1] ; keephead(rts) ; keeptail(rts) ; } eaten=1 ; break ; case 0 : nill_flag++ ; eaten++ ; hide=YES ; break; case 'w': w_flag++; break ; default: /* The flag is not recognized, put it on the list for the sub-processes */ #ifdef DEBUG if ( debug ) { vprint("Flag %s: phase dependent\n",argp) ; } #endif l_add(&flags,keeps(argp)) ; eaten=1 ; hide=YES ; } if ( !hide ) { register char *tokeep ; tokeep=keeps(argp) ; if ( argp[1]=='R' ) { do_Rflag(tokeep); } else { *tokeep |= NO_SCAN ; } l_add(&flags,tokeep) ; } if ( argp[2] && !eaten ) { werror("Unexpected characters at end of %s",argp) ; } } return ; } void firstarg(char *argp) { register char *name ; name=strrchr(argp,'/') ; if ( name && *(name+1) ) { name++ ; } else { name= argp ; } callname= name; } /************************* argument processing ***********************/ int process(char *arg) { /* Process files & library arguments */ trf *phase ; register trf *tmp ; #ifdef DEBUG if ( debug ) vprint("Processing %s\n",arg) ; #endif p_suffix= strrchr(arg,SUFCHAR) ; orig.p_keep= YES ; /* Don't throw away the original ! */ orig.p_keeps= NO; orig.p_path= arg ; if ( arg[0]=='-' || !p_suffix ) { if ( linker ) add_input(&orig,linker) ; return 1 ; } if ( p_basename ) throws(p_basename) ; p_basename= keeps(basename(arg)) ; /* Try to find a path through the transformations */ switch( getpath(&phase) ) { case FP_NOPATH : error("Cannot produce the desired file from %s",arg) ; if ( linker ) add_input(&orig,linker) ; return 1 ; case FP_NOMATCH : if ( stopsuffix ) werror("Unknown suffix in %s",arg) ; if ( linker ) add_input(&orig,linker) ; return 1 ; case FP_OK : break ; } if ( !phase ) return 1 ; for ( tmp=phase ; tmp ; tmp=tmp->t_next ) if ( !tmp->t_visited ) { /* The flags are set up once. At the first time each phase is in a list. The program name and flags may already be touched by vieuwargs. */ tmp->t_visited=YES ; if ( tmp->t_priority<0 ) werror("Using phase %s (negative priority)", tmp->t_name) ; if ( !rts && tmp->t_rts ) rts= tmp->t_rts ; if ( tmp->t_needed ) { add_head(tmp->t_needed) ; add_tail(tmp->t_needed) ; } } if ( phase->t_combine ) { add_input(&orig,phase) ; return 1 ; } in= orig ; if ( !nill_flag && arg_count > 1 ) { printf("%s\n",arg) ; } return startrf(phase) ; } int startrf(trf *first) { /* Start the transformations at the indicated phase */ register trf *phase ; phase=first ; for(;;) { int do_preprocess = 0; int only_prep = 0; switch ( phase->t_prep ) { /* BEWARE, sign extension */ case NO : break ; default : if ( !mayprep() ) break ; case YES: do_preprocess = 1; break; } if ( cpp_trafo && stopsuffix && strcmp(cpp_trafo->t_out,stopsuffix)==0 ) { /* user explicitly asked for preprocessing */ do_preprocess = 1; only_prep = 1; } if (do_preprocess && !transform(cpp_trafo) ) { n_error++ ; #ifdef DEBUG vprint("Pre-processor failed\n") ; #endif return 0 ; } if ( only_prep ) { break ; } if ( !transform(phase) ) { n_error++ ; block(phase->t_next) ; #ifdef DEBUG if ( debug ) { if ( !orig.p_path ) { vprint("phase %s failed\n", phase->t_name ) ; } else { vprint("phase %s for %s failed\n", phase->t_name,orig.p_path) ; } } #endif return 0 ; } first=NO ; phase=phase->t_next ; if ( !phase ) { #ifdef DEBUG if ( debug ) vprint("Transformation sequence complete for %s\n", orig.p_path) ; #endif /* No more work on this file */ if ( !in.p_keep ) { fatal("attempt to discard the result file") ; } if ( in.p_keeps ) throws(in.p_path) ; in.p_keep=NO ; in.p_keeps=NO ; in.p_path= (char *) 0 ; return 1 ; } if ( phase->t_combine ) { add_input(&in,phase) ; break ; } } return 1 ; } void block(trf *first) { /* One of the input files of this phase could not be produced, block all combiners taking their input from this one. */ register trf *phase ; for ( phase=first ; phase ; phase=phase->t_next ) { if ( phase->t_combine ) phase->t_blocked=YES ; } } int mayprep() { int file ; char fc ; file=open(in.p_path,0); if ( file<0 ) return 0 ; if ( read(file,&fc,1)!=1 ) fc=0 ; close(file) ; return fc=='#' ; } void keephead(char *suffix) { l_add(&head_list, suffix) ; } void keeptail(char *suffix) { l_add(&tail_list, suffix) ; } void scanneeds() { register list_elem *elem ; scanlist(l_first(head_list), elem) { setneeds(l_content(*elem),0) ; } l_clear(&head_list) ; scanlist(l_first(tail_list), elem) { setneeds(l_content(*elem),1) ; } l_clear(&tail_list) ; } void setneeds(char *suffix, int tail) { trf *phase ; p_suffix= suffix ; switch ( getpath(&phase) ) { case FP_OK : for ( ; phase ; phase= phase->t_next ) { if ( phase->t_needed ) { if ( tail ) add_tail(phase->t_needed) ; else add_head(phase->t_needed) ; } } break ; case FP_NOMATCH : werror("\"%s\": unrecognized suffix",suffix) ; break ; case FP_NOPATH : werror("sorry, cannot produce the desired file(s) from %s files", suffix) ; break ; } }