home *** CD-ROM | disk | FTP | other *** search
/ Dream 48 / Amiga_Dream_48.iso / Atari / c / sozobon-v2 / scsrc20.lzh / TOOLS.LZH / CC.C < prev    next >
C/C++ Source or Header  |  1991-02-22  |  23KB  |  1,129 lines

  1. /* Copyright (c) 1988,89,91 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. static    char    Version[] =
  13. "cc: version 2.0  Copyright (c) 1988,89,91 by Sozobon, Limited.";
  14.  
  15. /*
  16.  * cc - C compiler driver program
  17.  *
  18.  * Parses command line for options and file names. Then calls the
  19.  * various passes of the compiler as needed.
  20.  */
  21.  
  22. #include <stdio.h>
  23. #if    MINIX || UNIXHOST
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <signal.h>
  27. #include <errno.h>
  28. #else
  29. #include <types.h>
  30. #include <stat.h>
  31. #include <osbind.h>
  32. #endif
  33.  
  34. #if    MINIX || UNIXHOST
  35. #define    SEPCHAR    '/'
  36. #else
  37. #define    SEPCHAR    '\\'
  38. #endif
  39.  
  40. #ifndef    MINIX
  41. #define    rindex    strrchr
  42. #define    index    strchr
  43. #endif
  44.  
  45. #ifndef    TRUE
  46. #define    FALSE    (0)
  47. #define    TRUE    !FALSE
  48. #endif
  49.  
  50. #define    MAXOPT    16    /* max. number of options to any one pass */
  51.  
  52. /*
  53.  * Compiler pass information
  54.  */
  55. #if    MINIX || UNIXHOST
  56. #define    CC    "hcc"
  57. #else
  58. #define    CC    "hcc.ttp"
  59. #endif
  60.  
  61. char    *hccopt[MAXOPT];
  62. int    hcc_cnt = 0;        /* number of options to hcc */
  63.  
  64. /*
  65.  * Optimizer information
  66.  */
  67. #if    MINIX || UNIXHOST
  68. #define    OPT    "top"
  69. #else
  70. #define    OPT    "top.ttp"
  71. #endif
  72.  
  73. char    *topopt[MAXOPT];
  74. int    top_cnt = 0;        /* number of options to top */
  75.  
  76. /*
  77.  * Assembler information
  78.  */
  79. #if    MINIX || UNIXHOST
  80. #define    ASM    "jas"
  81. #define    CPP    "cpp"
  82. #else
  83. #define    ASM    "jas.ttp"
  84. #endif
  85.  
  86. /*
  87.  * Loader information
  88.  */
  89. #ifdef    MINIX
  90. #define    LD    "sld"
  91. #else
  92. #ifdef     UNIXHOST
  93. #define LD    "xld"
  94. #else
  95. #define    LD    "ld.ttp"
  96. #endif
  97. #endif
  98. char    *lsize = NULL;            /* process size (from the =N option) */
  99.  
  100. #ifdef    MINIX
  101. #define    CSU    (pflag ? "mcrtso.o"    : "crtso.o")    /* C startup code */
  102. #define    LIBC    (pflag ? "libp/libc.a" : "libc.a")    /* C runtime library */
  103. #define    LIBM    (pflag ? "libp/libm.a" : "libm.a")    /* math library */
  104. #else
  105. #define    CSU    (pflag ? "dstartp.o" : "dstart.o")    /* C startup code */
  106. #define    LIBC    (pflag ? "dlibsp.a"  : "dlibs.a")    /* C runtime library */
  107. #define    LIBM    (pflag ? "libmp.a"   : "libm.a")    /* math library */
  108. #endif
  109.  
  110. /*
  111.  * Path information
  112.  */
  113.  
  114. char    *path;        /* where to find executables */
  115. char    *lib = NULL;    /* where to find library stuff */
  116. char    *tmp = NULL;    /* where to put temporary files */
  117.  
  118. /*
  119.  * Temp file names
  120.  */
  121. char    Sfile[128];    /* temp file for assembly code */
  122. char    OSfile[128];    /* temp file for optimized assembly */
  123. char    Lfile[128];    /* the loader command file */
  124.  
  125. /*
  126.  * Default paths for executables and libraries
  127.  */
  128. #ifdef    MINIX
  129. #define    DEFPATH        "/usr/sozobon/bin"
  130. #define    DEFLIB        "/usr/sozobon/lib"
  131. #define    DEFTMP        "/tmp"
  132. #else
  133. #ifdef UNIXHOST
  134. #define    DEFPATH        "/home/hans/sozobon/bin"
  135. #define    DEFLIB        "/home/hans/sozobon/lib"
  136. #define    DEFTMP        "/tmp"
  137. #else
  138. #define    DEFPATH        "\\sozobon\\bin"
  139. #define    DEFLIB        "\\sozobon\\lib"
  140. #define    DEFTMP        "."
  141. #endif
  142. #endif
  143.  
  144. /*
  145.  * Boolean options
  146.  */
  147. int    mflag = 0;    /* generate a load map */
  148. int    vflag = 0;    /* show what we're doing w/ version numbers */
  149. int    nflag = 0;    /* ...but don't really do it */
  150. int    Sflag = 0;    /* generate assembly files */
  151. int    cflag = 0;    /* generate ".s" files only */
  152. int    Oflag = 0;    /* run the optimizer */
  153. int    sflag = 0;    /* don't generate a symbol table in executables */
  154. int    pflag = 0;    /* enable execution profiling */
  155. int    rflag = 0;    /* enable floating point (Real numbers) */
  156. int    fflag = 0;    /* scan given file for file names */
  157. int    tflag = 0;    /* don't remove temporary files */
  158. int    gflag = 0;    /* disable certain confusing optimizations */
  159.  
  160. /*
  161.  * We build lists of the various file types we're given. Within each
  162.  * type, MAXF says how many we can deal with.
  163.  */
  164. #define    MAXF    60
  165.  
  166. int    ncfiles = 0;    /* .c files */
  167. char    *cfiles[MAXF];
  168.  
  169. int    nsfiles = 0;    /* .s files */
  170. char    *sfiles[MAXF];
  171.  
  172. int    nofiles = 0;    /* .o files */
  173. char    *ofiles[MAXF];
  174.  
  175. int    nlfiles = 0;    /* .a or .lib files (or files with no suffix) */
  176. char    *lfiles[MAXF];
  177.  
  178. #ifdef    MINIX
  179. #define    DEFOUT    "a.out"        /* default output file */
  180. #else
  181. #define    DEFOUT    "a.ttp"        /* default output file */
  182. #endif
  183.  
  184. char    *output = NULL;        /* output file */
  185.  
  186. /*
  187.  * Argument vectors for the programs we'll run.
  188.  */
  189. #define    MAXARG        60
  190.  
  191. char    *av[MAXARG];
  192. int    ac;
  193.  
  194. #define    BEGARG()    (ac = 0)
  195. #define    ADDARG(x)    (av[ac++] = (x))
  196. #define    ENDARG()    (av[ac++] = NULL)
  197.  
  198. extern    int    errno;
  199.  
  200. int    got_sig = FALSE;    /* TRUE if we got a signal */
  201.  
  202. usage()
  203. {
  204. #define    P(s)    fprintf(stderr, s)
  205.  
  206.     P("Sozobon C Compiler Options:\n");
  207.     P("-c           compile, but don't link\n");
  208.     P("-S           don't assemble, leave .s files around (-A)\n");
  209.     P("-O           run the assembly code optimizer\n");
  210.     
  211.     P("-v           show what cc is doing\n");
  212.     P("-n           like -v, but don't really run anything\n");
  213.     P("-f file      read a list of input files from 'file'\n");
  214.     P("-Tdir        put temp files in 'dir' (-K)\n");
  215.     P("-t           don't remove temp files when done (-H)\n");
  216.     P("-p           enable execution profiling\n");
  217.     P("-g           compile program for use with the debugger\n");
  218.     
  219.     P("-Ilib        add dir. 'lib' to the header search list\n");
  220.     P("-Dsym        define the pre-processor symbol 'sym' as 1\n");
  221.     P("-Dsym=val    or as 'val'\n");
  222.     P("-Usym        un-define the built-in symbol 'sym'\n");
  223.     
  224.     P("-o file      use the file 'f' for the loader output (-X)\n");
  225.     P("-r           link the floating point library (-Q)\n");
  226.     P("-lxx         load the library libxx.a (-J)\n");
  227.     P("-m           generate a load map\n");
  228.     P("-s           don't generate a symbol table (-Y)\n");
  229.     
  230.     P("=nnn         make the stack/heap size nnn bytes (Minix only)\n");
  231.     P("-R           ignored (for Minix compatibility)\n");
  232.     P("-w           ignored (for Minix compatibility)\n");
  233.  
  234. #undef    P
  235.  
  236.     exit(1);
  237. }
  238.  
  239. main(argc, argv)
  240. int    argc;
  241. char    *argv[];
  242. {
  243. #if MINIX || UNIXHOST
  244.     int    catch();        /* signal handler */
  245. #endif
  246.     extern    char    *chsuf();
  247.     register int    i;
  248.     register char    *s;
  249.     register int    endopt;
  250.     int    domsg = FALSE;
  251.  
  252.     if (argc == 1)
  253.         usage();
  254.  
  255. #ifdef    MINIX
  256.     /*
  257.      * This is one of the places where ACK blew it. We have to check
  258.      * to see if we're in the background before setting up our own
  259.      * signal handler. ACK catches the signal anyway, so interrupting
  260.      * a foreground process kills any background compiles, too.
  261.      */
  262.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  263.         signal(SIGINT, catch);
  264. #endif
  265. #ifdef UNIXHOST
  266.     signal(SIGINT, catch);
  267. #endif
  268.  
  269.     for (i=1; i < argc ;i++) {
  270.         if (argv[i][0] == '-') {    /* option */
  271.             endopt = FALSE;
  272.             for (s = &argv[i][1]; *s && !endopt ;s++) {
  273.                 switch (*s) {
  274.                 case 'c': case 'C':
  275.                     cflag = TRUE;
  276.                     break;
  277.  
  278.                 case 'S': case 'a': case 'A':
  279.                     Sflag = TRUE;
  280.                     break;
  281.  
  282.                 case 'v': case 'V':
  283.                     vflag = TRUE;
  284.                     break;
  285.  
  286.                 case 'n': case 'N':
  287.                     nflag = TRUE;
  288.                     break;
  289.  
  290.                 case 'm': case 'M':
  291.                     mflag = TRUE;
  292.                     break;
  293.  
  294.                 case 's': case 'y': case 'Y':
  295.                     sflag = TRUE;
  296.                     break;
  297.  
  298.                 case 'r': case 'q': case 'Q':
  299.                     rflag = TRUE;
  300.                     break;
  301.  
  302.                 case 'p': case 'P':
  303.                     pflag = TRUE;
  304.                     break;
  305.  
  306.                 case 'g': case 'G':
  307.                     gflag = TRUE;
  308.                     break;
  309.  
  310.                 case 'o': case 'x': case 'X':
  311.                     output = argv[++i];
  312.                     endopt = TRUE;
  313.                     break;
  314.  
  315.                 case 'l': case 'j': case 'J':
  316.                     keeplib(s+1);
  317.                     endopt = TRUE;
  318.                     break;
  319.  
  320.                 case 'f': case 'F':
  321.                     getfiles(argv[++i]);
  322.                     endopt = TRUE;
  323.                     break;
  324.  
  325.                 /*
  326.                  * Minix compatibility
  327.                  */
  328.                 case 'R':    /* ignored */
  329.                 case 'w': case 'W':
  330.                     break;
  331.  
  332.                 case 'T': case 'k': case 'K':
  333.                     tmp = s+1;
  334.                     endopt = TRUE;
  335.                     break;
  336.  
  337.                 case 't': case 'h': case 'H':
  338.                     tflag = TRUE;
  339.                     break;
  340.  
  341.                 /*
  342.                  * Options for other passes.
  343.                  */
  344.                 case 'I':    /* compiler options */
  345.                 case 'D':
  346.                 case 'U':
  347.                     hccopt[hcc_cnt++] = argv[i];
  348.                     endopt = TRUE;
  349.                     break;
  350.  
  351.                 case 'z': case 'Z':
  352.                     *s = 'O';
  353.                     /* fall through */
  354.  
  355.                 case 'O':
  356.                     /*
  357.                      * Enable the optimizer, possibly with
  358.                      * options specifically for it.
  359.                      */
  360.                     Oflag = TRUE;
  361.                     if (s[1] != '\0')
  362.                         topopt[top_cnt++] = argv[i];
  363.                     endopt = TRUE;
  364.                     break;
  365.  
  366.                 default:
  367.                     usage();
  368.                 }
  369.             }
  370.         } else if (argv[i][0] == '=') {    /* heap/stack size for ld */
  371.             lsize = argv[i];
  372.         } else                /* input file */
  373.             keepfile(argv[i]);
  374.     }
  375.     doinit();
  376.  
  377.     if ((ncfiles + nsfiles) > 1)
  378.         domsg = TRUE;
  379.  
  380.     if (vflag && !nflag)
  381.         printf("%s\n", Version);
  382.  
  383.     for (i = 0; i < ncfiles ;i++) {
  384.         if (domsg)
  385.             printf("%s:\n", cfiles[i]);
  386.         docomp(cfiles[i]);
  387.         doopt(cfiles[i]);
  388.         doasm(cfiles[i], TRUE);
  389.     }
  390.  
  391.     for (i = 0; i < nsfiles ;i++) {
  392.         if (domsg)
  393.             printf("%s:\n", sfiles[i]);
  394.         doasm(sfiles[i], FALSE);
  395.     }
  396.  
  397.     dold();        /* run the loader */
  398.  
  399.     exit(0);
  400. }
  401.  
  402. /*
  403.  * doinit() - set up some variables before getting started
  404.  */
  405. doinit()
  406. {
  407.     char    *getenv();
  408.  
  409.     if ((path = getenv("PATH")) == NULL)
  410.         path = DEFPATH;
  411.  
  412.     if ((lib = getenv("LIB")) == NULL)
  413.         lib = DEFLIB;
  414.  
  415.     if (tmp == NULL) {
  416.         if ((tmp = getenv("TMPDIR")) == NULL)
  417.             tmp = DEFTMP;
  418.     }
  419.  
  420.     sprintf(Sfile, "%s%cC%05d.s",   tmp, SEPCHAR, getpid());
  421.     sprintf(OSfile, "%s%cCO%05d.s", tmp, SEPCHAR, getpid());
  422.     sprintf(Lfile, "%s%cCL%05d.ld", tmp, SEPCHAR, getpid());
  423. }
  424.  
  425. #if    MINIX || UNIXHOST
  426. catch()
  427. {
  428.     signal(SIGINT, catch);
  429.  
  430.     got_sig = TRUE;
  431. }
  432. #endif
  433.  
  434. /*
  435.  * getfiles(f) - read file names from the given file
  436.  */
  437. getfiles(f)
  438. char    *f;
  439. {
  440.     char    *strsave();
  441.     char    name[64];
  442.     FILE    *fp;
  443.  
  444.     if ((fp = fopen(f, "r")) == NULL) {
  445.         fprintf(stderr, "cc: can't open file '%s'\n", f);
  446.         return;
  447.     }
  448.  
  449.     while (scanf("%s", name))
  450.         keepfile(strsave(name));
  451.  
  452.     fclose(fp);
  453. }
  454.  
  455. /*
  456.  * keeplib(l) - save a library reference
  457.  *
  458.  * Given an option like "-lm", keeplib saves a reference to a library file
  459.  * named "libm.a". The usual places will be searched for the library when
  460.  * the time comes. keeplib() should be called with the "-l" stripped off.
  461.  */
  462. keeplib(l)
  463. char    *l;
  464. {
  465.     char    *strsave();
  466.     char    name[32];
  467.  
  468.     sprintf(name, "lib%s.a", l);
  469.  
  470.     keepfile(strsave(name));
  471. }
  472.  
  473. /*
  474.  * keepfile(f) - remember the filename 'f' in the appropriate place
  475.  */
  476. keepfile(f)
  477. char    *f;
  478. {
  479.     char    *p, *rindex();
  480.  
  481.     if ((p = rindex(f, '.')) == NULL) {    /* no suffix */
  482.         lfiles[nlfiles++] = f;
  483.         return;
  484.     }
  485.  
  486.     if ((strcmp(p, ".c") == 0) || (strcmp(p, ".C") == 0)) {
  487.         cfiles[ncfiles++] = f;
  488.         return;
  489.     }
  490.     if ((strcmp(p, ".s") == 0) || (strcmp(p, ".S") == 0)) {
  491.         sfiles[nsfiles++] = f;
  492.         return;
  493.     }
  494.     if ((strcmp(p, ".o") == 0) || (strcmp(p, ".O") == 0)) {
  495.         ofiles[nofiles++] = f;
  496.         return;
  497.     }
  498.     if ((strcmp(p, ".a") == 0) || (strcmp(p, ".A") == 0)) {
  499.         lfiles[nlfiles++] = f;
  500.         return;
  501.     }
  502.     fprintf(stderr, "cc: unknown file suffix '%s'\n", f);
  503.     exit(1);
  504. }
  505.  
  506. /*
  507.  * chsuf(f, suf) - change the suffix of file 'f' to 'suf'.
  508.  *
  509.  * Space for the new string is obtained using malloc().
  510.  */
  511. char *
  512. chsuf(f, suf)
  513. char    *f;
  514. char    *suf;
  515. {
  516.     char    *malloc();
  517.     char    *s, *p;
  518.  
  519.     p = s = malloc(strlen(f) + strlen(suf) + 1);
  520.  
  521.     strcpy(p, f);
  522.  
  523.     for (; *p ; p++) {
  524.         if (*p == '.')
  525.             break;
  526.     }
  527.  
  528.     while (*suf)
  529.         *p++ = *suf++;
  530.  
  531.     *p = '\0';
  532.  
  533.     return s;
  534. }
  535.  
  536. /*
  537.  * isfile(f) - return true if the given file exists
  538.  */
  539. int
  540. isfile(f)
  541. char    *f;
  542. {
  543.     struct    stat    sbuf;
  544.  
  545.     if (stat(f, &sbuf) < 0)
  546.         return FALSE;
  547.  
  548.     return TRUE;
  549. }
  550.  
  551. /*
  552.  * findfile(e, b)
  553.  *
  554.  * Finds a file in one of the directories given in the environment
  555.  * variable whose value is pointed to by 'e'. Looks for the file
  556.  * given by the name 'b'.
  557.  *
  558.  * Returns a pointer to a static area containing the pathname of the
  559.  * file, if found, NULL otherwise.
  560.  */
  561. char *
  562. findfile(e, b)
  563. char    *e;
  564. register char    *b;
  565. {
  566.     static    char    file[256];
  567.     char    env[256];
  568.     register char    *p;
  569.  
  570.     /*
  571.      * Make a copy of the value of the env. variable. Convert all
  572.      * delimiters to nulls.
  573.      */
  574.     if (e != NULL) {
  575.         strcpy(env, e);
  576.         for (p = env; *p ;p++) {
  577. #if    MINIX || UNIXHOST
  578.             if (*p == ':')
  579. #else
  580.             if (*p == ';' || *p == ',')
  581. #endif
  582.                 *p = '\0';
  583.         }
  584.         p[1] = '\0';        /* double null terminator */
  585.     } else
  586.         env[1] = env[0] = '\0';
  587.  
  588.     p = env;
  589.     /*
  590.      * An initial null means to try the current directory.
  591.      */
  592.     if (*p == '\0') {
  593.         if (isfile(b))
  594.             return b;
  595.         p++;
  596.     }
  597.  
  598.     while (*p) {
  599.         sprintf(file, "%s%c%s", p, SEPCHAR, b);
  600.         if (isfile(file))
  601.             return file;
  602.  
  603.         while (*p++ != '\0')
  604.             ;
  605.     }
  606.     return NULL;        /* give up */
  607. }
  608.  
  609. #if    MINIX || UNIXHOST
  610. /*
  611.  * docmd(path, argv) - run a command
  612.  *
  613.  * We check for an interrupt before and after executing the command.
  614.  * The sub-processes we run are the only very time-consuming thing we
  615.  * do in 'cc', so there's not much point in checking for signals in
  616.  * other places. When a signal comes in, we just delete the temp files.
  617.  */
  618. int
  619. docmd(path, argv)
  620. char    *path;
  621. char    *argv[];
  622. {
  623.     void    cleanup();
  624.     int    i;
  625.     int    pid, status;
  626.     char    buf[512];
  627.     int    dosystem = FALSE;
  628.  
  629.     if (vflag || nflag) {
  630.         fprintf(stderr, "%s", path);
  631.         for (i=1; argv[i] != NULL ;i++)
  632.             fprintf(stderr, " %s", argv[i]);
  633.         fputc('\n', stderr);
  634.         fflush(stderr);
  635.         if (nflag)
  636.             return 0;
  637.     }
  638.     /*
  639.      * Figure out whether exec() is okay or we need a shell.
  640.      */
  641.     for (i=1; argv[i] != NULL ;i++)
  642.         if (argv[i][0] == '>' || argv[i][0] == '<')
  643.             dosystem = TRUE;
  644.  
  645.     if (got_sig)
  646.         cleanup();
  647.  
  648.     if (dosystem) {
  649.         strcpy(buf, path);
  650.         for (i=1; argv[i] != NULL ;i++) {
  651.             strcat(buf, " ");
  652.             strcat(buf, argv[i]);
  653.         }
  654.         return system(buf);
  655.     } else {
  656.  
  657.         /*
  658.          * Fork and exec the command.
  659.          */
  660.  
  661.         if ((pid = fork()) < 0) {
  662.             fprintf(stderr, "cc: can't fork\n");
  663.             return -1;
  664.         }
  665.     
  666.         if (pid == 0) {            /* the child */
  667.             execv(path, argv);
  668.             fprintf(stderr, "cc: Can't exec '%s'\n", path);
  669.             exit(1);
  670.         } else {            /* the parent */
  671.             if (wait(&status) == -1 && errno != EINTR) {
  672.                 fprintf(stderr,"cc: wait failed (%d)\n", errno);
  673.                 return -1;
  674.             } else if ((status & 0xff) == 0)
  675.                 return (status >> 8);
  676.         }
  677.     }
  678.     if (got_sig)
  679.         cleanup();
  680.  
  681.     return -1;
  682. }
  683.  
  684. void
  685. cleanup()
  686. {
  687.     unlink(Sfile);
  688.     unlink(OSfile);
  689.     unlink(Lfile);
  690.  
  691.     exit(1);
  692. }
  693.  
  694. #else
  695.  
  696. /*
  697.  * docmd(path, argv) - run a command
  698.  */
  699. int
  700. docmd(path, argv)
  701. char    *path;
  702. char    *argv[];
  703. {
  704.     int    i;
  705.     char    cmdline[130];
  706.     char    *cmd;
  707.  
  708.     cmd = &cmdline[1];
  709.     *cmd = '\0';
  710.  
  711.     for (i=1; argv[i] != NULL ;i++) {
  712.         if (i > 1)
  713.             strcat(cmd, " ");
  714.         strcat(cmd, argv[i]);
  715.     }
  716.     cmdline[0] = strlen(cmd);
  717.  
  718.     if (vflag || nflag) {
  719.         fprintf(stderr, "%s %s\n", path, cmd);
  720.         fflush(stderr);
  721.         if (nflag)
  722.             return 0;
  723.     }
  724.  
  725.     i = Pexec(0, path, cmdline, 0L);
  726.  
  727.     return i;
  728. }
  729. #endif
  730.  
  731. /*
  732.  * docomp(f) - run the compiler on the given .c file
  733.  */
  734. docomp(f)
  735. char    *f;
  736. {
  737.     int    i;
  738.     char    *cpath, *sf;
  739.     char    tbuf[128];
  740.     char    sbuf[128];
  741.     int    notmp;        /* don't use temp directory */
  742.  
  743.     /*
  744.      * Don't use a temp directory if all we want is the assembly file,
  745.      * and we're not optimizing.
  746.      */
  747.     notmp = (Sflag && !Oflag);
  748.  
  749.     if ((cpath = findfile(path, CC)) == NULL) {
  750.         fprintf(stderr, "cc: can't find compiler program '%s'\n", CC);
  751.         exit(1);
  752.     }
  753.  
  754.     BEGARG();
  755.     ADDARG(CC);
  756.  
  757.     if (!notmp) {
  758.         sprintf(tbuf, "-T%s", tmp);
  759.         ADDARG(tbuf);
  760.     }
  761.  
  762.     if (pflag)
  763.         ADDARG("-P");
  764.  
  765.     for (i=0; i < hcc_cnt ;i++)
  766.         ADDARG(hccopt[i]);
  767.  
  768.     ADDARG(f);
  769.     ENDARG();
  770.  
  771.     sf = chsuf(f, ".s");
  772.     if (notmp)
  773.         strcpy(sbuf, sf);
  774.     else
  775.         sprintf(sbuf, "%s%c%s", tmp, SEPCHAR, sf);
  776.  
  777.     free(sf);
  778.  
  779.     if (docmd(cpath, av)) {
  780.         fremove(sbuf);
  781.         fprintf(stderr, "cc: compiler failed\n");
  782.         exit(1);
  783.     }
  784.  
  785.     if (!notmp)
  786.         frename(sbuf, Sfile);        /* fix the temp file name */
  787. }
  788.  
  789. /*
  790.  * doopt(f) - run the optimizer
  791.  *
  792.  * Only optimize files that were produced by the compiler.
  793.  */
  794. doopt(f)
  795. char    *f;
  796. {
  797.     int    i;
  798.     char    *opath;
  799.     char    *sf;
  800.     char    *of;        /* the output file name */
  801.  
  802.     if (!Oflag)
  803.         return;
  804.  
  805.     if ((opath = findfile(path, OPT)) == NULL) {
  806.         fprintf(stderr, "cc: can't find optimizer program '%s'\n", OPT);
  807.         exit(1);
  808.     }
  809.  
  810.     sf = chsuf(f, ".s");
  811.  
  812.     BEGARG();
  813.     ADDARG(OPT);
  814.  
  815.     for (i=0; i < top_cnt ;i++)
  816.         ADDARG(topopt[i]);
  817.  
  818.     /*
  819.      * The -g option turns off certain optimizations that make the
  820.      * debugger more difficult to use. These mostly involve messing
  821.      * with the stack frame, and make it harder to get accurate
  822.      * stack backtraces while stepping through a program.
  823.      */
  824.     if (gflag)
  825.         ADDARG("-g");
  826.  
  827.     ADDARG(Sfile);            /* the input file */
  828.  
  829.     of = (Sflag) ? sf : OSfile;    /* what's the output file name? */
  830.  
  831.     ADDARG(of);
  832.     ENDARG();
  833.  
  834.     if (docmd(opath, av)) {
  835.         if (Sflag) {    /* error is fatal if we wanted the assembly */
  836.             fremove(Sfile);
  837.             fremove(of);
  838.             fprintf(stderr, "cc: optimizer failed (aborting)\n");
  839.             exit(1);
  840.         } else {    /* try to press on... */
  841.             /*
  842.              * We continue by pretending we optimized the
  843.              * assembly file when we really didn't.
  844.              */
  845.             frename(Sfile, of);
  846.             fprintf(stderr, "cc: optimizer failed (continuing)\n");
  847.         }
  848.     }
  849.     free(sf);
  850.     fremove(Sfile);
  851. }
  852.  
  853. /*
  854.  * doasm() - run the assembler
  855.  *
  856.  * If 'istmp' is TRUE, the file we were given is a temporary. If we aren't
  857.  * working on a temp file, we may need to run the assembly through the C
  858.  * preprocessor. If the first character in the file is '#', we do it.
  859.  */
  860. doasm(f, istmp)
  861. char    *f;
  862. int    istmp;
  863. {
  864.     char    *strrchr(), *getenv();
  865.     int    i;
  866.     char    *dpath;
  867.     char    *sf;        /* file.s */
  868.     char    *infile;    /* the assembler input file */
  869.     char    *outfile;    /* the assembler output */
  870.  
  871.     if (Sflag)
  872.         return;
  873.  
  874.     outfile = chsuf(f, ".o");
  875.  
  876.     /*
  877.      * We want the -o option to be able to specify the output file
  878.      * from the assembler. This only makes sense if -c is given, and
  879.      * there is only one input file.
  880.      */
  881.     if (cflag && (output != NULL) && ((ncfiles+nsfiles) == 1))
  882.         outfile = output;
  883.  
  884.     /*
  885.      * Assume a temp file for now. May change...
  886.      */
  887.     infile = (Oflag) ? OSfile : Sfile;
  888.  
  889.     /*
  890.      * If this isn't a temp file, we may have to run the C preprocessor
  891.      * on it. If the first character of the file isn't '#', then we can
  892.      * skip it and just run the assembler.
  893.      */
  894.     if (!istmp) {
  895.  
  896. #ifdef    MINIX
  897.         int    fd;
  898.         char    c;
  899.  
  900.         if ((fd = open(f, 0)) < 0) {
  901.             fprintf(stderr, "cc: can't open file '%s'\n", f);
  902.             exit(1);
  903.         }
  904.         if (read(fd, &c, 1) != 1) {
  905.             fprintf(stderr, "cc: can't read file '%s'\n", f);
  906.             exit(1);
  907.         }
  908.         close(fd);
  909.  
  910.         if (c == '#') {
  911.             if ((dpath = findfile(lib, CPP)) == NULL) {
  912.                 fprintf(stderr,
  913.                     "cc: can't find C preprocessor '%s'\n",
  914.                     CPP);
  915.                 exit(1);
  916.             }
  917.             BEGARG();
  918.             ADDARG(dpath);
  919.     
  920.             /*
  921.              * The -P option removes "#file" and "#line" directives
  922.              * from the generated output.
  923.              */
  924.             ADDARG("-P");
  925.     
  926.             /*
  927.              * Include any pre-processor directives (-D, -I, or -U)
  928.              */
  929.             for (i=0; i < hcc_cnt ;i++)
  930.                 ADDARG(hccopt[i]);
  931.     
  932.             ADDARG(f);
  933.             ADDARG(">");
  934.             ADDARG(Sfile);
  935.             ENDARG();
  936.     
  937.             if (docmd(dpath, av)) {
  938.                 fprintf(stderr,
  939.                     "cc: preprocessor failed '%s'\n", f);
  940.                 fremove(Sfile);
  941.                 exit(1);
  942.             }
  943.             infile = Sfile;
  944.         } else
  945.             infile = f;
  946. #else
  947.         infile = f;
  948. #endif
  949.     }
  950.  
  951.     if ((dpath = findfile(path, ASM)) == NULL) {
  952.         fprintf(stderr, "cc: can't find assembler program '%s'\n", ASM);
  953.         exit(1);
  954.     }
  955.  
  956.  
  957.     BEGARG();
  958.     ADDARG(ASM);
  959.  
  960.     ADDARG(infile);
  961.     ADDARG("-o");
  962.     ADDARG(outfile);
  963.     ENDARG();
  964.  
  965.     if (docmd(dpath, av)) {
  966.         fprintf(stderr, "cc: assembler failed '%s'\n", infile);
  967.         if (infile != f)
  968.             fremove(infile);
  969.         exit(1);
  970.     }
  971.     free(outfile);
  972.  
  973.     if (infile != f)
  974.         fremove(infile);
  975. }
  976.  
  977. /*
  978.  * dold() - run the loader
  979.  */
  980. dold()
  981. {
  982.     FILE    *fp, *fopen();
  983.     int    i;
  984.     char    *lpath;
  985.     char    *s;
  986.     char    *l;
  987.  
  988.     if (cflag || Sflag)
  989.         return;
  990.  
  991.     /*
  992.      * Construct loader command file
  993.      */
  994.     if ((fp = fopen(Lfile, "w")) == NULL) {
  995.         fprintf(stderr, "cc: can't open loader temp file\n");
  996.         exit(1);
  997.     }
  998.  
  999.     if ((lpath = findfile(lib, CSU)) == NULL) {
  1000.         fprintf(stderr, "cc: can't find C startup code '%s'\n", CSU);
  1001.         exit(1);
  1002.     }
  1003.     fprintf(fp, "%s\n", lpath);
  1004.  
  1005.     for (i = 0; i < ncfiles ;i++) {
  1006.         s = chsuf(cfiles[i], ".o");
  1007.         fprintf(fp, "%s\n", s);
  1008.         free(s);
  1009.     }
  1010.     for (i = 0; i < nsfiles ;i++) {
  1011.         s = chsuf(sfiles[i], ".o");
  1012.         fprintf(fp, "%s\n", s);
  1013.         free(s);
  1014.     }
  1015.     for (i = 0; i < nofiles ;i++)
  1016.         fprintf(fp, "%s\n", ofiles[i]);
  1017.  
  1018.     for (i = 0; i < nlfiles ;i++) {
  1019.         if (isfile(lfiles[i])) {
  1020.             fprintf(fp, "%s\n", lfiles[i]);
  1021.         } else {
  1022.             lpath = findfile(lib, lfiles[i]);
  1023.             if (lpath == NULL) {
  1024.                 fprintf(stderr, "cc: can't find library '%s'\n", lfiles[i]);
  1025.                 exit(1);
  1026.             }
  1027.             fprintf(fp, "%s\n", lpath);
  1028.         }
  1029.     }
  1030.  
  1031.     if (rflag) {
  1032.         if ((lpath = findfile(lib, LIBM)) == NULL) {
  1033.             fprintf(stderr, "cc: can't find floating point library '%s'\n", LIBM);
  1034.             exit(1);
  1035.         }
  1036.         fprintf(fp, "%s\n", lpath);
  1037.     }
  1038.  
  1039.     if ((lpath = findfile(lib, LIBC)) == NULL) {
  1040.         fprintf(stderr, "cc: can't find C runtime library '%s'\n",LIBC);
  1041.         exit(1);
  1042.     }
  1043.     fprintf(fp, "%s\n", lpath);
  1044.  
  1045.     fclose(fp);
  1046.  
  1047.     if ((lpath = findfile(path, LD)) == NULL) {
  1048.         fprintf(stderr, "cc: can't find loader program '%s'\n", LD);
  1049.         exit(1);
  1050.     }
  1051.  
  1052.     BEGARG();
  1053.     ADDARG(LD);
  1054.     ADDARG("-p");
  1055.     ADDARG("-b");
  1056.     if (lsize != NULL)
  1057.         ADDARG(lsize);
  1058.     if (mflag)
  1059.         ADDARG("-m");
  1060.     if (!sflag)
  1061.         ADDARG("-t");
  1062.     if (rflag) {
  1063.         ADDARG("-u");
  1064.         ADDARG("__printf");
  1065.         ADDARG("-u");
  1066.         ADDARG("__scanf");
  1067.     }
  1068.     ADDARG("-o");
  1069.     ADDARG((output != NULL) ? output : DEFOUT);
  1070.     ADDARG("-f");
  1071.     ADDARG(Lfile);
  1072.  
  1073.     if (docmd(lpath, av)) {
  1074.         fprintf(stderr, "cc: loader failed\n");
  1075.         fremove(Lfile);
  1076.         fremove(output);
  1077.         exit(1);
  1078.     }
  1079.  
  1080.     for (i = 0; i < ncfiles ;i++) {
  1081.         s = chsuf(cfiles[i], ".o");
  1082.         fremove(s);
  1083.         free(s);
  1084.     }
  1085.  
  1086.     for (i = 0; i < nsfiles ;i++) {
  1087.         s = chsuf(sfiles[i], ".o");
  1088.         fremove(s);
  1089.         free(s);
  1090.     }
  1091.  
  1092.     fremove(Lfile);
  1093. }
  1094.  
  1095. int
  1096. frename(f1, f2)
  1097. char    *f1, *f2;
  1098. {
  1099.     if (vflag || nflag)
  1100.         fprintf(stderr, "mv %s %s\n", f1, f2);
  1101.  
  1102. #if    MINIX || UNIXHOST
  1103.     unlink(f2);
  1104.     link(f1, f2);
  1105.     unlink(f1);
  1106. #else
  1107.     rename(f1, f2);
  1108. #endif
  1109. }
  1110.  
  1111. fremove(f)
  1112. char    *f;
  1113. {
  1114.     if (vflag || nflag)
  1115.         fprintf(stderr, "rm %s\n", f);
  1116.  
  1117.     if (!tflag)
  1118.         unlink(f);
  1119. }
  1120.  
  1121. char *
  1122. strsave(string)
  1123. char    *string;
  1124. {
  1125.     char    *malloc(), *strcpy();
  1126.  
  1127.     return (strcpy(malloc((unsigned)(strlen(string)+1)), string));
  1128. }
  1129.