/* * 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"), 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=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; inamesUpto) 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 (; n0) /* 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