/* * * EPCL UNIX COMPILER DRIVER. * Stripped down to deal with IMP only * and restricted ti UNIX5.4 systems (pds) 31/10/94 /* Values Recognised by -DCOMP= */ #define GCF 1 #define SUN 2 #define SEQUENT 3 #define UNISYS 4 #define DRS 5 #define CLAN 6 #define TADPOLE 7 #define DRSNX 8 #define SUN386 9 #define UNICORN 10 #define M88000 11 #define AURORA 12 #define PENTIUM 13 #define NO 0 #define YES 1 #define UNIX5d4 YES #include #include static void fatal(char *t); static fatalstr(char *t, char *s); typedef FILE *FILEP; typedef short flag; #define NIMPCOMPILER "p5impcompiler " #define FORTRANCOMPILER " epcf77compiler " #define NUL '\0' #define MAXNOOPTIONS 200 #define ASMNAME "as" #define LDNAME "ld" #define CPPNAME "/usr/lib/cpp" #define FOOTNAME "/usr/lib/crt1.o" #define PROFFOOT "/usr/lib/mcrt1.o" #define GPRFFOOT "/usr/lib/gcrt0.o" static char *impliblist [ ] = { "-limp2", "-Y", "P,/usr/lib", "-Qy","-lc", "/usr/lib/crtn.o", NULL }; static char *sdbentry = "/usr/lib/sdbentry.o"; #include static FILEP diagfile = { stderr}; static int sigivalue = 0; static int sigqvalue = 0; static int sighvalue = 0; static int sigtvalue = 0; static char *fortrancompiler = FORTRANCOMPILER ; static char *nimpcompiler = NIMPCOMPILER ; static char *ldname = LDNAME ; static char *footname = FOOTNAME; static char *cppname = CPPNAME; static char *proffoot = PROFFOOT; static char *gprffoot = GPRFFOOT; static char *shellname = "/bin/sh"; static char *aoutname = "a.out" ; static char *entryname[]= { "-e", "start", NULL}; static char *constloaderargs[]= { "-dy","/usr/lib/crti.o", "/tmp/values-Xt.o", NULL }; static char *infname; static char **drivername; static char fflags[128] = "-"; /* RATFOR flags */ static char cflags[128] = ""; static char rflags[30] = ""; static char lflag[128] = "-x"; /* Loader flags */ static char *fflagp = fflags; static char *cflagp = cflags; static char *lflagp = lflag+1; static char *rflagp = rflags; static char **loadargs; static char **loadp; static char *options = ""; /* long winded options */ static flag erred = NO; static flag loadflag = YES; static flag profileflag = NO; static flag debugflag = NO; static flag optflag = NO; static flag verbose = NO; static flag fortonly = NO; /* Unix 5 variants */ static flag load3f = NO; /* not used if SEQUENT or UNISYS */ static flag loadVax = YES; /* not used if SEQUENT or UNISYS */ static flag loadC77 = NO; /* not used (yet) */ static flag loadNAG = NO; /* YES if -NAG and UNISYS */ int drive_sdb = 0; /* semaphore for flagging -g option */ int parallel = NO; /* semaphore for flagging -mp option */ int atsflag = NO; /* semaphore for flagging -ats option */ int kap = NO; /* semaphore for KAP/EPC preprocessor */ int kapf = NO; /* semaphore for KAP/EPC preprocessor -f option */ int kapl = NO; /* semaphore for KAP/EPC preprocessor -l option */ char **liblist; char *entryroute; char tempsource[200]; /* holds new .f filename for files passed to cpp */ static char partmpfout[20]; static char partmplout[20]; main(argc, argv) int argc; char **argv; { int i,j, c, status; char *setdoto(), *lastchar(), *lastfield(); char *ckalloc(), *copys(); register char *s; char fortfile[20], *t; char buff[100]; int intrupt(); char *CppOptions[MAXNOOPTIONS]; /* for C command line arguments */ char **ptrCppOptions; char **ptr; /* utility ptr to an array of ptrs */ int CppOnly = NO; char *tmpspntr; ptrCppOptions = CppOptions; /* initialise */ /* record original settings for these interrupts */ sigivalue = (int) signal(SIGINT, SIG_IGN) & 01; sigqvalue = (int) signal(SIGQUIT,SIG_IGN) & 01; sighvalue = (int) signal(SIGHUP, SIG_IGN) & 01; sigtvalue = (int) signal(SIGTERM,SIG_IGN) & 01; enbint(intrupt); /* redirect previously undirected interrupts to my routine */ options = '\0'; drive_sdb = 0; /* set to false */ loadargs = (char **) ckalloc( (argc+20) * sizeof(*loadargs) ); /* get more space for loader args */ loadp = loadargs+1; drivername=argv /* First letter of command identifies imp or fortran */; liblist = impliblist; --argc; /* ******* cycle through params ******* */ ++argv; while(argc>0 && argv[0][0]=='-' && argv[0][1]!='\0') { for(s = argv[0]+1 ; *s ; ++s) switch(*s) { case 'w': /* No warnigs or comments */ /* -w77 Suppress warnings about non-standard F77*/ /* features. likewise any extentions */ *fflagp++='-'; *fflagp++= *s; *fflagp++=' '; break; case 'S': /* code listing (sun native, gcf, and Clan) */ /* available with 68020 code generators */ case 'a': /* cross reference */ *fflagp++='-'; *fflagp++= *s; *fflagp++=' '; /* a */ break; case 'u': /* default variable type is undefined */ case 'q': /* code listing */ case 'x': /* inhibit instruction scheduling */ copyfflag: *fflagp++='-'; *fflagp++= *s; *fflagp++=' '; break; case 'k': /* KAP/EPC preprocessor options */ case 'K': s++; if ((checkif("pic", s, 0)==YES) || checkif("PIC", s ,0)==YES) { *fflagp++= '-'; *fflagp++=*s++; *fflagp++=*s++; *fflagp++=*s; *fflagp++= '+'; *fflagp++=' '; break; } s--; goto copylflag; case 'G': /* Listing switched on */ *fflagp++='-'; *fflagp++= *s; *fflagp++=' '; if (s[1] == '1' || s[1] == '2') { *s++; goto copylflag; } break; case 'h': /* Pass on Heap option to ld */ lflag[1] = *s; lflag[2] = '\0'; *loadp++ = copys(lflag); argv++; argc--; /* go to next parameter for size */ s = argv[0]; /* map s onto next parameter */ j = 0; while (isdigit(*s)) /* cycle through decimal size */ { lflag[j] = *s++; /* copy each digit */ j++; } lflag[j] = '\0'; *loadp++ = copys(lflag); /* pass whole thing to ld */ lflag[0] = '-'; lflag[1] = '\0'; lflag[2] = '\0'; goto endfor; case 'g': /* SDB flag */ *fflagp++ = '-'; *fflagp++ = 'g'; *fflagp++=' '; drive_sdb = 1; break; case 'O': optflag= YES; *fflagp++ = '-'; *fflagp++ = 'O'; *fflagp++ = 'X'; *fflagp++ = ' '; break; case 'P': /* FULL WORD OPTIONS */ if (options) { tmpspntr = (char *)malloc(strlen(options) + strlen(*++argv) + 2); if (tmpspntr == NULL) { fprintf(stderr, "Malloc failed!\n"); exit(1); } strcpy(tmpspntr, options); strcat(tmpspntr, ","); strcat(tmpspntr, *argv); options = tmpspntr; } else options = *++argv; --argc; break; case 'c': loadflag = NO; break; case '#': case 'v': /* Report progress through passes */ verbose = YES; debugflag = YES; break; case 'p': profileflag = YES; if ( s[1] == 'l') { profileflag = NO; *fflagp++ = *s++; } if ( s[1] == 't') { profileflag = NO; *fflagp++ = *s++; } goto copyfflag; case 'o': if( ! strcmp(s, "onetrip") ) { *fflagp++ = '1'; goto endfor; } if (argv[1]== NULL) { fprintf(diagfile,"%s: No output file found for '-o' option\n",*drivername); done(1); } aoutname = *++argv; if (dotchar(aoutname) ) --argv; /* save param for re-use. */ else --argc; break; case 'r': /* -r8 double precision */ if ( s[1] == '8' ) { *fflagp++ = *s++; goto copyfflag; } goto copylflag; case 'I': /* Fortran - Default INT size */ /* C - Directories in which to search for files */ if(s[1]=='2' || s[1]=='4' ) /* Fortran */ { *fflagp++ = *s++; goto copyfflag; } else /* C */ { *ptrCppOptions++ = s-1; while (*s != '\0') { *fflagp++ = *s++; } *fflagp++ = '+'; goto endfor; } case 'l': /* letter ell--library */ s[-1] = '-'; *loadp++ = s-1; goto endfor; case 'R': /* RATFOR */ while( *rflagp++ = *++s ) ; *rflagp++ = ' '; goto endfor; case 'M': /* possible loader option */ goto copylflag; case 'm': if (checkif("misalign", s, 0) == YES) { /* for RISC */ if (options) { tmpspntr = (char *)malloc(strlen(options) + 12); if (tmpspntr == NULL) { fprintf(stderr, "Malloc failed!\n"); exit(1); } strcpy(tmpspntr, options); strcat(tmpspntr, ",misalign"); options = tmpspntr; } else options = "misalign"; goto endfor; } if ( checkif ("mp" , s , 0 ) == YES ) { /* mp for parallel processing */ *fflagp++ = *s++; /* m */ *fflagp++ = *s++; /* p */ parallel = YES; goto endfor; } /* For Imp -m means max of everything.Others pass to loader */ *fflagp++ = 'm'; break; copylflag: default: strcpy(&lflag[1],s); /* copy the rest of the option to the loader */ *loadp++ = copys(lflag); goto endfor; } endfor: --argc; ++argv; } if(argc<=0) { /*check for file args*/ printf("%s",*drivername); printf(": No input files specified\n"); done(1); } *fflagp = '\0'; loadargs[0] = ldname; /* *loadp++ = (profileflag ? proffoot : footname); */ *loadp++ = constloaderargs[0]; /* place -dy */ *loadp++ = constloaderargs[1]; /* place /usr/lib/crti.o */ *loadp++ = constloaderargs[2]; /* place /usr/lib/values-Xt.o */ /* on the load line */ /* *loadp++ = footname; */ *loadp++ = (profileflag ? proffoot : footname); /*********** CYCLE THROUGH FILE NAMES **************/ for(i = 0 ; i%s", rflags, infname, fortfile); status = sys(buff); if(status) { erred = YES; rmf(fortfile); break; } if( ! fortonly ) { infname = argv[i] = lastfield(argv[i]); *lastchar(infname) = 'f'; if( docomp(fortrancompiler,argv[i]) ) erred = YES; else { if( nodup(t = setdoto(argv[i])) ) *loadp++ = t; rmf(fortfile); } } break; /* case 'p': */ /* Pascal file */ /* liblist = pascalliblist; */ /* if ( unreadable(argv[i] )) */ /* erred = YES; */ /* else if ( docomp(PASCALCOMPILER ,argv[i]) ) */ /* erred = YES; */ /* else if( nodup(t=setdoto(argv[i])) ) */ /* *loadp++ = t; */ /* break; */ case 'i': /* Imp80 file */ liblist = impliblist; if( unreadable(argv[i]) ) erred = YES; else if( docomp(nimpcompiler,argv[i]) ) erred = YES; else if( nodup(t=setdoto(argv[i])) ) *loadp++ = t; break; case 'f': /* Fortran file */ case 'k': /* Preprocessed KAP file */ if ( CppOnly == YES && c == 'k') { kapf = NO; kapl = NO; break; } if( unreadable(argv[i]) ) { erred = YES; break; } if( docomp(fortrancompiler,argv[i]) ) { erred = YES; break; } if (kap == YES && kapf == NO) unlink(infname); kapf = NO; kapl = NO; if( nodup(t=setdoto(argv[i])) ) *loadp++ = t; break; case 's': /* Assembler file */ if( unreadable(argv[i]) ) { erred = YES; break; } fprintf(diagfile, "%s:\n", argv[i]); if ((c== 'c') && (cflags[0]=='\0')) { if (drive_sdb == YES) copyCparm (cflagp,"-g "); if (optflag == YES) copyCparm (cflagp,"-O "); for (ptr= CppOptions; *ptr!=0; ptr++) { copyCparm (cflagp,*ptr); copyCparm (cflagp," "); } } sprintf(buff, "cc -c %s %s", cflags, argv[i] ); if( sys(buff) ) erred = YES; else if( nodup(t = setdoto(argv[i])) ) *loadp++ = t; break; case 'o': /* LINK in previously compiled objects */ if( nodup(argv[i]) ) *loadp++ = argv[i]; break; default: if( ! strcmp(argv[i], "-o") ) /* Perhaps its a -o option out of place? */ { if (argv[i+1]==NULL) { fprintf(diagfile,"%s: No output file found for '-o' option\n",*drivername); done (1); } aoutname = argv[++i]; } else { *loadp++ = argv[i]; } break; } if(loadflag && !erred) { doload(loadargs, loadp); /* Go on and LOAD if no errors */ } done(erred); } docomp(compiler,source) /* CALL COMPILER CONTROL */ char *compiler; char *source; { char buff[200]; /* Prevent NULL pointer dereference */ if (!options) options = ""; sprintf(buff, "%s %s %s %s",compiler, fflags, source, options); infname = source; if(verbose) fprintf(diagfile, "COMPILE:"); switch( sys(buff) ) /* FORK as per BUFF */ { case 1: goto error; case 0: break; default: goto comperror; } ret: return(0); error: return(1); comperror: fprintf(diagfile, "\ncompiler error.\n"); return(2); } doload(v0, v) register char *v0[], *v[]; { char **p; int waitpid; char temp[100]; int n; int len; for(p = liblist ; *p ; *v++ = *p++); *v++ = "-o"; strcpy(temp , aoutname); if (dotchar(temp)) { len = strlen(temp)-2; temp[len] = '\0'; } *v++ = temp; *v = NULL; if(verbose) fprintf(diagfile, "LOAD:"); if (v0[1]==NULL) { v0[1]= v0[0]; ++v0; } if(debugflag) { for(p = v0 ; p') { if(t[1] == '>') { append = YES; outname = argv+argc; } else { append = NO; outname = argv+argc; } } else argv[argc++] = t; while( !isspace(*t) && *t!='\0' ) ++t; if(*t) { *t++ = '\0'; while( isspace(*t) ) ++t; } } if (argc == 1) return(-1); /* no command */ argv[argc] = 0; /* kick off process */ s = path; t = "/usr/bin/"; while(*t) *s++ = *t++; for(t = argv[1] ; *s++ = *t++ ; ) ; if((waitpid = fork()) == 0) { if(inname) freopen(inname, "r", stdin); /*** the following two lines have been commented out as they cause the error - Termination code 139 to occur if (*outname) freopen(*outname, (append ? "a" : "w"), stdout); ***/ enbint(SIG_DFL); texec(path+9, argv); /* command */ texec(path+4, argv); /* /bin/command */ texec(path , argv); /* /usr/bin/command */ fatalstr("Cannot load %s",path+9); } return( await(waitpid, 0) ); } #include "errno.h" /* modified version from the Shell */ texec(f, av) char *f; char **av; { extern int errno; execvp(f, av+1); if (errno==ENOEXEC) { av[1] = f; execv(shellname, av); fatal("No shell!"); } if (errno==ENOMEM) fatalstr("%s: too large", f); } done(k) int k; { static int recurs = NO; if(recurs == NO) { recurs = YES; } exit(k); } enbint(k) /* Point signals at my INTRUPT routine */ void (*k)(); /* UNLESS already directed */ { if(sigivalue == 0) signal(SIGINT,k); if(sigqvalue == 0) signal(SIGQUIT,k); if(sighvalue == 0) signal(SIGHUP,k); if(sigtvalue == 0) signal(SIGTERM,k); } intrupt() { done(2); } await(waitpid,waitpid2) int waitpid,waitpid2; { int w, status; enbint(SIG_IGN); while ( ((w = wait(&status)) != waitpid) && (w != waitpid2) ) if(w == -1) fatal("bad wait code"); enbint(intrupt); if(status & 0377) { if(status != SIGINT) fprintf(diagfile, "Termination code %d", status); done(3); } return(status>>8); } /* File Name and File Manipulation Routines */ unreadable(s) register char *s; { register FILE *fp; if(fp = fopen(s, "r")) { fclose(fp); return(NO); } else { fprintf(diagfile, "Error: Cannot read file %s\n", s); return(YES); } } rmf(fn) register char *fn; { if(!debugflag && fn!=NULL && *fn!='\0') unlink(fn); } dotchar(s) register char *s; { for( ; *s ; ++s) if(s[0]=='.' && s[1]!='\0' && s[2]=='\0') return( s[1] ); return(NO); } char *lastfield(s) /* returns the last file in a pathname*/ register char *s; { register char *t; for(t = s; *s ; ++s) if(*s == '/') t = s+1; return(t); } char *lastchar(s) register char *s; { while(*s) ++s; return(s-1); } char *setdoto(s) /* replaces string.ext with string.o */ register char *s; { *lastchar(s) = 'o'; return(lastfield(s) ); } char *ckalloc(n) int n; { char *p, *calloc(); if( p = calloc(1, (unsigned) n) ) return(p); fatal("out of memory"); /* NOTREACHED */ } char * copyn(n, s) register int n; register char *s; { register char *p, *q; p = q = ckalloc(n); while(n-- > 0) *q++ = *s++; return(p); } char * copys(s) char *s; { return( copyn( strlen(s)+1 , s) ); } oneof(c,s) register c; register char *s; { while( *s ) if(*s++ == c) return(YES); return(NO); } copyCparm (cparms,option) char *cparms; char *option; { strcpy(cparms,option); cflagp= cflagp+strlen(option); } checkif (option, s , failaction) char *option,*s; int failaction; { char *save = s; int optionl = strlen(option); if (optionl<= strlen(s)+1) { while (*option) { if (*s++ != *option++) goto fail; } return (YES); } fail: if (failaction == 0) return (NO); fprintf (diagfile,"%s: invalid flag -%.*s\n", *drivername, optionl , save); done(1); } nodup(s) char *s; { register char **p; for(p = loadargs ; p < loadp ; ++p) if( !strcmp(*p, s) ) return(NO); return(YES); } static void fatal(t) char *t; { fprintf(diagfile, "Compiler error in file %s: %s\n", infname, t); if(debugflag) abort(); done(1); exit(1); } static fatali(t,d,e) char *t; int d,e; { char buff[100]; sprintf(buff, t, d, e); fatal(buff); } static fatalstr(t, s) char *t, *s; { char buff[100]; sprintf(buff, t, s); fatal(buff); }