home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Icon 8.1 / msm-2 / iconc.sit / tmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-19  |  15.8 KB  |  628 lines  |  [TEXT/MPS ]

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