home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)semantics.c 1.10 10/24/89
- */
- #include "assert.h"
- #include "scan.h"
- #include "nodes.h"
- #include "error.h"
- #include "opNames.h"
- #include "flags.h"
- #include "system.h"
- #include "trace.h"
- #include "option.h"
- #include "builtins.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/param.h>
- #include <sys/file.h>
- #include <a.out.h>
- #include <errno.h>
- #undef NULL
- #include "ndbm.h"
- #undef NULL
- #define NULL 0
-
- extern char *emDirectory, *emdbDirectory;
-
- static struct {
- Boolean shouldDo;
- int verboseLevel;
- char *name;
- } treePasses[] = {
- TRUE , 1, "parsing",
- TRUE , 1, "removing sugar",
- TRUE , 1, "processing symbols",
- TRUE , 1, "doing imports",
- TRUE , 1, "doing manifests",
- TRUE , 1, "assigning types",
- TRUE , 1, "checking types",
- TRUE , 1, "inline detection",
- FALSE, 0, "figuring concrete types",
- FALSE, 0, "figuring locals",
- TRUE , 1, "doing exports",
- FALSE, 0, "code generation",
- 0, 0, 0};
-
- extern void removeSugar(), processSymbols(), doManifest(),
- DisplayTree(), assignTypes(), typeCheck(), detectInlines(),
- multiPassManifest(), doSymbolGraph(),
- doKnowCTs(), doKnowManifests(),
- doKnowLocals(), newAssignTypes();
-
- extern char *makeOIDDotoFileName();
-
- char workingDirectory[MAXPATHLEN];
- #define MAXDOTSFILES 100
- typedef struct sDotsRec {
- Boolean alreadyGenerated;
- int codeFileNumber;
- OID codeOID;
- OID createdOID;
- } DotsRec, *DotsRecPtr;
-
- DotsRec dotsFiles[MAXDOTSFILES];
- static int nextDotsFile = 0;
-
- static void doTree(name, fTreeFile, Root)
- char *name;
- FILE *fTreeFile;
- NodePtr Root;
- {
- register int stage;
- for (stage = 0;
- treePasses[stage].name && strcmp(name, treePasses[stage].name);
- stage++) ;
- assert(treePasses[stage].name != NULL);
- if (treePasses[stage].shouldDo) {
- if (tflag) {
- TRACE0(passes, 1, "Writing the tree file.");
- fprintf(fTreeFile, "After %s\n", treePasses[stage].name);
- DisplayTree(fTreeFile, Root, treePasses[stage].verboseLevel, 9999);
- }
- }
- }
-
- extern NodePtr readTree();
- void doExports(), doImports(), generateCode();
-
- extern int nextObjectNumber;
-
- FILE *treeFile = NULL;
- FILE *codeFile = NULL;
- char *codeFileName = NULL, *codeFileRoot;
-
- /*
- * Call the program named f with the arguments v, and stdin and out
- * directed to inf and outf respectively.
- */
- #include <sys/wait.h>
-
- int callsys(f, v, inf, outf)
- char *f, **v, *inf, *outf;
- {
- int t;
- union wait status;
- register char **cpp;
-
- IFTRACE(passes, 5) {
- fprintf(stdout, "%s:", f);
- for (cpp = v; *cpp != 0; cpp++) fprintf(stdout, " %s", *cpp);
- if (inf != NULL) fprintf(stdout, " < %s", inf);
- if (outf != NULL) fprintf(stdout, " > %s", outf);
- fprintf(stdout, "\n");
- }
- t = vfork();
- if (t == -1) {
- fprintf(stderr, "No more processes\n");
- return (100);
- }
- if (t == 0) { /* I am the child */
- int infd, outfd;
- if (inf != NULL) {
- infd = open(inf, O_RDONLY, 0666);
- (void) dup2(infd, 0);
- }
- if (outf != NULL) {
- outfd = open(outf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
- (void) dup2(outfd, 1);
- }
- execv(f, v);
- fprintf(stderr, "Can't find %s\n", f);
- (void) fflush(stderr);
- _exit(100);
- }
- while (t != wait(&status))
- ;
- if ((t=status.w_termsig) != 0 && t!=14) {
- if (t!=2) {
- fprintf(stderr, "Fatal error in %s\n", f);
- }
- }
- return (status.w_retcode);
- }
-
- extern int link(), symlink();
-
- void myLink(existing, new, symbolic, Root)
- char *existing, *new;
- Boolean symbolic;
- NodePtr Root;
- {
- int (*linkroutine)() = symbolic ? symlink : link;
- char *linkroutinename = symbolic ? "symlink" : "link";
-
- if ((*linkroutine)(existing, new) < 0) {
- if (errno == EEXIST) {
- if (unlink(new) < 0) {
- ErrorMessage(Root, "Cannot unlink %s: %s", new,
- errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
- } else {
- if ((*linkroutine)(existing, new) < 0) {
- ErrorMessage(Root, "Cannot %s %s to %s: %s", linkroutinename, new,
- existing,
- errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
- }
- }
- } else {
- ErrorMessage(Root, "Cannot %s %s to %s: %s", linkroutinename, new, existing,
- errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
- }
- }
- }
-
- static int finishedPass;
- #define TOTALPASSES 14
-
- void checkCompletion()
- {
- if (! Cflag) return;
- if (Cvalue <= 0 && TOTALPASSES + Cvalue <= finishedPass) exit(0);
- else if (Cvalue > 0 && finishedPass >= Cvalue) exit(0);
- }
- extern void initializeOwnStuff();
-
- void DoneParsing(Root)
- NodePtr Root;
- {
- char *treeFileName, *p;
- char *realDotoFileName, *createdDotoFileName;
- char **systemBuffer, **execvec;
- char binpath[100];
- int systemResult, i;
- FILE *dotgFile;
-
- CheckForErrors();
-
- if (!strcmp(currentFileName, "<stdin>")) {
- codeFileRoot = malloc(6);
- strcpy(codeFileRoot, "stdin");
- } else {
- for (p = currentFileName; *p; p++) ;
- for (p--; *p != '/' && p >= currentFileName; p--) ;
- if (*p == '/') p++; else p = currentFileName;
- codeFileRoot = (char *) malloc((unsigned)strlen(p) + 1);
- strcpy(codeFileRoot, p);
- for (p = codeFileRoot; *p; p++) ;
- for (p--; *p != '.'; --p) ;
- if (p > codeFileRoot) *p = '\0';
- }
- if (tflag) {
- treeFileName = (char *) malloc((unsigned)strlen(codeFileRoot) + 6);
- (void) strcpy(treeFileName, codeFileRoot);
- (void) strcat(treeFileName, ".tree");
- treeFile = fopen(treeFileName, "w");
- if (treeFile == NULL) {
- fprintf(stderr, "Can't open the tree file (%s).\n", treeFileName);
- exit (1);
- }
- free(treeFileName);
- }
-
- doTree("parsing", treeFile, Root);
- finishedPass = 1;
- checkCompletion();
-
- TRACE0(passes, 1, "Removing sugar.");
- removeSugar(&Root);
- doTree("removing sugar", treeFile, Root);
- CheckForErrors();
- finishedPass = 2;
- checkCompletion();
-
- TRACE0(passes, 1, "Resolving symbols.");
- processSymbols(Root);
- doTree("processing symbols", treeFile, Root);
- CheckForErrors();
- finishedPass = 3;
- checkCompletion();
-
- TRACE0(passes, 1, "Doing imports.");
- doImports(Root);
- doTree("doing imports", treeFile, Root);
- CheckForErrors();
- finishedPass = 4;
- checkCompletion();
-
- initializeOwnStuff();
-
- TRACE0(passes, 1, "Doing manifests.");
- doKnowManifests(Root);
- doTree("doing manifests", treeFile, Root);
- CheckForErrors();
- finishedPass = 5;
- checkCompletion();
-
-
- TRACE0(passes, 1, "Assigning types.");
- newAssignTypes(Root, 9999);
- doTree("assigning types", treeFile, Root);
- CheckForErrors();
- finishedPass = 6;
- checkCompletion();
-
- if (! loadedDummyBuiltins) {
- TRACE0(passes, 1, "Checking the types.");
- typeCheck(Root);
- doTree("checking types", treeFile, Root);
- CheckForErrors();
- }
- finishedPass = 7;
- checkCompletion();
-
- if (cflag && !bflag) return;
-
- /*
- * Inlineable routines and signal and continue detection.
- */
- TRACE0(passes, 1, "Inline detection.");
- detectInlines(Root);
- doTree("inline detection", treeFile, Root);
- CheckForErrors();
- finishedPass = 8;
- checkCompletion();
-
- doSymbolGraph(Root);
-
- if (OPTION(knowct, 1) && !loadedDummyBuiltins) {
- TRACE0(passes, 1, "Figuring out Concrete Types.");
- doKnowCTs(Root);
- doTree("figuring concrete types", treeFile, Root);
- CheckForErrors();
- finishedPass = 9;
- checkCompletion();
- }
-
- if (OPTION(locals, 1) && !loadedDummyBuiltins) {
- TRACE0(passes, 1, "Figuring out Locals.");
- doKnowLocals(Root);
- doTree("figuring locals", treeFile, Root);
- CheckForErrors();
- finishedPass = 10;
- checkCompletion();
- }
-
- TRACE0(passes, 1, "Doing exports.");
- doExports(Root);
- doTree("doing exports", treeFile, Root);
- CheckForErrors();
- finishedPass = 11;
- checkCompletion();
-
- if (cflag) return;
-
- TRACE0(passes, 1, "Code generation.");
- codeFileName = (char *) malloc((unsigned)strlen(codeFileRoot) + 16);
-
- generateCode(Root);
- doTree("code generation", treeFile, Root);
- free(codeFileName);
- if (codeFile != NULL && fclose(codeFile) == EOF) assert(FALSE);
- CheckForErrors();
- finishedPass = 12;
- checkCompletion();
-
- systemBuffer = (char **) malloc((unsigned) 6 * sizeof(char *));
- systemBuffer[1] = (char *)malloc((unsigned) strlen(codeFileRoot) + 10);
- systemBuffer[5] = (char *)malloc((unsigned) strlen(codeFileRoot) + 10);
-
- systemBuffer[0] = "as";
- systemBuffer[2] = "-o";
- systemBuffer[3] = (char *) NULL;
- systemBuffer[4] = (char *) NULL;
-
- TRACE0(passes, 1, "Assembling.");
- assert(nextObjectNumber == nextDotsFile);
- for (i = 0; i < nextDotsFile; i++) {
- TRACE5(doto, 3,
- "i=%d alreadyGenerated=%s codeFileNumber=%d codeOID=0x%08x createdOID=0x%08x",
- i, dotsFiles[i].alreadyGenerated ? "true" : "false",
- dotsFiles[i].codeFileNumber, dotsFiles[i].codeOID,
- dotsFiles[i].createdOID);
- sprintf(systemBuffer[5], "%s.%d.o", codeFileRoot, i);
- realDotoFileName = makeOIDDotoFileName(dotsFiles[i].codeOID);
- if (! dotsFiles[i].alreadyGenerated) {
- sprintf(systemBuffer[1], "%s.%d.s", codeFileRoot, i);
- systemBuffer[3] = realDotoFileName;
- systemResult =
- callsys("/bin/as", systemBuffer, (char *)NULL, (char *)NULL);
- if (systemResult != 0) {
- ErrorMessage(Root, "As error");
- } else {
- if (dotsFiles[i].createdOID != 0) {
- /* we need to link the other name to the original name */
- createdDotoFileName = makeOIDDotoFileName(dotsFiles[i].createdOID);
- myLink(realDotoFileName, createdDotoFileName, FALSE, Root);
- free(createdDotoFileName);
- }
- #ifdef sun
- /* we need to fix the header */
- {
- int inf;
- struct exec header;
- inf = open(realDotoFileName, O_RDWR, 0);
- assert(inf != NULL);
- if (read(inf, &header, sizeof(header)) != sizeof(header))
- assert(FALSE);
- #define CHECK(S) if (!(S)) assert(FALSE);
- CHECK(header.a_text != 0);
- CHECK(header.a_data == 0);
- CHECK(header.a_drsize == 0);
- header.a_data = header.a_text;
- header.a_drsize = header.a_trsize;
- header.a_text = 0;
- header.a_trsize = 0;
- if (lseek(inf, 0L, 0) < 0) assert(FALSE);
- if (write(inf, &header, sizeof(header)) != sizeof(header)) assert(FALSE);
- (void) close(inf);
- }
- #endif
- }
- }
- if (zflag) myLink(realDotoFileName, systemBuffer[5], TRUE, Root);
- free(realDotoFileName);
- }
- CheckForErrors();
-
- if (!zflag) {
- for (i = 0; i < nextObjectNumber; i++) {
- if (dotsFiles[i].alreadyGenerated) continue;
- sprintf(systemBuffer[1], "%s.%d.s", codeFileRoot, i);
- systemResult = unlink(systemBuffer[1]);
- if (systemResult < 0) {
- ErrorMessage(Root, "Cannot unlink %s: %s", systemBuffer[1],
- errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
- }
- }
- }
-
- sprintf(systemBuffer[1], "%s.g", codeFileRoot);
- if ((dotgFile = fopen(systemBuffer[1], "w")) == NULL) {
- ErrorMessage(Root, "Cannot create %s", systemBuffer[1]);
- } else {
- struct stat st;
- DBM *dotgDBM;
- char dotgDBMName[1024];
- datum keydatum, valuedatum;
- fprintf(dotgFile, "#!%sbin/re\n", emDirectory);
- fprintf(dotgFile, "0x%08xzzzzzz\n", dotsFiles[0].codeOID);
- fstat(fileno(dotgFile), &st);
- fchmod(fileno(dotgFile), st.st_mode | 0111);
- fclose(dotgFile);
- sprintf(dotgDBMName, "%s/DB/dotgdb", emdbDirectory);
- if ((dotgDBM = dbm_open(dotgDBMName, O_RDWR | O_CREAT, 0777)) <= 0) {
- ErrorMessage(Root, "Can't open the data base file %s\n", dotgDBMName);
- } else {
- if (getwd(dotgDBMName) == 0) {
- ErrorMessage(Root, "Can't determine the current directory: %s\n",
- dotgDBMName);
- } else {
- keydatum.dptr = dotgDBMName;
- keydatum.dsize = strlen(dotgDBMName) + 1;
- valuedatum.dptr = "x";
- valuedatum.dsize = 2;
- if (dbm_store(dotgDBM, keydatum, valuedatum, DBM_REPLACE) < 0) {
- ErrorMessage(Root, "Can't write to .g filename database");
- }
- }
- dbm_close(dotgDBM);
- }
- }
-
- finishedPass = 13;
- checkCompletion();
-
- TRACE0(passes, 1, "Invoking the kernel.");
- execvec = (char **) malloc(10 * sizeof(char *));
- execvec[0] = "runec";
- i = 1;
- if (vflag) execvec[i++] = "-v";
- if (iflag) execvec[i++] = "-i";
- if (mflag) {
- execvec[i++] = "-m";
- execvec[i++] = mdata;
- }
- execvec[i++] = systemBuffer[1];
- execvec[i] = (char *) 0;
-
- sprintf(binpath, "%s/bin/runec", emDirectory);
- execv(binpath, execvec);
- assert(FALSE);
-
- CheckForErrors();
- finishedPass = 14;
- checkCompletion();
-
- free(systemBuffer[1]);
- free(systemBuffer[7]);
- free(codeFileRoot);
- }
-
- void nextCodeFileName()
- {
- if (codeFile != NULL) {
- if (fclose(codeFile) == EOF) assert(FALSE);
- codeFile = NULL;
- }
- sprintf(codeFileName, "%s.%d.s", codeFileRoot, nextObjectNumber);
- }
-
- extern Boolean doGenerateCode, environmentWasImported();
-
- /*
- * This one either:
- * 1. returns TRUE
- * 2. returns FALSE,opens the codeFile for .s writing
- * In either case it fills in the dotsFiles structure so that we can do the
- * right thing later.
- */
- Boolean easyGenerateObject(obj, fCodeOID, fOID)
- NodePtr obj;
- OID fCodeOID, fOID;
- {
- char *realDotoFileName;
- static Boolean theAnswer;
- struct stat statbuf;
- int sysresult;
-
- if (doGenerateCode) return(theAnswer);
- if (nextDotsFile >= MAXDOTSFILES) {
- fprintf(stderr, "Too many output code files.\n");
- }
- assert(fCodeOID != 0);
- if (bflag) {
- if (environmentWasImported(fCodeOID)) {
- theAnswer = TRUE;
- } else {
- theAnswer = FALSE;
- }
- } else {
- realDotoFileName = makeOIDDotoFileName(fCodeOID);
- theAnswer = TRUE;
- sysresult = stat(realDotoFileName, &statbuf);
- if (sysresult < 0) {
- if (errno == ENOENT) theAnswer = FALSE;
- else {
- ErrorMessage(obj, "Cannot stat %s: %s", realDotoFileName,
- errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
- }
- }
- free(realDotoFileName);
- }
- dotsFiles[nextDotsFile].alreadyGenerated = theAnswer;
- dotsFiles[nextDotsFile].codeFileNumber = nextObjectNumber;
- dotsFiles[nextDotsFile].codeOID = fCodeOID;
- dotsFiles[nextDotsFile].createdOID = fOID;
- TRACE4(doto, 1,
- "\"%s\" %s code=0x%08x created=0x%08x",
- obj && (obj->tag == P_OBLIT || obj->tag == P_ATLIT) ?
- ST_SymbolName(obj->b.oblit.name->b.symdef.symbol) : "<?>",
- dotsFiles[nextDotsFile].alreadyGenerated ? "AG" : "!AG",
- dotsFiles[nextDotsFile].codeOID,
- dotsFiles[nextDotsFile].createdOID);
- nextDotsFile++;
- nextCodeFileName();
- if (! theAnswer) {
- codeFile = fopen(codeFileName, "w");
- if (codeFile == NULL) {
- fprintf(stderr, "Can't open the code file (%s).\n", codeFileName);
- exit (1);
- }
- }
- return(theAnswer);
- }
-
- extern void init_Sugar();
- extern void initializebuildATs();
- extern void initializeGenerate();
- extern void initializeAllocate();
- extern void initializeSymbols();
- extern void initializeSymbolTable();
- extern void initializeEnvironment();
- extern void initializeManifest();
- extern void initializeTrace();
- extern void initializeOption();
- extern void initializeGraphs();
- extern void initializeKnowCT();
- extern void initializeKnowManifest();
- extern void initializeKnowLocal();
- extern void Scanner_Initialize();
- extern void initializeNodes();
-
- void initialize()
- {
- initializeDataBaseFiles();
- initializeNodes();
- ON_initialize();
- init_Conforms();
- init_Sugar();
- initializebuildATs();
- initializeAllocate();
- initializeGenerate();
- initializeSymbols();
- initializeSymbolTable();
- initializeEnvironment();
- initializeManifest();
- initializeRegisters();
- initializeTrace();
- initializeOption();
- initializeGraphs();
- initializeKnowCT();
- initializeKnowManifest();
- initializeKnowLocal();
- Scanner_Initialize();
- }
-
- void Finalize()
- {
- ON_finalize();
- }
-