home *** CD-ROM | disk | FTP | other *** search
/ SPACE 1 / SPACE - Library 1 - Volume 1.iso / misc~1 / 4 / cc.c next >
Encoding:
C/C++ Source or Header  |  1986-02-25  |  25.3 KB  |  1,033 lines

  1. /*
  2.  * cc -
  3.  *
  4.  * Compile and/or link one or more C, ASM, OBJ files.
  5.  *
  6.  * For DRI/Alcyon/GEM C Compiler
  7.  * Dave Clemans, November 1985
  8.  *
  9.  * History:
  10.  *    V1.0        initial release 11/30/85 (dgc)
  11.  *    V1.1        update 12/3/85 (dgc)
  12.  *            - clean up some code
  13.  *            - be able to abort a compile if we think that
  14.  *            a phase generated error messages.  This itself
  15.  *            has problems; some phases print error messages
  16.  *            on stdout and some on stderr and from what I
  17.  *            can tell this program can only intercept stdout
  18.  *            - add a -w flag to stop early aborts because
  19.  *            checks based on output line counts might be
  20.  *            wrong; it would be much simpler if the compiler
  21.  *            phases would just return error codes instead
  22.  *            of seemingly always zero
  23.  *            - make the max length of a command tail reflect
  24.  *            what the system actually supports (256 bytes)
  25.  *            - abort run (at the end of the execution of a
  26.  *            a compiler phase) if a ^C is typed; ignore any
  27.  *            other keypresses
  28.  *
  29.  * The following arguments don't match what you see on typical UNIX
  30.  * versions of "cc" because GEMDOS for some reason seems to lower case
  31.  * command lines.
  32.  *
  33.  * Arguments:
  34.  *    *.c        C file
  35.  *    *.s        ASM file
  36.  *    *.o        OBJECT file
  37.  *    *        passed as file name to linker
  38.  *    -a        compile to ASM file (*.s file)
  39.  *    -b dir        change name of bin directory
  40.  *    -c        compile to OBJECT file (*.o file)
  41.  *    -dname=value    define name at preprocessor time
  42.  *    -e        include in floating point library (ieee version)
  43.  *    -f        include in floating point library (ffp version)
  44.  *    -h(elp)        print out a help message, then exit immediately
  45.  *    -i dir        change default include directory for preprocessor
  46.  *    -la        compile for gem desk accessory
  47.  *    -lg        compile for gem desktop
  48.  *    -lt        compile for tos program (default)
  49.  *    -o file        put linked output here rather than a.out
  50.  *    -p        compile to preprocessor output only (*.i file)
  51.  *    -q        compile to preprocessor output only (on stdout)
  52.  *    -r        rename output to standard suffix
  53.  *    -s        strip symbols from linker output
  54.  *    -t dir        change name of tmp directory
  55.  *    -u(sage)    print out an usage message, then exit immediately
  56.  *    -v        verbose output
  57.  *    -w        ignore possible error messages
  58.  *    -x        set a debugging flag
  59.  *
  60.  * Temporary or output files created that are not mentioned above:
  61.  *    *.i        preprocessor output
  62.  *    *.tmp        temporary file
  63.  *    *.68k        linker temporary file
  64.  */
  65. #include "portab.h"
  66. #include "stdio.h"
  67. #include "osbind.h"
  68.  
  69. #define    MAXP    25    /* Max number of CPP args */
  70. #define    MAXC    50    /* Max number of C files */
  71. #define    MAXS    25    /* Max number of ASM files */
  72. #define    MAXO    75    /* Max number of OBJECT files */
  73. #define    MAXA    25    /* Max number of other args */
  74. #define    TAIL    128    /* Max size of command tail */
  75. char    *pargs[MAXP],*cargs[MAXC],*sargs[MAXS],*oargs[MAXO],*aargs[MAXA];
  76. int    pcnt,ccnt,scnt,ocnt,acnt;
  77. char    cmdTail[BUFSIZ*2];
  78. char    *ptrCmdTail;
  79. char    cmdName[256];
  80. char    tempFile[256];
  81.  
  82. int    csflag,esflag,eflag,sflag,cflag,fflag,pflag,vflag,gsflag,xflag,asflag;
  83. int    rflag,wflag;
  84. int    returnCode;
  85. char    *outputFile;
  86. char    argSeparator;
  87.  
  88. struct    memList
  89. {
  90.     struct memList *memPtr;
  91.     char *memString;
  92. };
  93. struct    memList *memTop,*memBottom;
  94.  
  95. /*
  96.  * Names of programs to run to do compiles, and names of directories
  97.  * that are special to us.
  98.  *
  99.  * Notes:
  100.  *    INCDIR
  101.  *        a drive name like "A:", or
  102.  *        a fully qualified directory name
  103.  *        MUST NOT BE AN EMPTY STRING!
  104.  *    BINDIR
  105.  *    TMPDIR
  106.  *        a drive name like "A:", or
  107.  *        a fully qualified directory name ENDING IN A '/', or
  108.  *        an empty string
  109.  */
  110. char    *VERSION= "Alcyon/DRI/GEM C Compiler Frontend; V1.1; dgc; 12/3/85";
  111. char    *INCDIR    = "A:";
  112. char    *BINDIR    = "A:";
  113. char    *TMPDIR = "";
  114. char    *CPP    = "CP68.PRG";
  115. char    *C0    = "C068.PRG";
  116. char    *C1    = "C168.PRG";
  117. char    *AS    = "AS68.PRG";
  118. char    *LD    = "LINK68.PRG";
  119. char    *RELMOD    = "RELMOD.PRG";
  120. char    *OSBIND    = "OSBIND.O";
  121. char    *CLIB    = "GEMLIB";
  122. char    *LIBF    = "LIBF";
  123. char    *CSTART    = "GEMSTART.O";
  124. char    *ACCSTRT= "ACCSTART.O";
  125. char    *GEMAES    = "AESBIND";
  126. char    *GEMVDI    = "VDIBIND";
  127.  
  128. /*
  129.  * Functions that we have to declare return types for early.
  130.  */
  131. char    *stringCopy();
  132. char    *newFileSuffix();
  133. FILE    *fopen();
  134. FILE    *fopenb();
  135. char    *malloc();
  136.  
  137. /*
  138.  * Let's get going...
  139.  */
  140. main(argc,argv)
  141. int argc;
  142. char *argv[];
  143. {
  144.     register int i;
  145.     register char *p;
  146.     char *oldf,*newf;
  147.     FILE *ofp,*nfp;
  148.     int cnt,maxarg;
  149.  
  150.     memTop = memBottom = (struct memList *)NULL;
  151.     argSeparator = ' ';
  152.     returnCode = 0;
  153.     pcnt = ccnt = scnt = ocnt = acnt = 0;
  154.     gsflag = xflag = asflag = rflag = wflag = 0;
  155.     csflag = esflag = eflag = sflag = cflag = fflag = pflag = vflag = 0;
  156.     outputFile = "a";
  157.  
  158.     for (i = 1; i < argc; i++)
  159.     {    /* go through our arguments */
  160.         p = argv[i];
  161.         switch (*p)
  162.         {    /* check for different types of args */
  163.             case '-':    /* a flag argument */
  164.             switch (p[1])
  165.             {    /* see which flag */
  166.                 case 'u':    /* print usage statement */
  167.                 printf("cc: [flags] files ...\n");
  168.                 doExit();
  169.                 break;
  170.                 case 'h':    /* print help statement */
  171.                 printf("cc: [flags] files ...\n");
  172.                 printf("  files ...\n");
  173.                 printf("    *.c     C files\n");
  174.                 printf("    *.s     ASM files\n");
  175.                 printf("    *.o     OBJECT files\n");
  176.                 printf("    others  pass to linker\n");
  177.                 printf("  flags ...\n");
  178.                 printf("    -a      compile to *.s file\n");
  179.                 printf("    -b dir  change bin directory\n");
  180.                 printf("    -c      compile to *.o file\n");
  181.                 printf("    -dname=value define name with value for preprocessor\n");
  182.                 printf("    -e      floating point (IEEE)\n");
  183.                 printf("    -f      floating point (FFP)\n");
  184.                 printf("    -h(elp) print this message\n");
  185.                 printf("    -i dir  change include directory\n");
  186.                 printf("    -la     link as GEM desk accessory\n");
  187.                 printf("    -lg     link as GEM program\n");
  188.                 printf("    -lt     link as TOS program\n");
  189.                 printf("    -o file put output file here\n");
  190.                 printf("    -p      preprocessor to *.i file\n");
  191.                 printf("    -q      preprocessor only to stdout\n");
  192.                 printf("    -r      rename to standard suffix\n");
  193.                 printf("    -s      strip symbol table from output\n");
  194.                 printf("    -t dir  change temp directory\n");
  195.                 printf("    -u(sage) print an usage message\n");
  196.                 printf("    -v      print verbose messages about what is happening\n");
  197.                 printf("    -w      ignore possible error messages\n");
  198.                 printf("    -x      cc command debugging output\n");
  199.                 printf("  defaults ...\n");
  200.                 printf("    BINDIR  A:  load compiler from here\n");
  201.                 printf("    INCDIR  A:  standard include files here\n");
  202.                 printf("    TMPDIR      build temp,output files here\n");
  203.                 printf("    a.prg       output file name\n");
  204.                 printf("                output file will ALWAYS have suffix .prg\n");
  205.                 printf("                  unless -r is specified\n");
  206.                 printf("        output file MUST NOT be a directory path\n");
  207.                 printf("\n");
  208.                 printf("    To use printf, specify -e or -f\n");
  209.                 printf("    Typing ^C will interrupt compilation\n");
  210.                 doExit();
  211.                 break;
  212.                 case 'a':    /* compile to assembly only */
  213.                 csflag++;
  214.                 break;
  215.                 case 'b':    /* new BINDIR */
  216.                 if ((i+1) >= argc)
  217.                 {    /* missing arg */
  218.                     fprintf(stderr,"cc: missing arg for -b\n");
  219.                     returnCode = -1;
  220.                     doExit();
  221.                 }
  222.                 BINDIR = argv[++i];
  223.                 break;
  224.                 case 'c':    /* compile to object only */
  225.                 cflag++;
  226.                 break;
  227.                 case 'd':    /* define preprocessor name */
  228.                 pargs[pcnt++] = argv[i];
  229.                 if (pcnt >= MAXP)
  230.                 {    /* out of space */
  231.                     fprintf(stderr,"cc: out of p arg space\n");
  232.                     returnCode = -1;
  233.                     doExit();
  234.                 }
  235.                 break;
  236.                 case 'e':    /* ieee floating point */
  237.                 eflag++;
  238.                 break;
  239.                 case 'f':    /* link in floating point */
  240.                 fflag++;
  241.                 break;
  242.                 case 'i':    /* include directory */
  243.                 if ((i+1) >= argc)
  244.                 {    /* missing arg */
  245.                     fprintf(stderr,"cc: missing arg for -i\n");
  246.                     returnCode = -1;
  247.                     doExit();
  248.                 }
  249.                 INCDIR = argv[++i];
  250.                 break;
  251.                 case 'l':    /* change link options */
  252.                 switch (p[2])
  253.                 {    /* see which option */
  254.                     case 'a':    /* desk accessory */
  255.                     asflag++;
  256.                     gsflag++;
  257.                     break;
  258.                     case 'g':    /* gem */
  259.                     gsflag++;
  260.                     break;
  261.                     case 't':    /* tos */
  262.                     asflag = 0;
  263.                     gsflag = 0;
  264.                     break;
  265.                     default:
  266.                     fprintf(stderr,"cc: bad -l arg\n");
  267.                     returnCode = -1;
  268.                     doExit();
  269.                 }
  270.                 break;
  271.                 case 'o':    /* new output filename */
  272.                 if ((i+1) >= argc)
  273.                 {    /* missing arg */
  274.                     fprintf(stderr,"cc: missing arg for -o\n");
  275.                     returnCode = -1;
  276.                     doExit();
  277.                 }
  278.                 outputFile = argv[++i];
  279.                 for (p = outputFile; *p; p++)
  280.                     if (*p == '.')
  281.                         *p = '\0';
  282.                 for (p = outputFile; *p; p++)
  283.                     continue;
  284.                 for (; p > outputFile; p--)
  285.                     if ((*p == ':') || (*p == '\\') || (*p == '/'))
  286.                         break;
  287.                 if (p > outputFile)
  288.                     outputFile = p+1;
  289.                 break;
  290.                 case 'p':    /* preprocessor output */
  291.                 pflag++;
  292.                 break;
  293.                 case 'q':    /* cpp output only */
  294.                 esflag++;
  295.                 break;
  296.                 case 'r':    /* rename to standard suffix */
  297.                 rflag++;
  298.                 break;
  299.                 case 's':    /* strip out linker symbols */
  300.                 sflag++;
  301.                 break;
  302.                 case 't':    /* new TMPDIR */
  303.                 if ((i+1) >= argc)
  304.                 {    /* missing arg */
  305.                     fprintf(stderr,"cc: missing arg for -t\n");
  306.                     returnCode = -1;
  307.                     doExit();
  308.                 }
  309.                 TMPDIR = argv[++i];
  310.                 break;
  311.                 case 'v':    /* verbose output */
  312.                 vflag++;
  313.                 break;
  314.                 case 'w':    /* ignore possible error messages */
  315.                 wflag++;
  316.                 break;
  317.                 case 'x':    /* some debugging output */
  318.                 xflag++;
  319.                 break;
  320.                 default:    /* unknown arg; pass to ld */
  321.                 aargs[acnt++] = argv[i];
  322.                 if (acnt >= MAXA)
  323.                 {    /* out of space */
  324.                     fprintf(stderr,"cc: out of a arg space\n");
  325.                     returnCode = -1;
  326.                     doExit();
  327.                 }
  328.                 break;
  329.             }
  330.             break;
  331.             default:    /* a filename */
  332.             while (*p != '\0') p++;
  333.             if ((*(p-2) != '.') ||
  334.                 ((*(p-2) == '.') &&
  335.                 (*(p-1) != 'c') &&
  336.                 (*(p-1) != 's') &&
  337.                 (*(p-1) != 'o')))
  338.             {    /* just pass through to linker */
  339.                 aargs[acnt++] = argv[i];
  340.                 if (acnt >= MAXA)
  341.                 {    /* out of space */
  342.                     fprintf(stderr,"cc: out of a arg space\n");
  343.                     returnCode = -1;
  344.                     doExit();
  345.                 }
  346.                 break;
  347.             }
  348.             switch (*(p-1))
  349.             {    /* which file type? */
  350.                 case 'c':    /* C file */
  351.                 cargs[ccnt++] = argv[i];
  352.                 cnt = ccnt;
  353.                 maxarg = MAXC;
  354.                 break;
  355.                 case 's':    /* ASM file */
  356.                 sargs[scnt++] = argv[i];
  357.                 cnt = scnt;
  358.                 maxarg = MAXS;
  359.                 break;
  360.                 case 'o':    /* OBJECT file */
  361.                 oargs[ocnt++] = argv[i];
  362.                 cnt = ocnt;
  363.                 maxarg = MAXO;
  364.                 break;
  365.             }
  366.             if (cnt >= maxarg)
  367.             {    /* out of arg space */
  368.                 fprintf(stderr,"cc: out of arg space\n");
  369.                 returnCode = -1;
  370.                 doExit();
  371.             }
  372.             break;
  373.         }
  374.     }
  375.     if (vflag)
  376.         printf("%s\n",VERSION);
  377.  
  378.     /*
  379.      * Start compiling C files...
  380.      */
  381.     for (i = 0; i < ccnt; i++)
  382.     {    /* go through our C files */
  383.         if ((ccnt > 1) || vflag)
  384.             printf("%s:\n",cargs[i]);
  385.         compileFile(cargs[i]);
  386.     }
  387.     if (esflag || csflag || pflag || (returnCode != 0))
  388.         doExit();
  389.  
  390.     /*
  391.      * Do any necessary assemblies...
  392.      */
  393.     for (i = 0; i < scnt; i++)
  394.     {    /* go through our ASM files */
  395.         if ((scnt > 1) || vflag)
  396.             printf("%s:\n",sargs[i]);
  397.         assembleFile(sargs[i]);
  398.     }
  399.     if (cflag || (returnCode != 0))
  400.         doExit();
  401.  
  402.     /*
  403.      * Link everything together...
  404.      */
  405.     linkFiles();
  406.     for (i = 0; i < ccnt; i++)
  407.         removeFile(newFileSuffix(cargs[i],'o'));
  408.     for (i = 0; i < scnt; i++)
  409.         removeFile(newFileSuffix(sargs[i],'o'));
  410.  
  411.     /*
  412.      * Put output file in good place if necessary
  413.      */
  414.     if (strlen(TMPDIR) > 0)
  415.     {    /* do if TMPDIR was specified */
  416.         sprintf(tempFile,"%s%s.prg",TMPDIR,outputFile);
  417.         oldf = stringCopy(tempFile);
  418.         if (rflag)
  419.         {    /* pick standard suffix */
  420.             if (asflag)
  421.                 sprintf(tempFile,"%s.acc",outputFile);
  422.             else if (gsflag)
  423.                 sprintf(tempFile,"%s.prg",outputFile);
  424.             else    sprintf(tempFile,"%s.ttp",outputFile);
  425.         }
  426.         else    sprintf(tempFile,"%s.prg",outputFile);
  427.         newf = stringCopy(tempFile);
  428.         if (vflag)
  429.             printf("+ copy %s %s\n",oldf,newf);
  430.         removeFile(newf);
  431.         i = creatb(newf,0644);
  432.         if (i < 0)
  433.         {    /* no file? */
  434.             fprintf(stderr,"cc: can't open %s\n",newf);
  435.             returnCode = -1;
  436.             doExit();
  437.         }
  438.         close(i);
  439.         nfp = fopenb(newf,"w");
  440.         if (nfp == (FILE *)NULL)
  441.         {    /* no file? */
  442.             fprintf(stderr,"cc: can't make %s\n",newf);
  443.             returnCode = -1;
  444.             doExit();
  445.         }
  446.         ofp = fopenb(oldf,"r");
  447.         if (ofp == (FILE *)NULL)
  448.         {    /* no file? */
  449.             fprintf(stderr,"cc: can't open program %s\n",oldf);
  450.             returnCode = -1;
  451.             doExit();
  452.         }
  453.         while ((i = fread(cmdTail,1,BUFSIZ,ofp)) > 0)
  454.             fwrite(cmdTail,1,i,nfp);
  455.         fclose(ofp);
  456.         fclose(nfp);
  457.         removeFile(oldf);
  458.     }
  459.     else if (rflag && !asflag && !gsflag)
  460.     {    /* we only have to rename file to get right suffix */
  461.         sprintf(tempFile,"%s%s.prg",TMPDIR,outputFile);
  462.         oldf = stringCopy(tempFile);
  463.         if (asflag)
  464.             sprintf(tempFile,"%s.acc",outputFile);
  465.         else    sprintf(tempFile,"%s.ttp",outputFile);
  466.         if (Frename(0,oldf,tempFile) != 0)
  467.         {    /* rename didn't work... */
  468.             fprintf(stderr,"cc: rename of %s to %s failed\n",oldf,tempFile);
  469.             returnCode = -1;
  470.             doExit();
  471.         }
  472.     }
  473.  
  474.     /*
  475.      * And return to the user
  476.      */
  477.     doExit();
  478. };    /* end of main */
  479.  
  480. /*
  481.  * Exit with our recorded return code
  482.  */
  483. doExit()
  484. {
  485.     register struct memList *ml,*sml;
  486.  
  487.     if (xflag)
  488.         printf("cc: doExit: freeing memory\n");
  489.     for (ml = memTop; ml != (struct memList *)NULL; )
  490.     {    /* free our allocated memory */
  491.         sml = ml;
  492.         ml = ml->memPtr;
  493.         free(sml->memString);
  494.         free(sml);
  495.     }
  496.     if (xflag)
  497.         printf("cc: doExit: returning to system\n");
  498.     exit(returnCode);
  499. };    /* end of doExit */
  500.  
  501. /*
  502.  * Allocate some memory, and save it's location so that we can find
  503.  * it later.
  504.  */
  505. char *getMemory(size)
  506. int size;
  507. {
  508.     register struct memList *ml;
  509.     register char *cp;
  510.     struct memList xm;
  511.  
  512.     if (xflag)
  513.         printf("cc: getMemory: allocating memory s=%d,l=%d\n",
  514.             size,(sizeof xm));
  515.     cp = (char *)malloc(size);
  516.     ml = (struct memList *)malloc(sizeof xm);
  517.     if ((cp == (char *)NULL) || (ml == (struct memList *)NULL))
  518.     {    /* out of memory */
  519.         if (cp != (char *)NULL)
  520.             free(cp);
  521.         if (ml != (struct memList *)NULL)
  522.             free(ml);
  523.         return((char *)NULL);
  524.     }
  525.     if (xflag)
  526.         printf("cc: getMemory: saving memory in list cp=%lx,ml=%lx\n",
  527.             cp,ml);
  528.     ml->memString = cp;
  529.     ml->memPtr = (struct memList *)NULL;
  530.     if (memTop == (struct memList *)NULL)
  531.         memTop = memBottom = ml;
  532.     else
  533.     {    /* tack onto bottom */
  534.         memBottom->memPtr = ml;
  535.         memBottom = ml;
  536.     }
  537.     if (xflag)
  538.         printf("cc: getMemory: memory list modified\n");
  539.     return(cp);
  540. };    /* end of getMemory */
  541.  
  542. /*
  543.  * Remove an unwanted file
  544.  */
  545. removeFile(file)
  546. char *file;
  547. {
  548.     if (xflag)
  549.         printf("cc: removeFile: deleting %s\n",file);
  550.     Fdelete(file);
  551. };    /* end of removeFile */
  552.  
  553. /*
  554.  * Make a copy of a string
  555.  */
  556. char *stringCopy(string,xlen)
  557. char *string;
  558. int xlen;
  559. {
  560.     register char *s,*os;
  561.     register int size;
  562.  
  563.     if (xflag)
  564.         printf("cc: stringCopy: copying '%s'\n",string);
  565.     os = string;
  566.     size = strlen(os)+1+xlen;
  567.     s = getMemory(size);
  568.     if (s == (char *)NULL)
  569.     {    /* out of space */
  570.         fprintf(stderr,"cc: out of space (malloc failed)\n");
  571.         returnCode = -1;
  572.         doExit();
  573.     }
  574.     strcpy(s,os);
  575.     if (xflag)
  576.         printf("cc: stringCopy: copy complete\n");
  577.     return(s);
  578. };    /* end of stringCopy */
  579.  
  580. /*
  581.  * Return a copy of a filename, but with a new suffix char
  582.  */
  583. char *newFileSuffix(file,suffix)
  584. char *file;
  585. char suffix;
  586. {
  587.     register char *p;
  588.     register char *f;
  589.     char *newFile;
  590.  
  591.     if (xflag)
  592.         printf("cc: newFileSuffix: copying '%s' with suffix '%c'\n",
  593.             file,suffix);
  594.  
  595.     /* isolate out the leaf name of the file */
  596.     for (f = file; *f; f++)
  597.         continue;
  598.     while ((f > file) && (*f != '/') && (*f != ':'))
  599.         f--;
  600.     if (f > file)
  601.         f++;
  602.  
  603.     /* make a copy of it and change the last character ("the suffix") */
  604.     p = newFile = stringCopy(f,strlen(TMPDIR));
  605.     strcpy(p,TMPDIR);
  606.     strcat(p,f);
  607.     while (*p) p++;
  608.     *--p = suffix;
  609.     return(newFile);
  610. };    /* end of newFileSuffix */
  611.  
  612. /*
  613.  * Make a temporary file name
  614.  */
  615. char *makeTempFile()
  616. {
  617.     static int seed;
  618.  
  619.     sprintf(tempFile,"%st%d.tmp",TMPDIR,seed++);
  620.     if (xflag)
  621.         printf("cc: makeTempFile: generating %s\n",tempFile);
  622.     return(stringCopy(tempFile,0));
  623. };    /* end of makeTempFile */
  624.  
  625. /*
  626.  * Compile a file
  627.  */
  628. int compileFile(file)
  629. char *file;
  630. {
  631.     register int i;
  632.     char *cppOutput,*ctemp1,*ctemp2,*ctemp3,*ccOutput,*asOutput;
  633.  
  634.     if (xflag)
  635.         printf("cc: compileFile: compiling %s\n",file);
  636.  
  637.     if (pflag)
  638.         cppOutput = newFileSuffix(file,'i');
  639.     else    cppOutput = makeTempFile();
  640.     ccOutput = newFileSuffix(file,'s');
  641.     asOutput = newFileSuffix(file,'o');
  642.     ctemp1 = makeTempFile();
  643.     ctemp2 = makeTempFile();
  644.     ctemp3 = makeTempFile();
  645.  
  646.     if (xflag)
  647.         printf("cc: compileFile: have temp files\n");
  648.  
  649.     resetCmdTail();
  650.     for (i = 0; i < pcnt; i++)
  651.         addtoCmdTail(pargs[i]);
  652.     addtoCmdTail("-i");
  653.     addtoCmdTail(INCDIR);
  654.     if (esflag || pflag)
  655.         addtoCmdTail("-p");
  656.     if (esflag)
  657.         addtoCmdTail("-e");
  658.     addtoCmdTail(file);
  659.     addtoCmdTail(cppOutput);
  660.     if (execute(CPP,0))
  661.     {    /* if something bad happened */
  662.         returnCode = -1;
  663.         removeFile(cppOutput);
  664.         return(-1);
  665.     }
  666.     if (esflag || pflag)
  667.     {    /* nothing else to do for this file */
  668.         return(0);
  669.     }
  670.  
  671.     resetCmdTail();
  672.     addtoCmdTail(cppOutput);
  673.     addtoCmdTail(ctemp1);
  674.     addtoCmdTail(ctemp2);
  675.     addtoCmdTail(ctemp3);
  676.     if (fflag)
  677.         addtoCmdTail("-f");
  678.     else if (eflag)
  679.         addtoCmdTail("-e");
  680.     if (execute(C0,0))
  681.     {    /* if something bad happened */
  682.         returnCode = -1;
  683.         removeFile(cppOutput);
  684.         removeFile(ctemp1);
  685.         removeFile(ctemp2);
  686.         removeFile(ctemp3);
  687.         return(-1);
  688.     }
  689.     removeFile(cppOutput);
  690.     removeFile(ctemp3);
  691.  
  692.     resetCmdTail();
  693.     addtoCmdTail(ctemp1);
  694.     addtoCmdTail(ctemp2);
  695.     addtoCmdTail(ccOutput);
  696.     if (execute(C1,0))
  697.     {    /* if something bad happened */
  698.         returnCode = -1;
  699.         removeFile(ctemp1);
  700.         removeFile(ctemp2);
  701.         removeFile(ccOutput);
  702.         return(-1);
  703.     }
  704.     removeFile(ctemp1);
  705.     removeFile(ctemp2);
  706.     if (csflag)
  707.         return(0);
  708.  
  709.     resetCmdTail();
  710.     addtoCmdTail("-l");
  711.     addtoCmdTail("-u");
  712.     addtoCmdTail("-s");
  713.     sprintf(tempFile,"%sAS68SYMB.DAT",BINDIR);
  714.     addtoCmdTail(tempFile);
  715.     if (strlen(TMPDIR) > 0)
  716.     {    /* redirect temp files */
  717.         addtoCmdTail("-f");
  718.         addtoCmdTail(TMPDIR);
  719.     }
  720.     addtoCmdTail(ccOutput);
  721.     if (execute(AS,0))
  722.     {    /* if something bad happened */
  723.         returnCode = -1;
  724.         removeFile(ccOutput);
  725.         removeFile(asOutput);
  726.         return(-1);
  727.     }
  728.     removeFile(ccOutput);
  729.     return(0);
  730. };    /* end of compileFile */
  731.  
  732. /*
  733.  * Assemble a file
  734.  */
  735. int assembleFile(file)
  736. char *file;
  737. {
  738.     register char *asOutput;
  739.  
  740.     if (xflag)
  741.         printf("cc: assembleFile: assembling %s\n",file);
  742.  
  743.     asOutput = newFileSuffix(file,'o');
  744.     resetCmdTail();
  745.     addtoCmdTail("-l -u");
  746.     addtoCmdTail(file);
  747.     if (execute(AS,0))
  748.     {    /* if something bad happened */
  749.         returnCode = -1;
  750.         removeFile(asOutput);
  751.         return(-1);
  752.     }
  753.     return(0);
  754. };    /* end of assembleFile */
  755.  
  756. /*
  757.  * Link everything together into one file
  758.  */
  759. linkFiles()
  760. {
  761.     register int i;
  762.     register char *cp;
  763.     register int counter;
  764.     FILE *fp;
  765.     char *ldtemp;
  766.  
  767.     if (xflag)
  768.         printf("cc: linkFiles: entering\n");
  769.  
  770.     ldtemp = makeTempFile();
  771.     removeFile(ldtemp);
  772.     i = creat(ldtemp,2);
  773.     if (i < 0)
  774.     {    /* no temp file for us to play with? */
  775.         fprintf(stderr,"cc: can't open ld temp file '%s'\n",ldtemp);
  776.         returnCode = -1;
  777.         return(-1);
  778.     }
  779.     close(i);
  780.     fp = fopen(ldtemp,"w");
  781.     if (!fp)
  782.     {    /* no temp file for us to play with? */
  783.         fprintf(stderr,"cc: can't open ld temp file '%s'\n",ldtemp);
  784.         returnCode = -1;
  785.         return(-1);
  786.     }
  787.     resetCmdTail();
  788.     argSeparator = ',';
  789.     addtoCmdTail("[u");
  790.     if (!sflag)
  791.         addtoCmdTail("s");
  792.     if (strlen(TMPDIR) > 0)
  793.     {    /* redirect temp files */
  794.         sprintf(tempFile,"tem[%s]",TMPDIR);
  795.         addtoCmdTail(tempFile);
  796.     }
  797.     *--ptrCmdTail = ']';
  798.     *++ptrCmdTail = ' ';
  799.     *++ptrCmdTail = '\0';
  800.     argSeparator = '=';
  801.     sprintf(tempFile,"%s%s.68k",TMPDIR,outputFile);
  802.     addtoCmdTail(tempFile);
  803.     argSeparator = ',';
  804.     strcpy(cmdName,BINDIR);
  805.     if (!asflag)
  806.         strcat(cmdName,CSTART);
  807.     else    strcat(cmdName,ACCSTRT);
  808.     addtoCmdTail(cmdName);
  809.     *--ptrCmdTail = '\0';
  810.     sprintf(cmdName,"[CO[%s]], ",ldtemp);
  811.     strcat(cmdTail,cmdName);
  812.     while (*ptrCmdTail)
  813.         ptrCmdTail++;
  814.     fputc(',',fp);
  815.     counter = 7;
  816.     for (i = 0; i < ccnt; i++)
  817.     {    /* C files */
  818.         cp = newFileSuffix(cargs[i],'o');
  819.         fprintf(fp,"%s,\n",cp);
  820.         counter++;
  821.     }
  822.     for (i = 0; i < scnt; i++)
  823.     {    /* ASM files */
  824.         cp = newFileSuffix(sargs[i],'o');
  825.         fprintf(fp,"%s,\n",cp);
  826.         counter++;
  827.     }
  828.     for (i = 0; i < ocnt; i++)
  829.     {    /* O files */
  830.         fprintf(fp,"%s,\n",oargs[i]);
  831.         counter++;
  832.     }
  833.     for (i = 0; i < acnt; i++)
  834.     {    /* other args */
  835.         fprintf(fp,"%s,\n",aargs[i]);
  836.         counter++;
  837.     }
  838.     if (gsflag)
  839.     {    /* link for gem */
  840.         strcpy(cmdName,BINDIR);
  841.         strcat(cmdName,GEMAES);
  842.         fprintf(fp,"%s,\n",cmdName);
  843.         counter++;
  844.         strcpy(cmdName,BINDIR);
  845.         strcat(cmdName,GEMVDI);
  846.         fprintf(fp,"%s,\n",cmdName);
  847.         counter++;
  848.     }
  849.     strcpy(cmdName,BINDIR);
  850.     strcat(cmdName,OSBIND);
  851.     fprintf(fp,"%s,\n",cmdName);
  852.     counter++;
  853.     strcpy(cmdName,BINDIR);
  854.     strcat(cmdName,CLIB);
  855.     if (eflag || fflag)
  856.     {    /* add in floating point library */
  857.         fprintf(fp,"%s,\n",cmdName);
  858.         counter++;
  859.         strcpy(cmdName,BINDIR);
  860.         strcat(cmdName,LIBF);
  861.     }
  862.     fprintf(fp,"%s\n",cmdName);
  863.     counter++;
  864.     fclose(fp);
  865.     if (execute(LD,counter))
  866.     {    /* if something bad happened */
  867.         returnCode = -1;
  868.         removeFile(tempFile);
  869.         removeFile(ldtemp);
  870.         return(-1);
  871.     }
  872.     removeFile(ldtemp);
  873.  
  874.     argSeparator = ' ';
  875.     resetCmdTail();
  876.     addtoCmdTail(TMPDIR);
  877.     ptrCmdTail--;
  878.     addtoCmdTail(outputFile);
  879.     if (execute(RELMOD,0))
  880.     {    /* if something bad happened */
  881.         returnCode = -1;
  882.         removeFile(tempFile);
  883.         return(-1);
  884.     }
  885.     removeFile(tempFile);
  886.     return(0);
  887. };    /* end of linkFiles */
  888.  
  889. /*
  890.  * Since we always execute commands underneath us the same way,
  891.  * one common routine is used to set things up and then call the
  892.  * more general execution routine "runCommand"
  893.  *
  894.  * Zero is returned if everything probably succeeded, and non-zero
  895.  * if not.  This includes making sure that the command doesn't generate
  896.  * any more output than we expect.
  897.  *
  898.  * The command tail should be completely set up by the time this
  899.  * routine is called.
  900.  */
  901. int execute(command,expectedOutput)
  902. char *command;
  903. int expectedOutput;
  904. {
  905.     register int rc;
  906.     register int outputLines;
  907.     char *tempOutput;
  908.     int character;
  909.  
  910.     if (xflag)
  911.         printf("cc: execute: run cmd=%s,lines=%d\n",command,expectedOutput);
  912.  
  913.     tempOutput = makeTempFile();
  914.     *ptrCmdTail++ = '>';
  915.     *ptrCmdTail = '\0';
  916.     addtoCmdTail(tempOutput);
  917.     rc = runCommand(command);
  918.     outputLines = copyToStderr(tempOutput,expectedOutput);
  919.     removeFile(tempOutput);
  920.     if ((rc != 0) && (outputLines == 0))
  921.         fprintf(stderr,"cc: bad return from executing %s\n",command);
  922.  
  923.     if (Bconstat(2))
  924.     {    /* if input waiting */
  925.         character = Bconin(2);
  926.         if ((character & 0xFF) == 0x03)
  927.         {    /* if a ^C */
  928.             fprintf(stderr,"cc: compilation aborted by ^C interrupt\n");
  929.             fprintf(stderr,"cc: existing temp files won't be removed\n");
  930.             returnCode = -1;
  931.             doExit();
  932.         }
  933.     }
  934.  
  935.     if (((outputLines != 0) && !wflag) || (rc != 0))
  936.         return(-1);    /* if an error was found */
  937.     else    return(0);    /* everything probably worked */
  938. };    /* end of execute */
  939.  
  940. /*
  941.  * Copy a the contents of a specified file to our standard error stream,
  942.  * after possibly skipping some lines at the beginning of the file.
  943.  * Return the number of lines actually printed, or -1 if the file could
  944.  * not be opened.
  945.  */
  946. int copyToStderr(file,skip)
  947. char *file;
  948. int skip;
  949. {
  950.     register FILE *fp;
  951.     register int count;
  952.     char line[BUFSIZ];
  953.  
  954.     if (xflag)
  955.         printf("cc: copyToStderr: entering file=%s,skip=%d\n",file,skip);
  956.  
  957.     fp = fopen(file,"r");
  958.     if (fp == (FILE *)NULL)
  959.     {    /* file not usable */
  960.         return(-1);
  961.     }
  962.  
  963.     count = 0;
  964.     while (fgets(line,sizeof line,fp) != NULL)
  965.     {    /*  go through the file */
  966.         if (++count <= skip)
  967.             continue;
  968.         fputs(line,stderr);
  969.     }
  970.     fclose(fp);
  971.  
  972.     return(count - skip);
  973. };    /* end of copyToStderr */
  974.  
  975. /*
  976.  * Empty out our argument buffer
  977.  */
  978. resetCmdTail()
  979. {
  980.     if (xflag)
  981.         printf("cc: resetCmdTail: entering\n");
  982.     ptrCmdTail = cmdTail;
  983.     *ptrCmdTail++ = ' ';
  984.     *ptrCmdTail = '\0';
  985. };    /* end of resetCmdTail */
  986.  
  987. /*
  988.  * Add an argument to our buffer
  989.  */
  990. addtoCmdTail(arg)
  991. char *arg;
  992. {
  993.     if (xflag)
  994.         printf("cc: addtoCmdTail: adding %s\n",arg);
  995.     while (*arg)
  996.     {    /* Copy the argument */
  997.         *ptrCmdTail++ = *arg++;
  998.         if (ptrCmdTail >&cmdTail[TAIL-3])
  999.         {    /* out of space */
  1000.             fprintf(stderr,"cc: out of cmd tail space\n");
  1001.             returnCode = -1;
  1002.             doExit();
  1003.         }
  1004.     }
  1005.     *ptrCmdTail++ = argSeparator;
  1006.     *ptrCmdTail = '\0';
  1007. };    /* end of addtoCmdTail */
  1008.  
  1009. /*
  1010.  * Run a given command using the argument buffer that MUST
  1011.  * have been setup previously.
  1012.  */
  1013. int runCommand(cmd)
  1014. char *cmd;
  1015. {
  1016.     register int rc,len;
  1017.  
  1018.     cmdName[0] = '\0';
  1019.     strcpy(cmdName,BINDIR);
  1020.     strcat(cmdName,cmd);
  1021.     if (*--ptrCmdTail != argSeparator)
  1022.         ptrCmdTail++;
  1023.     *ptrCmdTail = '\0';
  1024.     if (vflag)
  1025.         printf("+ %s %s\n",cmdName,cmdTail);
  1026.     len = strlen(cmdTail) - 1;
  1027.     cmdTail[0] = (char)len;
  1028.     rc = Pexec(0,cmdName,cmdTail,(char *)0);
  1029.     resetCmdTail();
  1030.     return(rc);
  1031. };    /* end of runCommand */
  1032. ə