home *** CD-ROM | disk | FTP | other *** search
- /*
- * tmain.c - main program icon compiler.
- */
-
- #include <ctype.h>
- #include "::h:gsupport.h"
- #include "trans.h"
- #include "tree.h"
- #include "tcode.h"
- #include "tsym.h"
- #include "tproto.h"
-
- /*
- * Prototypes.
- */
- hidden novalue execute Params((char *ofile, char *efile, char **args));
- hidden FILE *open_out Params((char *fname));
- hidden novalue rmfile Params((char *fname));
- hidden novalue report Params((char *s));
- hidden novalue usage Params((noargs));
-
- #ifdef strlen
- #undef strlen /* pre-defined in some contexts */
- #endif /* strlen */
-
- char patchpath[MaxPath+18] = "%PatchStringHere->";
-
- /*
- * The following code is operating-system dependent [@tmain.01]. Definition
- * of refpath.
- */
-
- #if PORT
- /* something is needed */
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if UNIX || AMIGA || ATARI_ST || MACINTOSH || MSDOS || MVS || OS2 || VM
- char *refpath = RefPath;
- #endif /* UNIX ... */
-
- #if VMS
- char *refpath = "ICON_BIN:";
- #endif /* VMS */
-
- /*
- * End of operating-system specific code.
- */
-
- /*
- * Define global variables.
- */
-
- #define Global
- #define Init(v) = v
- #include "globals.h"
-
- /*
- * getopt() variables
- */
- extern int optindex; /* index into parent argv vector */
- extern int optopt; /* character checked for validity */
- extern char *optarg; /* argument associated with option */
-
- FILE *codefile; /* C output - primary file */
- FILE *inclfile; /* C output - include file */
-
- /*
- * main program
- */
- novalue main(argc,argv)
- int argc;
- char **argv;
- {
- int no_c_comp = 0; /* suppress C compile and link? */
- int errors = 0; /* compilation errors */
- char *cfile = NULL; /* name of C file - primary */
- char *hfile = NULL; /* name of C file - include */
- char *ofile = NULL; /* name of executable result */
- char *efile = NULL; /* stderr file */
-
- char *db_name = "rt.db"; /* data base name */
- char *incl_file = "rt.h"; /* header file name */
-
- char *db_path; /* path to data base */
- char *db_lst; /* list of private data bases */
- char *incl_path; /* path to header file */
- char *s, c1;
- char buf[MaxFileName]; /* file name construction buffer */
- int c;
- int ret_code;
- struct fileparts *fp;
-
- if (strlen(patchpath)>18)
- refpath = patchpath+18;
-
- /*
- * Process options.
- */
- while ((c = getopt(argc,argv,Options)) != EOF)
- switch (c) {
- case 'C': /* -C C-comp: C compiler*/
- c_comp = optarg;
- break;
- case 'L': /* Ignore: interpreter only */
- break;
- case 'S': /* Ignore: interpreter only */
- break;
- case 'T':
- just_type_trace = 1;
- break;
- case 'c': /* -c: produce C file only */
- no_c_comp = 1;
- break;
- case 'e': /* -e file: redirect stderr */
- efile = optarg;
- break;
- case 'f': /* -f: enable features */
- for (s = optarg; *s != '\0'; ++s) {
- switch (*s) {
- case 'a': /* -fa: enable all features */
- line_info = 1;
- debug_info = 1;
- err_conv = 1;
- largeints = 1;
- str_inv = 1;
- break;
- case 'd': /* -fd: enable debugging features */
- line_info = 1;
- debug_info = 1;
- break;
- case 'e': /* -fe: enable error conversion */
- err_conv = 1;
- break;
- case 'l': /* -fl: support large integers */
- largeints = 1;
- break;
- case 'n': /* -fn: enable line numbers */
- line_info = 1;
- break;
- case 's': /* -fs: enable full string invocation */
- str_inv = 1;
- break;
- default:
- quitf("-f option must be a, d, e, l, n, or s. found: %s",
- optarg);
- }
- }
- break;
- case 'm': /* -m: preprocess using m4(1) [UNIX] */
- m4pre = 1;
- break;
- case 'n': /* -n: disable optimizations */
- for (s = optarg; *s != '\0'; ++s) {
- switch (*s) {
- case 'a': /* -na: disable all optimizations */
- opt_cntrl = 0;
- allow_inline = 0;
- opt_sgnl = 0;
- do_typinfer = 0;
- break;
- case 'c': /* -nc: disable control flow opts */
- opt_cntrl = 0;
- break;
- case 'e': /* -ne: disable expanding in-line */
- allow_inline = 0;
- break;
- case 's': /* -ns: disable switch optimizations */
- opt_sgnl = 0;
- break;
- case 't': /* -nt: disable type inference */
- do_typinfer = 0;
- break;
- default:
- usage();
- }
- }
- break;
- case 'o': /* -o file: name output file */
- ofile = optarg;
- break;
- case 'p': /* -p C-opts: options for C comp */
- c_opts = optarg;
- break;
- case 'r': /* -r path: primary runtime system */
- refpath = optarg;
- break;
- case 's': /* -s: suppress informative messages */
- verbose = 0;
- break;
- case 't': /* -t: &trace = -1 */
- line_info = 1;
- debug_info = 1;
- trace = 1;
- break;
- case 'u': /* -u: warn about undeclared ids */
- uwarn = 1;
- break;
- case 'v': /* -v: set level of verbosity */
- if (sscanf(optarg, "%d%c", &verbose, &c1) != 1)
- quitf("bad operand to -v option: %s",optarg);
- break;
- default:
- case 'x': /* -x illegal until after file list */
- usage();
- }
-
- init(); /* initialize memory for translation */
- init_src(); /* initialize source file handling */
-
- /*
- * Load the data bases of information about run-time routines and
- * determine what libraries are needed for linking (these libraries
- * go before any specified on the command line).
- */
- #ifdef EnvVars
- db_lst = getenv("DBLIST");
- if (db_lst != NULL)
- db_lst = salloc(db_lst);
- #else /* EnvVars */
- db_lst = NULL;
- #endif /* EnvVars */
- s = db_lst;
- while (s != NULL) {
- db_lst = s;
- while (isspace(*db_lst))
- ++db_lst;
- if (*db_lst == '\0')
- break;
- for (s = db_lst; !isspace(*s) && *s != '\0'; ++s)
- ;
- if (*s == '\0')
- s = NULL;
- else
- *s++ = '\0';
- readdb(db_lst);
- addlib(salloc(makename(buf,SourceDir, db_lst, LibSuffix)));
- }
- db_path = (char *)alloc((unsigned int)strlen(refpath) + strlen(db_name) + 1);
- strcpy(db_path, refpath);
- strcat(db_path, db_name);
- readdb(db_path);
- addlib(salloc(makename(buf,SourceDir, db_path, LibSuffix)));
-
- /*
- * Scan the rest of the command line for file name arguments.
- */
- while (optindex < argc) {
- if (strcmp(argv[optindex],"-x") == 0) /* stop at -x */
- break;
- else if (strcmp(argv[optindex],"-") == 0)
- src_file("-"); /* "-" means standard input */
-
- /*
- * The following code is operating-system dependent [@tmain.02]. Check for
- * C linker options on the command line.
- */
-
- #if PORT
- /* something is needed */
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if UNIX
- else if (argv[optindex][0] == '-')
- addlib(argv[optindex]); /* assume linker option */
- #endif /* UNIX ... */
-
- #if AMIGA || ATARI_ST || MACINTOSH || MSDOS || MVS || OS2 || VM || VMS
- /*
- * Linker options on command line not supported.
- */
- #endif /* AMIGA || ATARI_ST || ... */
-
- /*
- * End of operating-system specific code.
- */
-
- else {
- fp = fparse(argv[optindex]); /* parse file name */
- if (*fp->ext == '\0' || smatch(fp->ext, SourceSuffix)) {
- makename(buf,SourceDir,argv[optindex], SourceSuffix);
- #if VMS
- strcat(buf, fp->version);
- #endif /* VMS */
- src_file(buf);
- }
- else
-
- /*
- * The following code is operating-system dependent [@tmain.03]. Pass
- * appropriate files on to linker.
- */
-
- #if PORT
- /* something is needed */
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if UNIX
- /*
- * Assume all files that are not Icon source go to linker.
- */
- addlib(argv[optindex]);
- #endif /* UNIX ... */
-
- #if AMIGA || ATARI_ST || MACINTOSH || MSDOS || MVS || OS2 || VM || VMS
- /*
- * Pass no files to the linker.
- */
- quitf("bad argument %s",argv[optindex]);
- #endif /* AMIGA || ATARI_ST || ... */
-
- /*
- * End of operating-system specific code.
- */
-
- }
- optindex++;
- }
-
- if (srclst == NULL)
- usage(); /* error -- no files named */
-
- if (ofile == NULL) { /* if no -o file, synthesize a name */
- if (strcmp(srclst->name,"-") == 0)
- ofile = salloc(makename(buf,TargetDir,"stdin",ExecSuffix));
- else
- ofile = salloc(makename(buf,TargetDir,srclst->name,ExecSuffix));
- } else { /* add extension if necessary */
- fp = fparse(ofile);
- if (*fp->ext == '\0' && *ExecSuffix != '\0')
- ofile = salloc(makename(buf,NULL,ofile,ExecSuffix));
- }
-
- /*
- * Make name of intermediate C files.
- */
- cfile = salloc(makename(buf,TargetDir,ofile,CSuffix));
- hfile = salloc(makename(buf,TargetDir,ofile,HSuffix));
-
- codefile = open_out(cfile);
- fprintf(codefile, "#include \"%s\"\n", hfile);
-
- inclfile = open_out(hfile);
- fprintf(inclfile, "#define COMPILER 1\n");
-
- incl_path = (char *)alloc((unsigned int)(strlen(refpath) +
- strlen(incl_file) + 1));
- strcpy(incl_path, refpath);
- strcat(incl_path, incl_file);
- fprintf(inclfile,"#include \"%s\"\n", incl_path);
-
- /*
- * Translate .icn files to make C file.
- */
- if ((verbose > 0) && !just_type_trace)
- report("Translating to C");
-
- errors = trans();
- if ((errors > 0) || just_type_trace) { /* exit if errors seen */
- rmfile(cfile);
- rmfile(hfile);
- if (errors > 0)
- exit(ErrorExit);
- else exit(NormalExit);
- }
-
- fclose(codefile);
- fclose(inclfile);
-
- /*
- * Compile and link C file.
- */
- if (no_c_comp) /* exit if no C compile wanted */
- exit(NormalExit);
-
- if (verbose > 0)
- report("Compiling and linking C code");
- ret_code = ccomp(cfile, ofile);
- if (ret_code == ErrorExit) {
- fprintf(stderr, "*** C compile and link failed ***\n");
- rmfile(ofile);
- }
-
- /*
- * Finish by removing C files.
- */
- rmfile(cfile);
- rmfile(hfile);
- rmfile(makename(buf,TargetDir,cfile,ObjSuffix));
-
- if (ret_code == NormalExit && optindex < argc) {
- if (verbose > 0)
- report("Executing");
- execute (ofile, efile, argv+optindex+1);
- }
-
- exit(ret_code);
- }
-
- /*
- * execute - execute compiled Icon program
- */
- static novalue execute(ofile,efile,args)
- char *ofile, *efile, **args;
- {
-
- #if !(MACINTOSH && MPW)
- int n;
- char **argv, **p;
-
- #if UNIX
- char buf[MaxFileName]; /* file name construction buffer */
-
- ofile = salloc(makename(buf,"./",ofile,ExecSuffix));
- #endif /* UNIX */
-
- for (n = 0; args[n] != NULL; n++) /* count arguments */
- ;
- p = argv = (char **)alloc((unsigned int)((n + 2) * sizeof(char *)));
-
- *p++ = ofile; /* set executable file */
-
- #if AMIGA && LATTICE
- *p = *args;
- while (*p++) {
- *p = *args;
- args++;
- }
- #else /* AMIGA && LATTICE */
- while (*p++ = *args++) /* copy args into argument vector */
- ;
- #endif /* AMIGA && LATTICE */
-
- *p = NULL;
-
- if (efile != NULL && !redirerr(efile)) {
- fprintf(stderr, "Unable to redirect &errout\n");
- fflush(stderr);
- }
-
- /*
- * The following code is operating-system dependent [@tmain.04]. It calls
- * the Icon program on the way out.
- */
-
- #if PORT
- /* something is needed */
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if AMIGA
- #if AZTEC_C
- execvp(ofile,argv);
- return;
- #endif /* AZTEC_C */
- #if LATTICE
- {
- struct ProcID procid;
- if (forkv(ofile,argv,NULL,&procid) == 0) {
- wait(&procid);
- return;
- }
- }
- #endif /* LATTICE */
- #endif /* AMIGA */
-
- #if ATARI_ST || MACINTOSH
- fprintf(stderr,"-x not supported\n"); fflush(stderr);
- #endif /* ATARI_ST || ... */
-
- #if MSDOS
- #if LATTICE || MICROSOFT || TURBO
- execvp(ofile,argv);
- #endif /* LATTICE || MICROSOFT || ... */
- #if MWC || HIGHC_386 || INTEL_386 || ZTC_386 || WATCOM
- fprintf(stderr,"-x not supported\n");
- fflush(stderr);
- #endif /* MWC || HIGHC_386 || ... */
- #endif /* MSDOS */
-
- #if MVS || VM
- #if SASC
- exit(sysexec(ofile, argv));
- #endif /* SASC */
- fprintf(stderr,"-x not supported\n");
- fflush(stderr);
- #endif /* MVS || VM */
-
- #if OS2 || UNIX || VMS
- execvp(ofile,argv);
- #endif /* OS2 || UNIX || VMS */
-
-
- /*
- * End of operating-system specific code.
- */
-
- quitf("could not run %s",ofile);
-
- #else /* !(MACINTOSH && MPW) */
- printf("-x not supported\n");
- #endif /* !(MACINZTOSH && MPW) */
-
- }
-
- static novalue report(s)
- char *s;
- {
-
- /*
- * The following code is operating-system dependent [@tmain.05]. Report
- * phase.
- */
-
- #if PORT
- fprintf(stderr,"%s:\n",s);
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if AMIGA || ATARI_ST || MSDOS || MVS || OS2 || UNIX || VM || VMS
- fprintf(stderr,"%s:\n",s);
- #endif /* AMIGA || ATARI_ST || ... */
-
- #if MACINTOSH
- #if MPW
- printf("Echo '%s:' > Dev:StdErr\n",s);
- #endif /* MPW */
- #if LSC
- fprintf(stderr,"%s:\n",s);
- #endif /* LSC */
- #endif /* MACINTOSH */
-
- /*
- * End of operating-system specific code.
- */
-
- }
-
- /*
- * rmfile - remove a file
- */
-
- static novalue rmfile(fname)
- char *fname;
- {
- /*
- * The following code is operating-system dependent [@tmain.06].
- * remove files.
- */
-
- #if PORT
- unlink(fname);
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if AMIGA || ATARI_ST || MSDOS || MVS || OS2 || UNIX || VM || VMS
- unlink(fname);
- #endif /* AMIGA || ATARI_ST ... */
-
- #if MACINTOSH
- #if MPW
- /*
- * MPW generates commands rather than doing the actions
- * at this time.
- */
- fprintf(stdout,"Delete %s\n", fname);
- #endif /* MPW */
- #if LSC
- unlink(fname);
- #endif /* LSC */
- #endif /* MACINTOSH */
-
- /*
- * End of operating-system specific code.
- */
- }
-
- /*
- * open_out - open a C output file and write identifying information
- * to the front.
- */
- static FILE *open_out(fname)
- char *fname;
- {
- FILE *f;
- static char *ident = "/*ICONC*/";
- int c;
- int i;
-
- /*
- * If the file already exists, make sure it is old output from iconc
- * before overwriting it. Note, this test doesn't work if the file
- * is writable but not readable.
- */
- f = fopen(fname, "r");
- if (f != NULL) {
- for (i = 0; i < strlen(ident); ++i) {
- c = getc(f);
- if (c == EOF)
- break;
- if ((char)c != ident[i])
- quitf("%s not in iconc format; rename or delete, and rerun", fname);
- }
- fclose(f);
- }
-
- f = fopen(fname, "w");
- if (f == NULL)
- quitf("cannot create %s", fname);
- fprintf(f, "%s\n", ident); /* write "belongs to iconc" comment */
- id_comment(f); /* write detailed comment for human readers */
- fflush(f);
- return f;
- }
-
- /*
- * Print an error message if called incorrectly. The message depends
- * on the legal options for this system.
- */
- static novalue usage()
- {
- fprintf(stderr,"usage: %s %s file ... [-x args]\n", progname, CUsage);
- exit(ErrorExit);
- }
-
-