/* * tmain.c - main program for translator and linker. */ #include "..\h\config.h" #include "general.h" #include "tproto.h" #include "..\h\paths.h" /* * Prototypes. */ hidden novalue execute Params((char *ofile,char *efile,char * *args)); hidden novalue report Params((char *s)); hidden novalue rmfiles Params((char **p)); hidden novalue usage Params((noargs)); /* * The following code is operating-system dependent [@tmain.01]. Include * files and such. */ #if PORT Deliberate syntax error #endif /* PORT */ #if AMIGA || HIGHC_386 || MSDOS || MVS || UNIX || VM || VMS /* nothing is needed */ #endif /* AMIGA || HIGHC_386 || ... */ #if ATARI_ST char *patharg; #endif /* ATARI_ST */ #if MACINTOSH #if MPW #include \* MPW3 - for unlink() *\ #include void SortOptions(); #endif /* MPW */ #endif /* MACINTOSH */ #if OS2 #include #endif /* OS2 */ /* * End of operating-system specific code. */ #if IntBits == 16 #ifdef strlen #undef strlen /* pre-defined in some contexts */ #endif /* strlen */ #endif /* Intbits == 16 */ #ifndef Iconx #define Iconx IconxPath #endif /* Iconx */ /* * Define global variables. */ #define Global #define Init(v) = v #include "globals.h" char *ofile = NULL; /* linker output file name */ /* * getopt() variables */ extern int optind; /* index into parent argv vector */ extern int optopt; /* character checked for validity */ extern char *optarg; /* argument associated with option */ /* * main program */ novalue main(argc,argv) int argc; char **argv; { int nolink = 0; /* suppress linking? */ int errors = 0; /* translator and linker errors */ char **tfiles, **tptr; /* list of files to translate */ char **lfiles, **lptr; /* list of files to link */ char **rfiles, **rptr; /* list of files to remove */ char *efile = NULL; /* stderr file */ char buf[MaxFileName]; /* file name construction buffer */ int c, n; struct fileparts *fp; #if MACINTOSH #if MPW InitCursorCtl(NULL); SortOptions(argv); #endif /* MPW */ #endif /* MACINTOSH */ /* * Process options. */ while ((c = getopt(argc,argv,Options)) != EOF) switch (c) { case 'c': /* -c: compile only (no linking) */ nolink = 1; break; case 'e': /* -e file: redirect stderr */ efile = optarg; break; case 'm': /* -m: preprocess using m4(1) [UNIX] */ m4pre = 1; break; case 'o': /* -o file: name output file */ ofile = optarg; break; #if ATARI_ST case 'p': /* -p path: iconx path [ATARI] */ patharg = optarg; break; #endif /* ATARI_ST */ case 's': /* -s: suppress informative messages */ silent = 1; break; case 'u': /* -u: warn about undeclared ids */ uwarn = 1; break; case 't': /* -t: turn on procedure tracing */ trace = -1; break; case 'L': /* -L: enable linker debugging */ #ifdef DeBugLinker Dflag = 1; #endif /* DeBugLinker */ break; case 'S': /* -Sxnnnn: set a size */ sizearg(optarg,argv); break; default: case 'x': /* -x illegal until after file list */ usage(); } /* * Allocate space for lists of file names. */ n = argc - optind + 1; tptr = tfiles = (char **)alloc((unsigned int)(n * sizeof(char *))); lptr = lfiles = (char **)alloc((unsigned int)(n * sizeof(char *))); rptr = rfiles = (char **)alloc((unsigned int)(2 * n * sizeof(char *))); /* * Scan file name arguments. */ while (optind < argc) { if (strcmp(argv[optind],"-x") == 0) /* stop at -x */ break; else if (strcmp(argv[optind],"-") == 0) { *tptr++ = "-"; /* "-" means standard input */ *lptr++ = *rptr++ = "stdin.u1"; *rptr++ = "stdin.u2"; } else { fp = fparse(argv[optind]); /* parse file name */ if (*fp->ext == '\0' || smatch(fp->ext, SourceSuffix)) { makename(buf,SourceDir,argv[optind], SourceSuffix); *tptr++ = salloc(buf); /* translate the .icn file */ makename(buf,TargetDir,argv[optind],U1Suffix); *lptr++ = *rptr++ = salloc(buf); /* link & remove .u1 */ makename(buf,TargetDir,argv[optind],U2Suffix); *rptr++ = salloc(buf); /* also remove .u2 */ } else if (smatch(fp->ext,U1Suffix) || smatch(fp->ext,U2Suffix) || smatch(fp->ext,USuffix)) { makename(buf,TargetDir,argv[optind],U1Suffix); *lptr++ = salloc(buf); } else quitf("bad argument %s",argv[optind]); } optind++; } *tptr = *lptr = *rptr = NULL; /* terminate filename lists */ if (lptr == lfiles) usage(); /* error -- no files named */ /* * Round hash table sizes to next power of two, and set masks for hashing. */ chsize = round2(chsize); cmask = chsize - 1; fhsize = round2(fhsize); fmask = fhsize - 1; ghsize = round2(ghsize); gmask = ghsize - 1; ihsize = round2(ihsize); imask = ihsize - 1; lhsize = round2(lhsize); lmask = lhsize - 1; /* * Translate .icn files to make .u1 and .u2 files. */ if (tptr > tfiles) { if (!silent) report("Translating"); errors = trans(tfiles); if (errors > 0) /* exit if errors seen */ exit(ErrorExit); } /* * Link .u1 and .u2 files to make an executable. */ if (nolink) /* exit if no linking wanted */ #if MACINTOSH #if MPW /* * Set type of translator output ucode (.u) files * to 'TEXT', so they can be easily viewed by editors. */ { char **p; void setfile(); for (p = rfiles; *p; ++p) setfile(*p,'TEXT','icon'); } #endif /* MPW */ #endif /* MACINTOSH */ exit(NormalExit); if (ofile == NULL) { /* if no -o file, synthesize a name */ ofile = salloc(makename(buf,TargetDir,lfiles[0],IcodeSuffix)); } else { /* add extension in necessary */ fp = fparse(ofile); #if !(MACINTOSH && MPW) /* This code provokes code generation bug in */ /* pre-release MPW 3.0 C compiler */ if (*fp->ext == '\0' && *IcodeSuffix != '\0') /* if no ext given, but wanted */ ofile = salloc(makename(buf,TargetDir,ofile,IcodeSuffix)); #endif /* !(MACINTOSH && MPW) */ if (*fp->ext == '\0' && *IcodeSuffix != '\0') /* if no ext given */ ofile = salloc(makename(buf,TargetDir,ofile,IcodeSuffix)); } if (!silent) report("Linking"); errors = ilink(lfiles,ofile); /* link .u files to make icode file */ /* * Finish by removing intermediate files. * Execute the linked program if so requested and if there were no errors. */ #if MACINTOSH #if MPW /* Set file type to TEXT so it will be executable as a script. */ setfile(ofile,'TEXT','icon'); #endif /* MPW */ #endif /* MACINTOSH */ rmfiles(rfiles); /* remove intermediate files */ if (errors > 0) { /* exit if linker errors seen */ unlink(ofile); exit(ErrorExit); } if (optind < argc) { if (!silent) report("Executing"); execute (ofile, efile, argv+optind+1); } exit(NormalExit); } /* * execute - execute iconx to run the icon program */ static novalue execute(ofile,efile,args) char *ofile, *efile, **args; { int n; char **argv, **p; for (n = 0; args[n] != NULL; n++) /* count arguments */ ; p = argv = (char **)alloc((unsigned int)((n + 5) * sizeof(char *))); *p++ = Iconx; /* set iconx pathname */ if (efile != NULL) { /* if -e given, copy it */ *p++ = "-e"; *p++ = efile; } *p++ = ofile; /* pass icode file name */ #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; /* * The following code is operating-system dependent [@tmain.02]. It calls * iconx on the way out. */ #if PORT /* something is needed */ Deliberate Syntax Error #endif /* PORT */ #if AMIGA #if AZTEC_C execvp(Iconx,argv); return; #endif /* AZTEC_C */ #if LATTICE { struct ProcID procid; if (forkv(Iconx,argv,NULL,&procid) == 0) { wait(&procid); return; } } #endif /* LATTICE */ #endif /* AMIGA */ #if ATARI_ST || MVS || VM /* Forkvp(Iconx,argv); */ /* return; */ fprintf(stderr,"-x not supported\n"); fflush(stderr); /* not implemented yet */ #endif /* ATARI_ST || MVS || VM */ #if HIGHC_386 fprintf(stderr,"-x not supported\n"); fflush(stderr); /* not implemented yet */ #endif /* HIGHC_386 */ #if MACINTOSH #if MPW /* * Something slightly different ... */ { char *s; char *mpwquote(); fputs(Iconx,stdout); for (p = argv + 1; *p; ++p) { putchar(' '); fputs(s = mpwquote(*p),stdout); free(s); } putchar('\n'); return; } #endif /* MPW */ #if LSC fprintf(stderr,"-x not supported\n"); fflush(stderr); #endif /* LSC */ #endif /* MACINTOSH */ #if MSDOS #if LATTICE || MICROSOFT || TURBO execvp(Iconx,argv); /* execute with path search */ #endif /* LATTICE || MICROSOFT || TURBO */ #if MWC fprintf(stderr,"-x not supported\n"); fflush(stderr); /* execall(Iconx,argv); */ #endif /* MWC */ #endif /* MSDOS */ #if MVS || VM #if SASC exit(sysexec(Iconx, argv)); #endif /* SASC */ #endif /* MVS || VM */ #if OS2 execvp(Iconx,argv); /* execute with path search */ #endif /* OS2 */ #if UNIX /* * If an ICONX environment variable is defined, use that. * If not, first try the predefined path, then search $PATH via execvp. */ if ((argv[0] = getenv("ICONX")) != NULL && argv[0][0] != '\0') { execv(argv[0], argv); /* exec file specified by $ICONX */ quitf("cannot execute $ICONX (%s)", argv[0]); } #ifdef HardWiredPaths #ifdef CRAY argv[0] = "iconx"; execv(Iconx, argv); #else /* CRAY */ argv[0] = Iconx; /* try predefined file */ execv(argv[0], argv); #endif /* CRAY */ #endif /* HardWiredPaths */ argv[0] = "iconx"; execvp(argv[0], argv); /* if no Iconx, search path for "iconx" */ #ifdef HardWiredPaths quitf("cannot run %s", Iconx); #else /* HardWiredPaths */ quitf("cannot find iconx", ""); #endif /* HardWiredPaths */ #endif /* UNIX */ #if VMS execv(Iconx,argv); #endif /* VMS */ /* * End of operating-system specific code. */ quitf("could not run %s",Iconx); } static novalue report(s) char *s; { /* * The following code is operating-system dependent [@tmain.03]. Report * phase. */ #if PORT fprintf(stderr,"%s:\n",s); Deliberate Syntax Error #endif /* PORT */ #if AMIGA || ATARI_ST || HIGHC_386 || MSDOS || MVS || OS2 || UNIX || VM || VMS fprintf(stderr,"%s:\n",s); #endif /* AMIGA || ATARI_ST || HIGHC_386 ... */ #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. */ } /* * rmfiles - remove a list of files */ static novalue rmfiles(p) char **p; { for (; *p; p++) { /* * The following code is operating-system dependent [@tmain.04]. * remove files. */ #if PORT unlink(*p); Deliberate Syntax Error #endif /* PORT */ #if AMIGA || ATARI_ST || HIGHC_386 || MSDOS || MVS || OS2 || UNIX || VM || VMS unlink(*p); #endif /* AMIGA || ATARI_ST ... */ #if MACINTOSH #if MPW /* * MPW generates commands rather than doing the actions * at this time. */ fprintf(stdout,"Delete %s\n", *p); #endif /* MPW */ #if LSC unlink(*p); #endif /* LSC */ #endif /* MACINTOSH */ /* * End of operating-system specific code. */ } } /* * 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, Usage); exit(ErrorExit); }