home *** CD-ROM | disk | FTP | other *** search
- /*
- * cc -
- *
- * Compile and/or link one or more C, ASM, OBJ files.
- *
- * For DRI/Alcyon/GEM C Compiler
- * Dave Clemans, November 1985
- *
- * History:
- * V1.0 initial release 11/30/85 (dgc)
- * V1.1 update 12/3/85 (dgc)
- * - clean up some code
- * - be able to abort a compile if we think that
- * a phase generated error messages. This itself
- * has problems; some phases print error messages
- * on stdout and some on stderr and from what I
- * can tell this program can only intercept stdout
- * - add a -w flag to stop early aborts because
- * checks based on output line counts might be
- * wrong; it would be much simpler if the compiler
- * phases would just return error codes instead
- * of seemingly always zero
- * - make the max length of a command tail reflect
- * what the system actually supports (256 bytes)
- * - abort run (at the end of the execution of a
- * a compiler phase) if a ^C is typed; ignore any
- * other keypresses
- *
- * The following arguments don't match what you see on typical UNIX
- * versions of "cc" because GEMDOS for some reason seems to lower case
- * command lines.
- *
- * Arguments:
- * *.c C file
- * *.s ASM file
- * *.o OBJECT file
- * * passed as file name to linker
- * -a compile to ASM file (*.s file)
- * -b dir change name of bin directory
- * -c compile to OBJECT file (*.o file)
- * -dname=value define name at preprocessor time
- * -e include in floating point library (ieee version)
- * -f include in floating point library (ffp version)
- * -h(elp) print out a help message, then exit immediately
- * -i dir change default include directory for preprocessor
- * -la compile for gem desk accessory
- * -lg compile for gem desktop
- * -lt compile for tos program (default)
- * -o file put linked output here rather than a.out
- * -p compile to preprocessor output only (*.i file)
- * -q compile to preprocessor output only (on stdout)
- * -r rename output to standard suffix
- * -s strip symbols from linker output
- * -t dir change name of tmp directory
- * -u(sage) print out an usage message, then exit immediately
- * -v verbose output
- * -w ignore possible error messages
- * -x set a debugging flag
- *
- * Temporary or output files created that are not mentioned above:
- * *.i preprocessor output
- * *.tmp temporary file
- * *.68k linker temporary file
- */
- #include "portab.h"
- #include "stdio.h"
- #include "osbind.h"
-
- #define MAXP 25 /* Max number of CPP args */
- #define MAXC 50 /* Max number of C files */
- #define MAXS 25 /* Max number of ASM files */
- #define MAXO 75 /* Max number of OBJECT files */
- #define MAXA 25 /* Max number of other args */
- #define TAIL 128 /* Max size of command tail */
- char *pargs[MAXP],*cargs[MAXC],*sargs[MAXS],*oargs[MAXO],*aargs[MAXA];
- int pcnt,ccnt,scnt,ocnt,acnt;
- char cmdTail[BUFSIZ*2];
- char *ptrCmdTail;
- char cmdName[256];
- char tempFile[256];
-
- int csflag,esflag,eflag,sflag,cflag,fflag,pflag,vflag,gsflag,xflag,asflag;
- int rflag,wflag;
- int returnCode;
- char *outputFile;
- char argSeparator;
-
- struct memList
- {
- struct memList *memPtr;
- char *memString;
- };
- struct memList *memTop,*memBottom;
-
- /*
- * Names of programs to run to do compiles, and names of directories
- * that are special to us.
- *
- * Notes:
- * INCDIR
- * a drive name like "A:", or
- * a fully qualified directory name
- * MUST NOT BE AN EMPTY STRING!
- * BINDIR
- * TMPDIR
- * a drive name like "A:", or
- * a fully qualified directory name ENDING IN A '/', or
- * an empty string
- */
- char *VERSION= "Alcyon/DRI/GEM C Compiler Frontend; V1.1; dgc; 12/3/85";
- char *INCDIR = "A:";
- char *BINDIR = "A:";
- char *TMPDIR = "";
- char *CPP = "CP68.PRG";
- char *C0 = "C068.PRG";
- char *C1 = "C168.PRG";
- char *AS = "AS68.PRG";
- char *LD = "LINK68.PRG";
- char *RELMOD = "RELMOD.PRG";
- char *OSBIND = "OSBIND.O";
- char *CLIB = "GEMLIB";
- char *LIBF = "LIBF";
- char *CSTART = "GEMSTART.O";
- char *ACCSTRT= "ACCSTART.O";
- char *GEMAES = "AESBIND";
- char *GEMVDI = "VDIBIND";
-
- /*
- * Functions that we have to declare return types for early.
- */
- char *stringCopy();
- char *newFileSuffix();
- FILE *fopen();
- FILE *fopenb();
- char *malloc();
-
- /*
- * Let's get going...
- */
- main(argc,argv)
- int argc;
- char *argv[];
- {
- register int i;
- register char *p;
- char *oldf,*newf;
- FILE *ofp,*nfp;
- int cnt,maxarg;
-
- memTop = memBottom = (struct memList *)NULL;
- argSeparator = ' ';
- returnCode = 0;
- pcnt = ccnt = scnt = ocnt = acnt = 0;
- gsflag = xflag = asflag = rflag = wflag = 0;
- csflag = esflag = eflag = sflag = cflag = fflag = pflag = vflag = 0;
- outputFile = "a";
-
- for (i = 1; i < argc; i++)
- { /* go through our arguments */
- p = argv[i];
- switch (*p)
- { /* check for different types of args */
- case '-': /* a flag argument */
- switch (p[1])
- { /* see which flag */
- case 'u': /* print usage statement */
- printf("cc: [flags] files ...\n");
- doExit();
- break;
- case 'h': /* print help statement */
- printf("cc: [flags] files ...\n");
- printf(" files ...\n");
- printf(" *.c C files\n");
- printf(" *.s ASM files\n");
- printf(" *.o OBJECT files\n");
- printf(" others pass to linker\n");
- printf(" flags ...\n");
- printf(" -a compile to *.s file\n");
- printf(" -b dir change bin directory\n");
- printf(" -c compile to *.o file\n");
- printf(" -dname=value define name with value for preprocessor\n");
- printf(" -e floating point (IEEE)\n");
- printf(" -f floating point (FFP)\n");
- printf(" -h(elp) print this message\n");
- printf(" -i dir change include directory\n");
- printf(" -la link as GEM desk accessory\n");
- printf(" -lg link as GEM program\n");
- printf(" -lt link as TOS program\n");
- printf(" -o file put output file here\n");
- printf(" -p preprocessor to *.i file\n");
- printf(" -q preprocessor only to stdout\n");
- printf(" -r rename to standard suffix\n");
- printf(" -s strip symbol table from output\n");
- printf(" -t dir change temp directory\n");
- printf(" -u(sage) print an usage message\n");
- printf(" -v print verbose messages about what is happening\n");
- printf(" -w ignore possible error messages\n");
- printf(" -x cc command debugging output\n");
- printf(" defaults ...\n");
- printf(" BINDIR A: load compiler from here\n");
- printf(" INCDIR A: standard include files here\n");
- printf(" TMPDIR build temp,output files here\n");
- printf(" a.prg output file name\n");
- printf(" output file will ALWAYS have suffix .prg\n");
- printf(" unless -r is specified\n");
- printf(" output file MUST NOT be a directory path\n");
- printf("\n");
- printf(" To use printf, specify -e or -f\n");
- printf(" Typing ^C will interrupt compilation\n");
- doExit();
- break;
- case 'a': /* compile to assembly only */
- csflag++;
- break;
- case 'b': /* new BINDIR */
- if ((i+1) >= argc)
- { /* missing arg */
- fprintf(stderr,"cc: missing arg for -b\n");
- returnCode = -1;
- doExit();
- }
- BINDIR = argv[++i];
- break;
- case 'c': /* compile to object only */
- cflag++;
- break;
- case 'd': /* define preprocessor name */
- pargs[pcnt++] = argv[i];
- if (pcnt >= MAXP)
- { /* out of space */
- fprintf(stderr,"cc: out of p arg space\n");
- returnCode = -1;
- doExit();
- }
- break;
- case 'e': /* ieee floating point */
- eflag++;
- break;
- case 'f': /* link in floating point */
- fflag++;
- break;
- case 'i': /* include directory */
- if ((i+1) >= argc)
- { /* missing arg */
- fprintf(stderr,"cc: missing arg for -i\n");
- returnCode = -1;
- doExit();
- }
- INCDIR = argv[++i];
- break;
- case 'l': /* change link options */
- switch (p[2])
- { /* see which option */
- case 'a': /* desk accessory */
- asflag++;
- gsflag++;
- break;
- case 'g': /* gem */
- gsflag++;
- break;
- case 't': /* tos */
- asflag = 0;
- gsflag = 0;
- break;
- default:
- fprintf(stderr,"cc: bad -l arg\n");
- returnCode = -1;
- doExit();
- }
- break;
- case 'o': /* new output filename */
- if ((i+1) >= argc)
- { /* missing arg */
- fprintf(stderr,"cc: missing arg for -o\n");
- returnCode = -1;
- doExit();
- }
- outputFile = argv[++i];
- for (p = outputFile; *p; p++)
- if (*p == '.')
- *p = '\0';
- for (p = outputFile; *p; p++)
- continue;
- for (; p > outputFile; p--)
- if ((*p == ':') || (*p == '\\') || (*p == '/'))
- break;
- if (p > outputFile)
- outputFile = p+1;
- break;
- case 'p': /* preprocessor output */
- pflag++;
- break;
- case 'q': /* cpp output only */
- esflag++;
- break;
- case 'r': /* rename to standard suffix */
- rflag++;
- break;
- case 's': /* strip out linker symbols */
- sflag++;
- break;
- case 't': /* new TMPDIR */
- if ((i+1) >= argc)
- { /* missing arg */
- fprintf(stderr,"cc: missing arg for -t\n");
- returnCode = -1;
- doExit();
- }
- TMPDIR = argv[++i];
- break;
- case 'v': /* verbose output */
- vflag++;
- break;
- case 'w': /* ignore possible error messages */
- wflag++;
- break;
- case 'x': /* some debugging output */
- xflag++;
- break;
- default: /* unknown arg; pass to ld */
- aargs[acnt++] = argv[i];
- if (acnt >= MAXA)
- { /* out of space */
- fprintf(stderr,"cc: out of a arg space\n");
- returnCode = -1;
- doExit();
- }
- break;
- }
- break;
- default: /* a filename */
- while (*p != '\0') p++;
- if ((*(p-2) != '.') ||
- ((*(p-2) == '.') &&
- (*(p-1) != 'c') &&
- (*(p-1) != 's') &&
- (*(p-1) != 'o')))
- { /* just pass through to linker */
- aargs[acnt++] = argv[i];
- if (acnt >= MAXA)
- { /* out of space */
- fprintf(stderr,"cc: out of a arg space\n");
- returnCode = -1;
- doExit();
- }
- break;
- }
- switch (*(p-1))
- { /* which file type? */
- case 'c': /* C file */
- cargs[ccnt++] = argv[i];
- cnt = ccnt;
- maxarg = MAXC;
- break;
- case 's': /* ASM file */
- sargs[scnt++] = argv[i];
- cnt = scnt;
- maxarg = MAXS;
- break;
- case 'o': /* OBJECT file */
- oargs[ocnt++] = argv[i];
- cnt = ocnt;
- maxarg = MAXO;
- break;
- }
- if (cnt >= maxarg)
- { /* out of arg space */
- fprintf(stderr,"cc: out of arg space\n");
- returnCode = -1;
- doExit();
- }
- break;
- }
- }
- if (vflag)
- printf("%s\n",VERSION);
-
- /*
- * Start compiling C files...
- */
- for (i = 0; i < ccnt; i++)
- { /* go through our C files */
- if ((ccnt > 1) || vflag)
- printf("%s:\n",cargs[i]);
- compileFile(cargs[i]);
- }
- if (esflag || csflag || pflag || (returnCode != 0))
- doExit();
-
- /*
- * Do any necessary assemblies...
- */
- for (i = 0; i < scnt; i++)
- { /* go through our ASM files */
- if ((scnt > 1) || vflag)
- printf("%s:\n",sargs[i]);
- assembleFile(sargs[i]);
- }
- if (cflag || (returnCode != 0))
- doExit();
-
- /*
- * Link everything together...
- */
- linkFiles();
- for (i = 0; i < ccnt; i++)
- removeFile(newFileSuffix(cargs[i],'o'));
- for (i = 0; i < scnt; i++)
- removeFile(newFileSuffix(sargs[i],'o'));
-
- /*
- * Put output file in good place if necessary
- */
- if (strlen(TMPDIR) > 0)
- { /* do if TMPDIR was specified */
- sprintf(tempFile,"%s%s.prg",TMPDIR,outputFile);
- oldf = stringCopy(tempFile);
- if (rflag)
- { /* pick standard suffix */
- if (asflag)
- sprintf(tempFile,"%s.acc",outputFile);
- else if (gsflag)
- sprintf(tempFile,"%s.prg",outputFile);
- else sprintf(tempFile,"%s.ttp",outputFile);
- }
- else sprintf(tempFile,"%s.prg",outputFile);
- newf = stringCopy(tempFile);
- if (vflag)
- printf("+ copy %s %s\n",oldf,newf);
- removeFile(newf);
- i = creatb(newf,0644);
- if (i < 0)
- { /* no file? */
- fprintf(stderr,"cc: can't open %s\n",newf);
- returnCode = -1;
- doExit();
- }
- close(i);
- nfp = fopenb(newf,"w");
- if (nfp == (FILE *)NULL)
- { /* no file? */
- fprintf(stderr,"cc: can't make %s\n",newf);
- returnCode = -1;
- doExit();
- }
- ofp = fopenb(oldf,"r");
- if (ofp == (FILE *)NULL)
- { /* no file? */
- fprintf(stderr,"cc: can't open program %s\n",oldf);
- returnCode = -1;
- doExit();
- }
- while ((i = fread(cmdTail,1,BUFSIZ,ofp)) > 0)
- fwrite(cmdTail,1,i,nfp);
- fclose(ofp);
- fclose(nfp);
- removeFile(oldf);
- }
- else if (rflag && !asflag && !gsflag)
- { /* we only have to rename file to get right suffix */
- sprintf(tempFile,"%s%s.prg",TMPDIR,outputFile);
- oldf = stringCopy(tempFile);
- if (asflag)
- sprintf(tempFile,"%s.acc",outputFile);
- else sprintf(tempFile,"%s.ttp",outputFile);
- if (Frename(0,oldf,tempFile) != 0)
- { /* rename didn't work... */
- fprintf(stderr,"cc: rename of %s to %s failed\n",oldf,tempFile);
- returnCode = -1;
- doExit();
- }
- }
-
- /*
- * And return to the user
- */
- doExit();
- }; /* end of main */
-
- /*
- * Exit with our recorded return code
- */
- doExit()
- {
- register struct memList *ml,*sml;
-
- if (xflag)
- printf("cc: doExit: freeing memory\n");
- for (ml = memTop; ml != (struct memList *)NULL; )
- { /* free our allocated memory */
- sml = ml;
- ml = ml->memPtr;
- free(sml->memString);
- free(sml);
- }
- if (xflag)
- printf("cc: doExit: returning to system\n");
- exit(returnCode);
- }; /* end of doExit */
-
- /*
- * Allocate some memory, and save it's location so that we can find
- * it later.
- */
- char *getMemory(size)
- int size;
- {
- register struct memList *ml;
- register char *cp;
- struct memList xm;
-
- if (xflag)
- printf("cc: getMemory: allocating memory s=%d,l=%d\n",
- size,(sizeof xm));
- cp = (char *)malloc(size);
- ml = (struct memList *)malloc(sizeof xm);
- if ((cp == (char *)NULL) || (ml == (struct memList *)NULL))
- { /* out of memory */
- if (cp != (char *)NULL)
- free(cp);
- if (ml != (struct memList *)NULL)
- free(ml);
- return((char *)NULL);
- }
- if (xflag)
- printf("cc: getMemory: saving memory in list cp=%lx,ml=%lx\n",
- cp,ml);
- ml->memString = cp;
- ml->memPtr = (struct memList *)NULL;
- if (memTop == (struct memList *)NULL)
- memTop = memBottom = ml;
- else
- { /* tack onto bottom */
- memBottom->memPtr = ml;
- memBottom = ml;
- }
- if (xflag)
- printf("cc: getMemory: memory list modified\n");
- return(cp);
- }; /* end of getMemory */
-
- /*
- * Remove an unwanted file
- */
- removeFile(file)
- char *file;
- {
- if (xflag)
- printf("cc: removeFile: deleting %s\n",file);
- Fdelete(file);
- }; /* end of removeFile */
-
- /*
- * Make a copy of a string
- */
- char *stringCopy(string,xlen)
- char *string;
- int xlen;
- {
- register char *s,*os;
- register int size;
-
- if (xflag)
- printf("cc: stringCopy: copying '%s'\n",string);
- os = string;
- size = strlen(os)+1+xlen;
- s = getMemory(size);
- if (s == (char *)NULL)
- { /* out of space */
- fprintf(stderr,"cc: out of space (malloc failed)\n");
- returnCode = -1;
- doExit();
- }
- strcpy(s,os);
- if (xflag)
- printf("cc: stringCopy: copy complete\n");
- return(s);
- }; /* end of stringCopy */
-
- /*
- * Return a copy of a filename, but with a new suffix char
- */
- char *newFileSuffix(file,suffix)
- char *file;
- char suffix;
- {
- register char *p;
- register char *f;
- char *newFile;
-
- if (xflag)
- printf("cc: newFileSuffix: copying '%s' with suffix '%c'\n",
- file,suffix);
-
- /* isolate out the leaf name of the file */
- for (f = file; *f; f++)
- continue;
- while ((f > file) && (*f != '/') && (*f != ':'))
- f--;
- if (f > file)
- f++;
-
- /* make a copy of it and change the last character ("the suffix") */
- p = newFile = stringCopy(f,strlen(TMPDIR));
- strcpy(p,TMPDIR);
- strcat(p,f);
- while (*p) p++;
- *--p = suffix;
- return(newFile);
- }; /* end of newFileSuffix */
-
- /*
- * Make a temporary file name
- */
- char *makeTempFile()
- {
- static int seed;
-
- sprintf(tempFile,"%st%d.tmp",TMPDIR,seed++);
- if (xflag)
- printf("cc: makeTempFile: generating %s\n",tempFile);
- return(stringCopy(tempFile,0));
- }; /* end of makeTempFile */
-
- /*
- * Compile a file
- */
- int compileFile(file)
- char *file;
- {
- register int i;
- char *cppOutput,*ctemp1,*ctemp2,*ctemp3,*ccOutput,*asOutput;
-
- if (xflag)
- printf("cc: compileFile: compiling %s\n",file);
-
- if (pflag)
- cppOutput = newFileSuffix(file,'i');
- else cppOutput = makeTempFile();
- ccOutput = newFileSuffix(file,'s');
- asOutput = newFileSuffix(file,'o');
- ctemp1 = makeTempFile();
- ctemp2 = makeTempFile();
- ctemp3 = makeTempFile();
-
- if (xflag)
- printf("cc: compileFile: have temp files\n");
-
- resetCmdTail();
- for (i = 0; i < pcnt; i++)
- addtoCmdTail(pargs[i]);
- addtoCmdTail("-i");
- addtoCmdTail(INCDIR);
- if (esflag || pflag)
- addtoCmdTail("-p");
- if (esflag)
- addtoCmdTail("-e");
- addtoCmdTail(file);
- addtoCmdTail(cppOutput);
- if (execute(CPP,0))
- { /* if something bad happened */
- returnCode = -1;
- removeFile(cppOutput);
- return(-1);
- }
- if (esflag || pflag)
- { /* nothing else to do for this file */
- return(0);
- }
-
- resetCmdTail();
- addtoCmdTail(cppOutput);
- addtoCmdTail(ctemp1);
- addtoCmdTail(ctemp2);
- addtoCmdTail(ctemp3);
- if (fflag)
- addtoCmdTail("-f");
- else if (eflag)
- addtoCmdTail("-e");
- if (execute(C0,0))
- { /* if something bad happened */
- returnCode = -1;
- removeFile(cppOutput);
- removeFile(ctemp1);
- removeFile(ctemp2);
- removeFile(ctemp3);
- return(-1);
- }
- removeFile(cppOutput);
- removeFile(ctemp3);
-
- resetCmdTail();
- addtoCmdTail(ctemp1);
- addtoCmdTail(ctemp2);
- addtoCmdTail(ccOutput);
- if (execute(C1,0))
- { /* if something bad happened */
- returnCode = -1;
- removeFile(ctemp1);
- removeFile(ctemp2);
- removeFile(ccOutput);
- return(-1);
- }
- removeFile(ctemp1);
- removeFile(ctemp2);
- if (csflag)
- return(0);
-
- resetCmdTail();
- addtoCmdTail("-l");
- addtoCmdTail("-u");
- addtoCmdTail("-s");
- sprintf(tempFile,"%sAS68SYMB.DAT",BINDIR);
- addtoCmdTail(tempFile);
- if (strlen(TMPDIR) > 0)
- { /* redirect temp files */
- addtoCmdTail("-f");
- addtoCmdTail(TMPDIR);
- }
- addtoCmdTail(ccOutput);
- if (execute(AS,0))
- { /* if something bad happened */
- returnCode = -1;
- removeFile(ccOutput);
- removeFile(asOutput);
- return(-1);
- }
- removeFile(ccOutput);
- return(0);
- }; /* end of compileFile */
-
- /*
- * Assemble a file
- */
- int assembleFile(file)
- char *file;
- {
- register char *asOutput;
-
- if (xflag)
- printf("cc: assembleFile: assembling %s\n",file);
-
- asOutput = newFileSuffix(file,'o');
- resetCmdTail();
- addtoCmdTail("-l -u");
- addtoCmdTail(file);
- if (execute(AS,0))
- { /* if something bad happened */
- returnCode = -1;
- removeFile(asOutput);
- return(-1);
- }
- return(0);
- }; /* end of assembleFile */
-
- /*
- * Link everything together into one file
- */
- linkFiles()
- {
- register int i;
- register char *cp;
- register int counter;
- FILE *fp;
- char *ldtemp;
-
- if (xflag)
- printf("cc: linkFiles: entering\n");
-
- ldtemp = makeTempFile();
- removeFile(ldtemp);
- i = creat(ldtemp,2);
- if (i < 0)
- { /* no temp file for us to play with? */
- fprintf(stderr,"cc: can't open ld temp file '%s'\n",ldtemp);
- returnCode = -1;
- return(-1);
- }
- close(i);
- fp = fopen(ldtemp,"w");
- if (!fp)
- { /* no temp file for us to play with? */
- fprintf(stderr,"cc: can't open ld temp file '%s'\n",ldtemp);
- returnCode = -1;
- return(-1);
- }
- resetCmdTail();
- argSeparator = ',';
- addtoCmdTail("[u");
- if (!sflag)
- addtoCmdTail("s");
- if (strlen(TMPDIR) > 0)
- { /* redirect temp files */
- sprintf(tempFile,"tem[%s]",TMPDIR);
- addtoCmdTail(tempFile);
- }
- *--ptrCmdTail = ']';
- *++ptrCmdTail = ' ';
- *++ptrCmdTail = '\0';
- argSeparator = '=';
- sprintf(tempFile,"%s%s.68k",TMPDIR,outputFile);
- addtoCmdTail(tempFile);
- argSeparator = ',';
- strcpy(cmdName,BINDIR);
- if (!asflag)
- strcat(cmdName,CSTART);
- else strcat(cmdName,ACCSTRT);
- addtoCmdTail(cmdName);
- *--ptrCmdTail = '\0';
- sprintf(cmdName,"[CO[%s]], ",ldtemp);
- strcat(cmdTail,cmdName);
- while (*ptrCmdTail)
- ptrCmdTail++;
- fputc(',',fp);
- counter = 7;
- for (i = 0; i < ccnt; i++)
- { /* C files */
- cp = newFileSuffix(cargs[i],'o');
- fprintf(fp,"%s,\n",cp);
- counter++;
- }
- for (i = 0; i < scnt; i++)
- { /* ASM files */
- cp = newFileSuffix(sargs[i],'o');
- fprintf(fp,"%s,\n",cp);
- counter++;
- }
- for (i = 0; i < ocnt; i++)
- { /* O files */
- fprintf(fp,"%s,\n",oargs[i]);
- counter++;
- }
- for (i = 0; i < acnt; i++)
- { /* other args */
- fprintf(fp,"%s,\n",aargs[i]);
- counter++;
- }
- if (gsflag)
- { /* link for gem */
- strcpy(cmdName,BINDIR);
- strcat(cmdName,GEMAES);
- fprintf(fp,"%s,\n",cmdName);
- counter++;
- strcpy(cmdName,BINDIR);
- strcat(cmdName,GEMVDI);
- fprintf(fp,"%s,\n",cmdName);
- counter++;
- }
- strcpy(cmdName,BINDIR);
- strcat(cmdName,OSBIND);
- fprintf(fp,"%s,\n",cmdName);
- counter++;
- strcpy(cmdName,BINDIR);
- strcat(cmdName,CLIB);
- if (eflag || fflag)
- { /* add in floating point library */
- fprintf(fp,"%s,\n",cmdName);
- counter++;
- strcpy(cmdName,BINDIR);
- strcat(cmdName,LIBF);
- }
- fprintf(fp,"%s\n",cmdName);
- counter++;
- fclose(fp);
- if (execute(LD,counter))
- { /* if something bad happened */
- returnCode = -1;
- removeFile(tempFile);
- removeFile(ldtemp);
- return(-1);
- }
- removeFile(ldtemp);
-
- argSeparator = ' ';
- resetCmdTail();
- addtoCmdTail(TMPDIR);
- ptrCmdTail--;
- addtoCmdTail(outputFile);
- if (execute(RELMOD,0))
- { /* if something bad happened */
- returnCode = -1;
- removeFile(tempFile);
- return(-1);
- }
- removeFile(tempFile);
- return(0);
- }; /* end of linkFiles */
-
- /*
- * Since we always execute commands underneath us the same way,
- * one common routine is used to set things up and then call the
- * more general execution routine "runCommand"
- *
- * Zero is returned if everything probably succeeded, and non-zero
- * if not. This includes making sure that the command doesn't generate
- * any more output than we expect.
- *
- * The command tail should be completely set up by the time this
- * routine is called.
- */
- int execute(command,expectedOutput)
- char *command;
- int expectedOutput;
- {
- register int rc;
- register int outputLines;
- char *tempOutput;
- int character;
-
- if (xflag)
- printf("cc: execute: run cmd=%s,lines=%d\n",command,expectedOutput);
-
- tempOutput = makeTempFile();
- *ptrCmdTail++ = '>';
- *ptrCmdTail = '\0';
- addtoCmdTail(tempOutput);
- rc = runCommand(command);
- outputLines = copyToStderr(tempOutput,expectedOutput);
- removeFile(tempOutput);
- if ((rc != 0) && (outputLines == 0))
- fprintf(stderr,"cc: bad return from executing %s\n",command);
-
- if (Bconstat(2))
- { /* if input waiting */
- character = Bconin(2);
- if ((character & 0xFF) == 0x03)
- { /* if a ^C */
- fprintf(stderr,"cc: compilation aborted by ^C interrupt\n");
- fprintf(stderr,"cc: existing temp files won't be removed\n");
- returnCode = -1;
- doExit();
- }
- }
-
- if (((outputLines != 0) && !wflag) || (rc != 0))
- return(-1); /* if an error was found */
- else return(0); /* everything probably worked */
- }; /* end of execute */
-
- /*
- * Copy a the contents of a specified file to our standard error stream,
- * after possibly skipping some lines at the beginning of the file.
- * Return the number of lines actually printed, or -1 if the file could
- * not be opened.
- */
- int copyToStderr(file,skip)
- char *file;
- int skip;
- {
- register FILE *fp;
- register int count;
- char line[BUFSIZ];
-
- if (xflag)
- printf("cc: copyToStderr: entering file=%s,skip=%d\n",file,skip);
-
- fp = fopen(file,"r");
- if (fp == (FILE *)NULL)
- { /* file not usable */
- return(-1);
- }
-
- count = 0;
- while (fgets(line,sizeof line,fp) != NULL)
- { /* go through the file */
- if (++count <= skip)
- continue;
- fputs(line,stderr);
- }
- fclose(fp);
-
- return(count - skip);
- }; /* end of copyToStderr */
-
- /*
- * Empty out our argument buffer
- */
- resetCmdTail()
- {
- if (xflag)
- printf("cc: resetCmdTail: entering\n");
- ptrCmdTail = cmdTail;
- *ptrCmdTail++ = ' ';
- *ptrCmdTail = '\0';
- }; /* end of resetCmdTail */
-
- /*
- * Add an argument to our buffer
- */
- addtoCmdTail(arg)
- char *arg;
- {
- if (xflag)
- printf("cc: addtoCmdTail: adding %s\n",arg);
- while (*arg)
- { /* Copy the argument */
- *ptrCmdTail++ = *arg++;
- if (ptrCmdTail >&cmdTail[TAIL-3])
- { /* out of space */
- fprintf(stderr,"cc: out of cmd tail space\n");
- returnCode = -1;
- doExit();
- }
- }
- *ptrCmdTail++ = argSeparator;
- *ptrCmdTail = '\0';
- }; /* end of addtoCmdTail */
-
- /*
- * Run a given command using the argument buffer that MUST
- * have been setup previously.
- */
- int runCommand(cmd)
- char *cmd;
- {
- register int rc,len;
-
- cmdName[0] = '\0';
- strcpy(cmdName,BINDIR);
- strcat(cmdName,cmd);
- if (*--ptrCmdTail != argSeparator)
- ptrCmdTail++;
- *ptrCmdTail = '\0';
- if (vflag)
- printf("+ %s %s\n",cmdName,cmdTail);
- len = strlen(cmdTail) - 1;
- cmdTail[0] = (char)len;
- rc = Pexec(0,cmdName,cmdTail,(char *)0);
- resetCmdTail();
- return(rc);
- }; /* end of runCommand */