home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / iconc / cmain.c < prev    next >
C/C++ Source or Header  |  1996-03-22  |  18KB  |  673 lines

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