home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / src / iconc / cmain.c < prev    next >
C/C++ Source or Header  |  2002-01-18  |  16KB  |  624 lines

  1. /*
  2.  * cmain.c - main program icon compiler.
  3.  */
  4. #include "../h/gsupport.h"
  5. #include "ctrans.h"
  6. #include "ctree.h"
  7. #include "ccode.h"
  8. #include "csym.h"
  9. #include "cproto.h"
  10.  
  11. /*
  12.  * Prototypes.
  13.  */
  14. static void execute (char *ofile, char *efile, char **args);
  15. static FILE  *open_out (char *fname);
  16. static void rmfile  (char *fname);
  17. static void report  (char *s);
  18. static void usage   (void);
  19.  
  20. #ifdef strlen
  21. #undef strlen                /* pre-defined in some contexts */
  22. #endif                    /* strlen */
  23.  
  24. #ifdef ExpTools
  25. char *toolstr = "${TOOLS}";
  26. #endif                    /* ExpTools */
  27.  
  28. char *refpath;
  29.  
  30. char patchpath[MaxPath+18] = "%PatchStringHere->";
  31.  
  32. /*
  33.  *  Define global variables.
  34.  */
  35.  
  36. #define Global
  37. #define Init(v) = v
  38. #include "cglobals.h"
  39.  
  40. /*
  41.  * getopt() variables
  42.  */
  43. extern int optind;        /* index into parent argv vector */
  44. extern int optopt;        /* character checked for validity */
  45. extern char *optarg;        /* argument associated with option */
  46.  
  47. /*
  48.  *  main program
  49.  */
  50. int main(argc,argv)
  51. int argc;
  52. char **argv;
  53.    {
  54.    int no_c_comp = 0;            /* suppress C compile and link? */
  55.    int errors = 0;            /* compilation errors */
  56.    char *cfile = NULL;            /* name of C file - primary */
  57.    char *hfile = NULL;            /* name of C file - include */
  58.    char *ofile = NULL;            /* name of executable result */
  59.    char *efile = NULL;            /* stderr file */
  60.  
  61.    char *db_name = "rt.db";        /* data base name */
  62.    char *incl_file = "rt.h";        /* header file name */
  63.  
  64.    char *db_path;            /* path to data base */
  65.    char *db_lst;            /* list of private data bases */
  66.    char *incl_path;            /* path to header file */
  67.    char *s, c1;
  68.    char buf[MaxFileName];        /* file name construction buffer */
  69.  
  70. #ifdef ExpTools
  71.    char Buf[MaxFileName];
  72.    char *tools;                /* patch and TOOLS string buffer */
  73. #endif                    /* ExpTools */
  74.  
  75.    int c;
  76.    int ret_code;
  77.    struct fileparts *fp;
  78.  
  79. #ifdef ExpTools
  80.    /* needs rewrite */
  81.    if (strlen(patchpath)>18) {
  82.       refpath = patchpath+18;
  83.       if(!strncmp(refpath,toolstr,strlen(toolstr))) {    /* Is it TOOLS   */
  84.          refpath = refpath+strlen(toolstr);        /* skip TOOLS    */
  85.          if ((tools = getenv("TOOLS")) == NULL) {
  86.             fprintf(stderr,
  87.               "patchstr begins with \"${TOOLS}\" but ${TOOLS} has no value\n");
  88.             fprintf(stderr, "patchstr=%s\ncompilation aborted\n", refpath);
  89.             exit(EXIT_FAILURE);
  90.            } else strcpy(Buf,tools);
  91.          strcat(Buf,refpath);            /* append name   */
  92.      if (Buf[strlen(Buf)-1] != '/') strcat(Buf,"/");
  93.      refpath = Buf;                /* use refpath   */
  94.        }
  95.       }
  96.    fprintf(stderr,"iconc library files found in %s\n",refpath);
  97. #else                    /* ExpTools */
  98.    if ((int)strlen(patchpath) > 18)
  99.       refpath = patchpath+18;
  100.    else
  101.       refpath = relfile(argv[0], "/../");
  102. #endif                    /* ExpTools */
  103.  
  104.    /*
  105.     * Process options.
  106.     */
  107.    while ((c = getopt(argc,argv,"+C:ELS:Tce:f:mn:o:p:r:stuv:x")) != EOF)
  108.       switch (c) {
  109.          case 'C':            /* -C C-comp: C compiler*/
  110.             c_comp = optarg;
  111.             break;
  112.          case 'E':            /* -E: preprocess only */
  113.             pponly = 1;
  114.             no_c_comp = 1;
  115.             break;
  116.          case 'L':            /* Ignore: interpreter only */
  117.             break;
  118.          case 'S':            /* Ignore: interpreter only */
  119.             break;
  120.      case 'T':
  121.         just_type_trace = 1;
  122.         break;
  123.          case 'c':            /* -c: produce C file only */
  124.             no_c_comp = 1;
  125.             break;
  126.          case 'e':            /* -e file: redirect stderr */
  127.             efile = optarg;
  128.             break;
  129.          case 'f':            /* -f: enable features */
  130.             for (s = optarg; *s != '\0'; ++s) {
  131.                switch (*s) {
  132.                   case 'a':             /* -fa: enable all features */
  133.                      line_info = 1;
  134.                      debug_info = 1;
  135.                      err_conv = 1;
  136.                      largeints = 1;
  137.                      str_inv = 1;
  138.                      break;
  139.                   case 'd':             /* -fd: enable debugging features */
  140.                      line_info = 1;
  141.                      debug_info = 1;
  142.                      break;
  143.                   case 'e':             /* -fe: enable error conversion */
  144.                      err_conv = 1;
  145.                      break;
  146.                   case 'l':             /* -fl: support large integers */
  147.                      largeints = 1;
  148.                      break;
  149.                   case 'n':             /* -fn: enable line numbers */
  150.                      line_info = 1;
  151.                      break;
  152.                   case 's':        /* -fs: enable full string invocation */
  153.                      str_inv = 1;
  154.                      break;
  155.                   default:
  156.                      quitf("-f option must be a, d, e, l, n, or s. found: %s",
  157.                         optarg);
  158.                   }
  159.                }
  160.             break;
  161.          case 'm':            /* -m: preprocess using m4(1) [UNIX] */
  162.             m4pre = 1;
  163.             break;
  164.          case 'n':            /* -n: disable optimizations */
  165.             for (s = optarg; *s != '\0'; ++s) {
  166.                switch (*s) {
  167.                   case 'a':        /* -na: disable all optimizations */
  168.                      opt_cntrl = 0;
  169.                      allow_inline = 0;
  170.                      opt_sgnl = 0;
  171.                      do_typinfer = 0;
  172.                      break;
  173.                   case 'c':        /* -nc: disable control flow opts */
  174.                      opt_cntrl = 0;
  175.                      break;
  176.                   case 'e':        /* -ne: disable expanding in-line */
  177.                      allow_inline = 0;
  178.                      break;
  179.                   case 's':        /* -ns: disable switch optimizations */
  180.                      opt_sgnl = 0;
  181.                      break;
  182.                   case 't':        /* -nt: disable type inference */
  183.                      do_typinfer = 0;
  184.                      break;
  185.                   default:
  186.                      usage();
  187.                   }
  188.                }
  189.             break;
  190.          case 'o':            /* -o file: name output file */
  191.             ofile = optarg;
  192.             break;
  193.          case 'p':            /* -p C-opts: options for C comp */
  194.             if (*optarg == '\0')    /* if empty string, clear options */
  195.                c_opts = optarg;
  196.             else {            /* else append to current set */
  197.                s = (char *)alloc(strlen(c_opts) + 1 + strlen(optarg) + 1);
  198.                sprintf(s, "%s %s", c_opts, optarg);
  199.                c_opts = s;
  200.                }
  201.             break;
  202.          case 'r':            /* -r path: primary runtime system */
  203.             refpath = optarg;
  204.             break;
  205.          case 's':            /* -s: suppress informative messages */
  206.             verbose = 0;
  207.             break;
  208.          case 't':                      /* -t: &trace = -1 */
  209.             line_info = 1;
  210.             debug_info = 1;
  211.             trace = 1;
  212.             break;
  213.          case 'u':            /* -u: warn about undeclared ids */
  214.             uwarn = 1;
  215.             break;
  216.          case 'v':            /* -v: set level of verbosity */
  217.             if (sscanf(optarg, "%d%c", &verbose, &c1) != 1)
  218.                quitf("bad operand to -v option: %s",optarg);
  219.             break;
  220.          default:
  221.          case 'x':                      /* -x illegal until after file list */
  222.             usage();
  223.          }
  224.  
  225.    init();            /* initialize memory for translation */
  226.  
  227.    /*
  228.     * Load the data bases of information about run-time routines and
  229.     *  determine what libraries are needed for linking (these libraries
  230.     *  go before any specified on the command line).
  231.     */
  232.    db_lst = getenv("DBLIST");
  233.    if (db_lst != NULL)
  234.       db_lst = salloc(db_lst);
  235.    s = db_lst;
  236.    while (s != NULL) {
  237.       db_lst = s;
  238.       while (isspace(*db_lst))
  239.          ++db_lst;
  240.       if (*db_lst == '\0')
  241.          break;
  242.       for (s = db_lst; !isspace(*s) && *s != '\0'; ++s)
  243.          ;
  244.       if (*s == '\0')
  245.          s = NULL;
  246.       else
  247.          *s++ = '\0';
  248.       readdb(db_lst);
  249.       addlib(salloc(makename(buf,SourceDir, db_lst, LibSuffix)));
  250.       }
  251.    db_path = (char *)alloc((unsigned int)strlen(refpath) + strlen(db_name) + 1);
  252.    strcpy(db_path, refpath);
  253.    strcat(db_path, db_name);
  254.    readdb(db_path);
  255.    addlib(salloc(makename(buf,SourceDir, db_path, LibSuffix)));
  256.  
  257.    /*
  258.     * Scan the rest of the command line for file name arguments.
  259.     */
  260.    while (optind < argc)  {
  261.       if (strcmp(argv[optind],"-x") == 0)    /* stop at -x */
  262.          break;
  263.       else if (strcmp(argv[optind],"-") == 0)
  264.          src_file("-");                /* "-" means standard input */
  265.  
  266. /*
  267.  * The following code is operating-system dependent [@tmain.02].  Check for
  268.  *  C linker options on the command line.
  269.  */
  270.  
  271. #if PORT
  272.    /* something is needed */
  273. Deliberate Syntax Error
  274. #endif                    /* PORT */
  275.  
  276. #if UNIX
  277.       else if (argv[optind][0] == '-')
  278.          addlib(argv[optind]);        /* assume linker option */
  279. #endif                    /* UNIX ... */
  280.  
  281. #if AMIGA || MACINTOSH || MSDOS || OS2 || VMS
  282.       /*
  283.        * Linker options on command line not supported.
  284.        */
  285. #endif                    /* AMIGA || ... */
  286.  
  287. /*
  288.  * End of operating-system specific code.
  289.  */
  290.  
  291.       else {
  292.          fp = fparse(argv[optind]);        /* parse file name */
  293.          if (*fp->ext == '\0' || smatch(fp->ext, SourceSuffix)) {
  294.             makename(buf,SourceDir,argv[optind], SourceSuffix);
  295. #if VMS
  296.         strcat(buf, fp->version);
  297. #endif                    /* VMS */
  298.             src_file(buf);
  299.             }
  300.          else
  301.  
  302. /*
  303.  * The following code is operating-system dependent [@tmain.03].  Pass
  304.  *  appropriate files on to linker.
  305.  */
  306.  
  307. #if PORT
  308.    /* something is needed */
  309. Deliberate Syntax Error
  310. #endif                    /* PORT */
  311.  
  312. #if UNIX
  313.             /*
  314.              * Assume all files that are not Icon source go to linker.
  315.              */
  316.             addlib(argv[optind]);
  317. #endif                    /* UNIX ... */
  318.  
  319. #if AMIGA || MACINTOSH || MSDOS || OS2 || VMS
  320.             /*
  321.              * Pass no files to the linker.
  322.              */
  323.             quitf("bad argument %s",argv[optind]);
  324. #endif                    /* AMIGA || ... */
  325.  
  326. /*
  327.  * End of operating-system specific code.
  328.  */
  329.  
  330.          }
  331.       optind++;
  332.       }
  333.  
  334.    if (srclst == NULL)
  335.       usage();                /* error -- no files named */
  336.  
  337.    if (pponly) {
  338.       if (trans() == 0)
  339.      exit (EXIT_FAILURE);
  340.       else
  341.      exit (EXIT_SUCCESS);
  342.       }
  343.  
  344.    if (ofile == NULL)  {        /* if no -o file, synthesize a name */
  345.       if (strcmp(srclst->name,"-") == 0)
  346.          ofile = salloc(makename(buf,TargetDir,"stdin",ExecSuffix));
  347.       else
  348.          ofile = salloc(makename(buf,TargetDir,srclst->name,ExecSuffix));
  349.    } else {                /* add extension if necessary */
  350.       fp = fparse(ofile);
  351.       if (*fp->ext == '\0' && *ExecSuffix != '\0')
  352.          ofile = salloc(makename(buf,NULL,ofile,ExecSuffix));
  353.    }
  354.  
  355.    /*
  356.     * Make name of intermediate C files.
  357.     */
  358.    cfile = salloc(makename(buf,TargetDir,ofile,CSuffix));
  359.    hfile = salloc(makename(buf,TargetDir,ofile,HSuffix));
  360.  
  361.    codefile = open_out(cfile);
  362.    fprintf(codefile, "#include \"%s\"\n", hfile);
  363.  
  364.    inclfile = open_out(hfile);
  365.    fprintf(inclfile, "#define COMPILER 1\n");
  366.  
  367.    incl_path = (char *)alloc((unsigned int)(strlen(refpath) +
  368.        strlen(incl_file) + 1));
  369.    strcpy(incl_path, refpath);
  370.    strcat(incl_path, incl_file);
  371.    fprintf(inclfile,"#include \"%s\"\n", incl_path);
  372.  
  373.    /*
  374.     * Translate .icn files to make C file.
  375.     */
  376.    if ((verbose > 0) && !just_type_trace)
  377.       report("Translating to C");
  378.  
  379.    errors = trans();
  380.    if ((errors > 0) || just_type_trace) {    /* exit if errors seen */
  381.       rmfile(cfile);
  382.       rmfile(hfile);
  383.       if (errors > 0)
  384.      exit(EXIT_FAILURE);
  385.       else exit(EXIT_SUCCESS);
  386.       }
  387.  
  388.    fclose(codefile);
  389.    fclose(inclfile);
  390.  
  391.    /*
  392.     * Compile and link C file.
  393.     */
  394.    if (no_c_comp)            /* exit if no C compile wanted */
  395.       exit(EXIT_SUCCESS);
  396.  
  397. #if !MSDOS
  398.    if (verbose > 0)
  399.       report("Compiling and linking C code");
  400. #endif                    /* !MSDOS */
  401.  
  402.    ret_code = ccomp(cfile, ofile);
  403.    if (ret_code == EXIT_FAILURE) {
  404.       fprintf(stderr, "*** C compile and link failed ***\n");
  405.       rmfile(ofile);
  406.       }
  407.  
  408.    /*
  409.     * Finish by removing C files.
  410.     */
  411. #if !MSDOS
  412.    rmfile(cfile);
  413.    rmfile(hfile);
  414. #endif                    /* !MSDOS */
  415.    rmfile(makename(buf,TargetDir,cfile,ObjSuffix));
  416.  
  417.    if (ret_code == EXIT_SUCCESS && optind < argc)  {
  418.       if (verbose > 0)
  419.          report("Executing");
  420.       execute (ofile, efile, argv+optind+1);
  421.       }
  422.  
  423.    return ret_code;
  424.    }
  425.  
  426. /*
  427.  * execute - execute compiled Icon program
  428.  */
  429. static void execute(ofile,efile,args)
  430. char *ofile, *efile, **args;
  431.    {
  432.  
  433. #if !(MACINTOSH && MPW)
  434.    int n;
  435.    char **argv, **p;
  436.  
  437. #if UNIX
  438.       char buf[MaxFileName];        /* file name construction buffer */
  439.  
  440.       ofile = salloc(makename(buf,"./",ofile,ExecSuffix));
  441. #endif                    /* UNIX */
  442.  
  443.    for (n = 0; args[n] != NULL; n++)    /* count arguments */
  444.       ;
  445.    p = argv = (char **)alloc((unsigned int)((n + 2) * sizeof(char *)));
  446.  
  447.    *p++ = ofile;            /* set executable file */
  448.  
  449. #if AMIGA && LATTICE
  450.    *p = *args;
  451.    while (*p++) {
  452.       *p = *args;
  453.       args++;
  454.    }
  455. #else                    /* AMIGA && LATTICE */
  456.    while (*p++ = *args++)        /* copy args into argument vector */
  457.       ;
  458. #endif                    /* AMIGA && LATTICE */
  459.  
  460.    *p = NULL;
  461.  
  462.    if (efile != NULL && !redirerr(efile)) {
  463.       fprintf(stderr, "Unable to redirect &errout\n");
  464.       fflush(stderr);
  465.       }
  466.  
  467. /*
  468.  * The following code is operating-system dependent [@tmain.04].  It calls
  469.  *  the Icon program on the way out.
  470.  */
  471.  
  472. #if PORT
  473.    /* something is needed */
  474. Deliberate Syntax Error
  475. #endif                    /* PORT */
  476.  
  477. #if AMIGA
  478. #if AZTEC_C
  479.       execvp(ofile,argv);
  480.       return;
  481. #endif                    /* AZTEC_C */
  482. #if LATTICE
  483.       {
  484.       struct ProcID procid;
  485.       if (forkv(ofile,argv,NULL,&procid) == 0) { 
  486.          wait(&procid);
  487.          return;
  488.          }
  489.       }
  490. #endif                    /* LATTICE */
  491. #endif                    /* AMIGA */
  492.  
  493. #if MACINTOSH
  494.       fprintf(stderr,"-x not supported\n"); fflush(stderr);
  495. #endif                    /* MACINTOSH */
  496.  
  497. #if MSDOS
  498. #if MICROSOFT || TURBO || BORLAND_286 || BORLAND_386
  499.       execvp(ofile,argv);
  500. #endif                    /* MICROSOFT || ... */
  501. #if HIGHC_386 || INTEL_386 || ZTC_386 || WATCOM
  502.       fprintf(stderr,"-x not supported\n");
  503.       fflush(stderr);
  504. #endif                    /* HIGHC_386 || ... */
  505. #endif                    /* MSDOS */
  506.  
  507. #if OS2 || UNIX || VMS
  508.       execvp(ofile,argv);
  509. #endif                    /* OS2 || UNIX || VMS */
  510.  
  511.  
  512. /*
  513.  * End of operating-system specific code.
  514.  */
  515.  
  516.    quitf("could not run %s",ofile);
  517.  
  518. #else                    /* !(MACINTOSH && MPW) */
  519.    printf("-x not supported\n");
  520. #endif                    /* !(MACINZTOSH && MPW) */
  521.  
  522.    }
  523.  
  524. static void report(s)
  525. char *s;
  526.    {
  527.  
  528. /*
  529.  * The following code is operating-system dependent [@tmain.05].  Report
  530.  *  phase.
  531.  */
  532.  
  533. #if PORT
  534.    fprintf(stderr,"%s:\n",s);
  535. Deliberate Syntax Error
  536. #endif                    /* PORT */
  537.  
  538. #if AMIGA || MSDOS || OS2 || UNIX || VMS
  539.    fprintf(stderr,"%s:\n",s);
  540. #endif                    /* AMIGA || ... */
  541.  
  542. #if MACINTOSH
  543. #if MPW
  544.    printf("Echo '%s:' > Dev:StdErr\n",s);
  545. #endif                    /* MPW */
  546. #if LSC
  547.    fprintf(stderr,"%s:\n",s);
  548. #endif                    /* LSC */
  549. #endif                    /* MACINTOSH */
  550.  
  551. /*
  552.  * End of operating-system specific code.
  553.  */
  554.  
  555.    }
  556.  
  557. /*
  558.  * rmfile - remove a file
  559.  */
  560.  
  561. static void rmfile(fname)
  562. char *fname;
  563.    {
  564.  
  565. #if MACINTOSH && MPW
  566.       /*
  567.        * MPW generates commands rather than doing the actions
  568.        *  at this time.
  569.        */
  570.    fprintf(stdout,"Delete %s\n", fname);
  571. #else                    /* MACINTOSH && MPW */
  572.    remove(fname);
  573. #endif                    /* MACINTOSH && MPW */
  574.  
  575.    }
  576.  
  577. /*
  578.  * open_out - open a C output file and write identifying information
  579.  *  to the front.
  580.  */
  581. static FILE *open_out(fname)
  582. char *fname;
  583.    {
  584.    FILE *f;
  585.    static char *ident = "/*ICONC*/";
  586.    int c;
  587.    int i;
  588.  
  589.    /*
  590.     * If the file already exists, make sure it is old output from iconc
  591.     *   before overwriting it. Note, this test doesn't work if the file
  592.     *   is writable but not readable.
  593.     */
  594.    f = fopen(fname, "r");
  595.    if (f != NULL) {
  596.       for (i = 0; i < (int)strlen(ident); ++i) {
  597.          c = getc(f);
  598.          if (c == EOF)
  599.              break;
  600.          if ((char)c != ident[i])
  601.             quitf("%s not in iconc format; rename or delete, and rerun", fname);
  602.          }
  603.       fclose(f);
  604.       }
  605.  
  606.    f = fopen(fname, "w");
  607.    if (f == NULL)
  608.       quitf("cannot create %s", fname);
  609.    fprintf(f, "%s\n", ident); /* write "belongs to iconc" comment */
  610.    id_comment(f);             /* write detailed comment for human readers */
  611.    fflush(f);
  612.    return f;
  613.    }
  614.  
  615. /*
  616.  * Print an error message if called incorrectly.  The message depends
  617.  *  on the legal options for this system.
  618.  */
  619. static void usage()
  620.    {
  621.    fprintf(stderr,"usage: %s %s file ... [-x args]\n", progname, CUsage);
  622.    exit(EXIT_FAILURE);
  623.    }
  624.