home *** CD-ROM | disk | FTP | other *** search
- /* --------------------------------------------------------------------------
- * gofc.c: Copyright (c) Mark P Jones 1991-1993. All rights reserved.
- * See goferite.h for details and conditions of use etc...
- * Gofer Compiler version 1.01 February 1992
- * Gofer version 2.28 January 1993
- *
- * Gofer->C main program
- * ------------------------------------------------------------------------*/
-
- #include "prelude.h"
- #include "storage.h"
- #include "command.h"
- #include "connect.h"
- #include "errors.h"
- #include <setjmp.h>
- #include <ctype.h>
-
- #if TURBOC
- #include <sys\stat.h>
- #endif
-
- #if UNIX
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif
-
- #define VERSION "1.01 (2.28)"
-
- Bool dumpScs = FALSE; /* TRUE => output sc defns */
-
- typedef FILE *Fp;
- static Fp gofcFp = 0; /* for output to file */
-
- /* --------------------------------------------------------------------------
- * Machine dependent code for Gofer compiler:
- * ------------------------------------------------------------------------*/
-
- #define MACHDEP_GOFC 1
- #include "machdep.c"
-
- /* --------------------------------------------------------------------------
- * Shared parts of user interface:
- * ------------------------------------------------------------------------*/
-
- #include "commonui.c"
-
- /* --------------------------------------------------------------------------
- * Local function prototypes:
- * ------------------------------------------------------------------------*/
-
- static Void local loadCompile Args((Void));
- static Fp local initOutput Args((String));
- static Void local initialise Args((Int,String []));
-
- /* --------------------------------------------------------------------------
- * Gofer entry point:
- * ------------------------------------------------------------------------*/
-
- Main main Args((Int, String [])); /* now every func has a prototype */
-
- Main main(argc,argv)
- int argc;
- char *argv[]; {
- CStackBase = &argc; /* Save stack base for use in gc */
-
- /* The startup banner now includes my name. Gofer is provided free of */
- /* charge. I ask however that you show your appreciation for the many */
- /* hours of work involved by retaining my name in the banner. Thanks! */
-
- printf("Gofer->C Version %s Copyright (c) Mark P Jones 1992-1993\n\n",
- VERSION);
- fflush(stdout);
- initialise(argc, argv); /* initialise compiler */
-
- if (dumpScs) { /* produce script of sc defns for */
- gofcFp = initOutput(".gsc"); /* debugging purposes */
- printf("[Writing supercombinators to \"%s\"]\n",outputFile);
- loadCompile();
- fprintf(gofcFp,"\n/* end of %s */\n",outputFile);
- fclose(gofcFp);
- }
- else { /* produce C code as output */
- extern Void outputCode Args((FILE *,Name));
- Name mn;
- loadCompile();
- gofcFp = initOutput(".c");
-
- mn = findName(findText("main"));/* check for main symbol */
- if (isNull(mn)) {
- ERROR(0) "Program must include definition for \"main\"::Dialogue"
- EEND;
- }
-
- if (name(mn).defn==CFUN || /* check that definition is ok */
- name(mn).defn==MFUN ||
- name(mn).defn==PRIM ||
- isNull(name(mn).type)) {
- ERROR(0) "Invalid definition for \"main\""
- EEND;
- }
-
- if (!typeMatches(name(mn).type,typeDialogue)) {
- ERROR(0) "Illegal typing for \"main\":" ETHEN
- ERRTEXT "\n*** inferred type : " ETHEN
- ERRTYPE(name(mn).type);
- ERRTEXT "\n*** does not match : Dialogue\n"
- EEND;
- }
-
- printf("\nWriting C output file \"%s\":\n",outputFile);
- outputCode(gofcFp,mn);
- fclose(gofcFp);
- }
-
- printf("[Leaving Gofer->C]\n");
- everybody(EXIT);
- exit(0);
- MainDone
- }
-
- static Void local loadCompile() { /* load and compile source modules */
- Module i;
- Time timeStamp;
- Long fileSize;
-
- for (i=0; i<namesUpto; ++i) { /* load and compile source modules */
- getFileInfo(scriptName[i], &timeStamp, &fileSize);
- if (i>0)
- startNewModule();
- addScript(scriptName[i], fileSize);
- numScripts++;
- }
- }
-
- /* --------------------------------------------------------------------------
- * Determine name of output file:
- * ------------------------------------------------------------------------*/
-
- static Fp local initOutput(suff) /* find name for output file, open */
- String suff; { /* it and write header ... */
- Fp fp = 0;
- int i;
-
- if (!outputFile) { /* user specified name has priority*/
- String s,dot;
-
- if (projectLoaded && currProject) /* use project name if poss*/
- s = currProject;
- else
- s = scriptName[namesUpto-1]; /* o/w use last script name*/
-
- outputFile = malloc(strlen(s)+strlen(suff)+1);
- if (!outputFile)
- fatal("setOutputName");
- strcpy(outputFile,s);
-
- for (s=outputFile, dot=0; *s; ++s) /* do something sensible */
- if (*s=='.') /* with file extensions */
- dot = s;
-
- #if !RISCOS
- if (dot && (strcmp(dot+1,"gp") == 0 || strcmp(dot+1,"prj") ==0 ||
- strcmp(dot+1,"hs") == 0 || strcmp(dot+1,"lhs") ==0 ||
- strcmp(dot+1,"gs") == 0 || strcmp(dot+1,"lgs") ==0 ||
- strcmp(dot+1,"gof")== 0 || strcmp(dot+1,"has") ==0 ||
- strcmp(dot+1,"lit")== 0 || strcmp(dot+1,"verb")==0 ||
- strcmp(dot+1,"prelude")==0))
- *dot = '\0';
-
- strcat(outputFile,suff);
- #else
- if(dot)
- {
- char *prev = dot;
- while(prev > outputFile && *--prev != '.') ;
- if(*prev == '.') ++prev;
- if(namecmp(prev, "gp")
- || namecmp(prev, "hs")
- || namecmp(prev, "gs")
- || namecmp(prev, "gof")
- || namecmp(prev, "lit")
- || namecmp(prev, "prj")
- || namecmp(prev, "lhs")
- || namecmp(prev, "lgs")
- || namecmp(prev, "has")
- || namecmp(prev, "verb")
- || namecmp(prev, "prelude"))
- {
- strcpy(prev, suff+1);
- strcat(prev, dot);
- }
- else
- {
- strcat(outputFile,suff);
- outputFile[strlen(outputFile)-strlen(suff)] = '_'; /* No dot */
- }
- }
- else
- {
- strcat(outputFile,suff);
- outputFile[strlen(outputFile)-strlen(suff)] = '_'; /* No dot */
- }
- #endif
- }
-
- if (!(fp=fopen(outputFile,"w"))) { /* now try to open */
- ERROR(0) "Unable to open output file \"%s\" for writing",
- outputFile
- EEND;
- }
-
- fprintf(fp,"/* %s\t\t\t\t%s *\n",outputFile,timeString());
- fprintf(fp," * This program produced by gofc %s from:\n",VERSION);
-
- if (projectLoaded && currProject)
- fprintf(fp," * Project file %s comprising:\n",currProject);
-
- for (i=0; i<namesUpto; i++)
- fprintf(fp," *\t%s\n",scriptName[i]);
- fprintf(fp," */\n\n");
-
- return fp;
- }
-
- /* --------------------------------------------------------------------------
- * Include our own version of output.c with ability to output sc defns
- * (This is a big hack, but it would probably be worth doing a proper
- * overhaul of the overall structure of Gofer before spending too much
- * time here.)
- * ------------------------------------------------------------------------*/
-
- #define GOFC_OUTPUT
- #include "output.c"
-
- /* --------------------------------------------------------------------------
- * Initialisation, interpret command line args and read prelude:
- * ------------------------------------------------------------------------*/
-
- struct options toggle[] = {
- {'d', "Show dictionary values in output exprs",&showDicts},
- {'g', "Print no. cells recovered after gc", &gcMessages},
- {'c', "Test conformality for pattern bindings",&useConformality},
- {'l', "Treat input files as literate scripts", &literateScripts},
- {'e', "Warn about errors in literate scripts", &literateErrors},
- {'i', "Apply fromInteger to integer literals", &coerceNumLiterals},
- {'o', "Optimise use of (&&) and (||)", &andorOptimise},
- {'u', "Catch ambiguously typed top-level vars",&catchAmbigs},
- {'a', "Use any evidence, not nec. best", &anyEvidence},
- {'E', "Fail silently if evidence not found", &silentEvFail},
- {'.', "Print dots to show progress", &useDots},
- {'1', "Overload singleton list notation", &overSingleton},
- {'D', "Output .gsc file for debugging", &dumpScs},
- {0, 0, 0}
- };
-
- static Void local initialise(argc,argv)/* compiler initialisation */
- Int argc;
- String argv[]; {
- Module i;
- String proj = 0;
-
- scriptFile = 0;
- numScripts = 0;
- namesUpto = 1;
- scriptName[0] = strCopy(fromEnv("GOFER",STD_PRELUDE));
-
- for (i=1; i<argc; ++i) /* process command line arguments */
- if (strcmp(argv[i],"+")==0 && i+1<argc)
- if (proj) {
- ERROR(0) "Multiple project filenames on command line"
- EEND;
- }
- else
- proj = argv[++i];
- else
- addScriptName(argv[i]);
-
- everybody(INSTALL);
- if (proj) {
- if (namesUpto>1)
- fprintf(stderr,
- "\nUsing project file, ignoring additional filenames\n");
- loadProject(strCopy(proj));
- }
- }
-
- Void errHead(l) /* print start of error message */
- Int l; {
- failed(); /* failed to reach target ... */
- fprintf(errorStream,"ERROR");
-
- if (scriptFile) {
- fprintf(errorStream," \"%s\"", scriptFile);
- if (l) fprintf(errorStream," (line %d)",l);
- }
- fprintf(errorStream,": ");
- fflush(errorStream);
- }
-
- Void errFail() { /* terminate error message */
- fprintf(errorStream,"\nAborting compilation\n");
- fflush(errorStream);
- exit(1);
- }
-
- Void errAbort() { /* altern. form of error handling */
- failed(); /* used when suitable error message*/
- errFail();
- }
-
- Void internal(msg) /* handle internal error */
- String msg; {
- fatal(msg); /* treat as fatal condition */
- }
-
- Void fatal(msg) /* handle fatal error */
- String msg; {
- fflush(stdout);
- printf("\nINTERNAL ERROR: %s\n",msg);
- everybody(EXIT);
- exit(1);
- }
-
- sigHandler(breakHandler) { /* respond to break interrupt */
- breakOn(TRUE);
- printf("{Interrupted!}\n");
- everybody(BREAK);
- fflush(stdout);
- errAbort();
- sigResume;/*NOTREACHED*/
- }
-
- /*-------------------------------------------------------------------------*/
-