407 lines · 11.4 KB · C
RawDownload
/* * Maintaining a stack of files / scripts. *  * The Hugs 98 system is Copyright (c) Mark P Jones, Alastair Reid, the * Yale Haskell Group, and the OGI School of Science & Engineering at OHSU, * 1994-2003, All rights reserved.  It is distributed as free software under * the license in the file "License", which is included in the distribution. * */#include "prelude.h"#include "storage.h"#include "connect.h"#include "errors.h"#include "machdep.h"#include "opts.h"#include "strutil.h"#include "script.h" /* -------------------------------------------------------------------------- * Local script state: * ------------------------------------------------------------------------*/ /* * The scripts that either have been loaded or will be later are all * stored in fixed-size stacks. (Moving to growable tables will also  * require making the module table expandable.) */struct strScript {    String fileName;			/* Script file name                */    String realName;			/* Full path to canonical name     */    String directory;			/* Directory module was found in   */    Time lastChange;			/* Time of last change to script   */    Bool postponed;			/* Indicates postponed load        */    Bool chased;			/* Added by import chasing?        */}; static struct strScript scriptTable[NUM_SCRIPTS]; static Int    numScripts;               /* Number of scripts loaded        */static Int    namesUpto;                /* Number of script names set      */static Int    scriptsStable;            /* Number of (Prelude) scripts     */                                        /* considered 'stable'             */                                        /* (=> won't be nuked when clearing */                                        /* the script stack / reloading.)   */ static Bool   needsImports;             /* set to TRUE if imports required */       String scriptFile;               /* Name of current script (if any) */ /* -------------------------------------------------------------------------- * Local function prototypes: * ------------------------------------------------------------------------*/static Bool local addScript     Args((String,Long));static Void local freeScript    Args((Int)); /* -------------------------------------------------------------------------- * Initialising / freeing script stacks: * ------------------------------------------------------------------------*/Void initScripts() {  scriptFile    = 0;  numScripts    = 0;  namesUpto     = 0;  scriptsStable = 0;} Void stopScripts() {  int i;   for (i=0; i < numScripts ; i++)    freeScript(i);} static Void local freeScript(i)Int i; {  if (scriptTable[i].fileName)    free(scriptTable[i].fileName);  if (scriptTable[i].realName)    free(scriptTable[i].realName);  if (scriptTable[i].directory)    free(scriptTable[i].directory);} /* We record the number of scripts that loading the Prelude * brought about, so that when the user comes to clear the module * stack (e.g., ":l<ENTER>"), only modules later than the Prelude * ones are scratched. */Void setScriptStableMark() {  scriptsStable = namesUpto;} String getScriptName(s)  /* access the script name at index 's' */Script s; {  if ( s >=0 && s <= numScripts ) {    return scriptTable[s].fileName;  } else {    ERRMSG(0) "getScriptName: Illegal script index %d (max: %d)", s, numScripts    EEND;  }  return NULL;} String getScriptRealName(s)  /* access the path of script at index 's' */Script s; {  if ( s >=0 && s <= numScripts ) {    return scriptTable[s].realName;  } else {    ERRMSG(0) "getScriptRealName: Illegal script index %d (max: %d)", s, numScripts    EEND;  }  return NULL;} Int getScriptHwMark() { /* return number of on the stack, loaded or not. */  return namesUpto;} Int numLoadedScripts() { /* return number of currently loaded scripts */  return numScripts;} #if HUGS_FOR_WINDOWS/* UI pokes around the script stack, give it access... */Void setNumLoadedScripts(s)Script s; {  numScripts=s;} Void setScriptHwMark(s)Script s; {  namesUpto = s;} Void setScriptName(s,scr)Script s;String scr; {  scriptTable[s].fileName = scr;} Void setScriptRealName(s,scr)Script s;String scr; {  scriptTable[s].realName = scr;}#endif /* -------------------------------------------------------------------------- * Loading script files: * ------------------------------------------------------------------------*/ Void addScriptName(s,sch)  /* Add script to list of scripts   */String s;                  /* to be read in ...               */Bool   sch; {              /* TRUE => requires pathname search*/    if (namesUpto>=NUM_SCRIPTS) {	ERRMSG(0) "Too many module files (maximum of %d allowed)",		  NUM_SCRIPTS	EEND;	return;    }    if (sch) {	if (isModuleId(s)) {	    String location = findMPathname(s);	    if (!location) {		ERRMSG(0) "Can't find module \"%s\"", s		EEND;	    }	    scriptTable[namesUpto].fileName  = strCopy(location);	    scriptTable[namesUpto].directory = NULL;	} else {	    scriptTable[namesUpto].fileName  = strCopy(findPathname(s));	    scriptTable[namesUpto].directory = dirname(scriptTable[namesUpto].fileName);	}    } else {	scriptTable[namesUpto].fileName  = strCopy(s);	scriptTable[namesUpto].directory = NULL;    }    scriptTable[namesUpto].realName   = strCopy(RealPath(scriptTable[namesUpto].fileName));    scriptTable[namesUpto].chased     = !sch;    namesUpto++;} static Bool local addScript(fname,len)  /* read single script file */String fname;                           /* name of script file     */Long   len; {                           /* length of script file   */#if HUGS_FOR_WINDOWS         /* Set clock cursor while loading   */    allowBreak();    SetCursor(LoadCursor(NULL, IDC_WAIT));#endif     if (!quiet) {	Printf("Reading file \"%s\":\n",fname);  FlushStdout();    }    setLastEdit(fname,0);     needsImports = FALSE;    scriptFile = 0;    if (!parseScript(fname,len)) {   /* process script file */	/* file or parse error, drop the script */ 	forgetAScript(numScripts);	errFail();    }    if (needsImports) return FALSE;    checkDefns();    typeCheckDefns();    compileDefns();    scriptFile    = 0;    preludeLoaded = TRUE;    return TRUE;} Bool chase(imps)                 /* Process list of import requests */List imps; {    Int    origPos = numScripts; /* keep track of original position */    String origDir = scriptTable[origPos].directory;    for (; nonNull(imps); imps=tl(imps)) {	String modname = textToStr(textOf(hd(imps)));	String iname = NULL;	String rname;	Bool   inOrigDir = FALSE;	Int    i     = 0; 	if (origDir) {	    iname = findMInDir(origDir,modname);	    if (iname)		inOrigDir = TRUE;	}	if (iname == NULL)	    iname = findMPathname(modname);	if (iname == NULL) {	    ERRMSG(0) "Can't find imported module \"%s\"", modname	    EEND;	} 	rname = RealPath(iname);	for (; i<namesUpto; i++)	    if (filenamecmp(scriptTable[i].realName,rname)==0)		break;	if (i>=origPos) {           /* Neither loaded or queued        */	    struct strScript tmpScript; 	    scriptTable[origPos].postponed = TRUE;	    needsImports           = TRUE; 	    if (i>=namesUpto) {     /* Name not found (i==namesUpto)   */		addScriptName(iname,FALSE);		if (inOrigDir)		    scriptTable[i].directory = strCopy(origDir);	    } else if (scriptTable[i].postponed) {/* imported by itself? */		ERRMSG(0)		  "Recursive import dependency between \"%s\" and \"%s\"",		  scriptTable[origPos].fileName, iname		EEND;	    }	    /* Right rotate section of tables between numScripts and i so	     * that i ends up with other imports in front of orig. script	     */	    tmpScript = scriptTable[i];	    for (; i>numScripts; i--)		scriptTable[i] = scriptTable[i-1];	    scriptTable[numScripts] = tmpScript;	    origPos++;	}    }    return needsImports;} /* -------------------------------------------------------------------------- * Adding scripts found in an argument vector: * ------------------------------------------------------------------------*/Void addScriptsFromArgs(argc,argv)Int argc;String argv[]; {    Int i; #if USE_PREFERENCES_FILE    extern Int     iniArgc;    extern String* iniArgv;     if (iniArgc > 0) {        /* load additional files found in the preferences file */        for (i=0; i<iniArgc; i++) {	    addScriptName(iniArgv[i],TRUE);        }    }#endif    for (i=1; i<argc; ++i) {      if (argv[i] && argv[i][0] && !isOption(argv[i])) {	    addScriptName(argv[i],TRUE);#if HUGS_FOR_WINDOWS	    SetWorkingDir(argv[i]);#endif      }    }  } /* -------------------------------------------------------------------------- * Dropping script files: * ------------------------------------------------------------------------*/Void forgetScriptsFrom(scno) /* remove scripts from system     */Script scno; {    Script i;    for (i=scno; i<namesUpto; ++i)	freeScript(i);    dropScriptsFrom(scno-1); /* don't count prelude as script  */    namesUpto = scno;    if (numScripts>namesUpto)	numScripts = scno;} Void forgetAllScripts() {  /* Drop all but the stable scripts; i.e., the   * Prelude and (possibly) its implementation module(s).   */  forgetScriptsFrom( scriptsStable ); } Void forgetAScript(scno) /* remove a script from system */Script scno; {    Script i;        if (scno > namesUpto)	return;     freeScript(scno);     for (i=scno+1; i < namesUpto; i++)	scriptTable[i-1] = scriptTable[i];    dropAScript(scno);    namesUpto--;} Void readScripts(n)        /* Reread current list of scripts, */Int n; {                   /* loading everything after and    */    Time timeStamp;        /* including the first script which*/    Long fileSize;         /* has been either changed or added*/ #if HUGS_FOR_WINDOWS    SetCursor(LoadCursor(NULL, IDC_WAIT));#endif     for (; n<numScripts; n++) {         /* Scan previously loaded scripts  */	getFileInfo(scriptTable[n].fileName, &timeStamp, &fileSize);	if (timeChanged(timeStamp,scriptTable[n].lastChange)) {	    dropScriptsFrom(n-1);	    numScripts = n;	    break;	}    }    for (; n<NUM_SCRIPTS; n++)          /* No scripts have been postponed  */	scriptTable[n].postponed = FALSE;       /* at this stage                   */      while (numScripts<namesUpto) {      /* Process any remaining scripts   */	getFileInfo(scriptTable[numScripts].fileName, &timeStamp, &fileSize);	timeSet(scriptTable[numScripts].lastChange,timeStamp);	if (numScripts>0)               /* no new script for prelude       */	    startNewScript(scriptTable[numScripts].fileName);        generate_ffi = generateFFI && !scriptTable[numScripts].chased;	if (addScript(scriptTable[numScripts].fileName,fileSize))	    numScripts++;	else	    dropScriptsFrom(numScripts-1);    }     if (listScripts)	whatScripts();    if (numScripts<=1)	setLastEdit((String)0, 0);} Void whatScripts() {       /* list scripts in current session */    int i;#if HUGS_FOR_WINDOWS    if (!InAutoReloadFiles) {#endif    Printf("\nHugs session for:");    for (i=0; i<numScripts; ++i) {#if HUGS_FOR_WINDOWS	Putchar('\n');	WinHugsFilename(scriptTable[i].fileName, 0);#else	Printf("\n%s",scriptTable[i].fileName);#endif    }    Putchar('\n');#if HUGS_FOR_WINDOWS    }#endif} Void script(what)Int what; {   /* not much to it..will be more when/if the local tables   * become resizable.   */  switch(what) {  case RESET:   return;  case MARK:    return;  case INSTALL: return;  case EXIT:    stopScripts();                return;  case BREAK:   return;  }}