2 /* --------------------------------------------------------------------------
5 * The Hugs 98 system is Copyright (c) Mark P Jones, Alastair Reid, the
6 * Yale Haskell Group, and the Oregon Graduate Institute of Science and
7 * Technology, 1994-1999, All rights reserved. It is distributed as
8 * free software under the license in the file "License", which is
9 * included in the distribution.
11 * $RCSfile: hugs.c,v $
13 * $Date: 2000/03/15 23:27:16 $
14 * ------------------------------------------------------------------------*/
29 #include "Assembler.h" /* DEBUG_LoadSymbols */
31 Bool haskell98 = TRUE; /* TRUE => Haskell 98 compatibility*/
33 #if EXPLAIN_INSTANCE_RESOLUTION
34 Bool showInstRes = FALSE;
37 Bool multiInstRes = FALSE;
40 /* --------------------------------------------------------------------------
41 * Local function prototypes:
42 * ------------------------------------------------------------------------*/
44 static Void local initialize ( Int,String [] );
45 static Void local promptForInput ( String );
46 static Void local interpreter ( Int,String [] );
47 static Void local menu ( Void );
48 static Void local guidance ( Void );
49 static Void local forHelp ( Void );
50 static Void local set ( Void );
51 static Void local changeDir ( Void );
52 static Void local load ( Void );
53 static Void local project ( Void );
54 static Void local readScripts ( Int );
55 static Void local whatScripts ( Void );
56 static Void local editor ( Void );
57 static Void local find ( Void );
58 static Bool local startEdit ( Int,String );
59 static Void local runEditor ( Void );
60 static Void local setModule ( Void );
61 static Module local findEvalModule ( Void );
62 static Void local evaluator ( Void );
63 static Void local stopAnyPrinting ( Void );
64 static Void local showtype ( Void );
65 static String local objToStr ( Module, Cell );
66 static Void local info ( Void );
67 static Void local printSyntax ( Name );
68 static Void local showInst ( Inst );
69 static Void local describe ( Text );
70 static Void local listNames ( Void );
72 static Void local toggleSet ( Char,Bool );
73 static Void local togglesIn ( Bool );
74 static Void local optionInfo ( Void );
75 #if USE_REGISTRY || HUGS_FOR_WINDOWS
76 static String local optionsToStr ( Void );
78 static Void local readOptions ( String );
79 static Bool local processOption ( String );
80 static Void local setHeapSize ( String );
81 static Int local argToInt ( String );
83 static Void local loadProject ( String );
84 static Void local clearProject ( Void );
85 static Bool local addScript ( Int );
86 static Void local forgetScriptsFrom ( Script );
87 static Void local setLastEdit ( String,Int );
88 static Void local failed ( Void );
89 static String local strCopy ( String );
90 static Void local browseit ( Module,String,Bool );
91 static Void local browse ( Void );
93 /* --------------------------------------------------------------------------
94 * Machine dependent code for Hugs interpreter:
95 * ------------------------------------------------------------------------*/
102 /* --------------------------------------------------------------------------
104 * ------------------------------------------------------------------------*/
106 static Bool printing = FALSE; /* TRUE => currently printing value*/
107 static Bool showStats = FALSE; /* TRUE => print stats after eval */
108 static Bool listScripts = TRUE; /* TRUE => list scripts after loading*/
109 static Bool addType = FALSE; /* TRUE => print type with value */
110 static Bool useDots = RISCOS; /* TRUE => use dots in progress */
111 static Bool quiet = FALSE; /* TRUE => don't show progress */
112 static Bool lastWasObject = FALSE;
114 Bool flagAssert = FALSE; /* TRUE => assert False <e> causes
115 an assertion failure */
116 Bool preludeLoaded = FALSE;
117 Bool debugSC = FALSE;
118 Bool combined = FALSE;
122 String modName; /* Module name */
123 Bool details; /* FALSE => remaining fields are invalid */
124 String path; /* Path to module */
125 String srcExt; /* ".hs" or ".lhs" if fromSource */
126 Time lastChange; /* Time of last change to script */
127 Bool fromSource; /* FALSE => load object code */
128 Bool postponed; /* Indicates postponed load */
135 static Void local makeStackEntry ( ScriptInfo*,String );
136 static Void local addStackEntry ( String );
138 static ScriptInfo scriptInfo[NUM_SCRIPTS];
140 static Int numScripts; /* Number of scripts loaded */
141 static Int nextNumScripts;
142 static Int namesUpto; /* Number of script names set */
143 static Bool needsImports; /* set to TRUE if imports required */
144 String scriptFile; /* Name of current script (if any) */
148 static Text evalModule = 0; /* Name of module we eval exprs in */
149 static String currProject = 0; /* Name of current project file */
150 static Bool projectLoaded = FALSE; /* TRUE => project file loaded */
152 static Bool autoMain = FALSE;
153 static String lastEdit = 0; /* Name of script to edit (if any) */
154 static Int lastEdLine = 0; /* Editor line number (if possible)*/
155 static String prompt = 0; /* Prompt string */
156 static Int hpSize = DEFAULTHEAP; /* Desired heap size */
157 String hugsEdit = 0; /* String for editor command */
158 String hugsPath = 0; /* String for file search path */
160 List ifaces_outstanding = NIL;
163 static Bool disableOutput = FALSE; /* redirect output to buffer? */
166 String bool2str ( Bool b )
168 if (b) return "Yes"; else return "No ";
171 void ppSmStack ( String who )
175 fflush(stdout);fflush(stderr);
177 printf ( "ppSmStack %s: numScripts = %d namesUpto = %d needsImports = %s\n",
178 who, numScripts, namesUpto, bool2str(needsImports) );
179 assert (namesUpto >= numScripts);
180 printf ( " Det FrS Pst ObL Module Ext Size ModTime Path\n" );
181 for (i = namesUpto-1; i >= 0; i--) {
182 printf ( "%c%2d: %3s %3s %3s %3s %16s %-4s %5ld %8lx %s\n",
183 (i==numScripts ? '*' : ' '),
184 i, bool2str(scriptInfo[i].details),
185 bool2str(scriptInfo[i].fromSource),
186 bool2str(scriptInfo[i].postponed),
187 bool2str(scriptInfo[i].objLoaded),
188 scriptInfo[i].modName,
189 scriptInfo[i].fromSource ? scriptInfo[i].srcExt : "",
191 scriptInfo[i].lastChange,
195 fflush(stdout);fflush(stderr);
201 /* --------------------------------------------------------------------------
203 * ------------------------------------------------------------------------*/
205 #ifndef NO_MAIN /* we omit main when building the "Hugs server" */
207 Main main ( Int, String [] ); /* now every func has a prototype */
212 #ifdef HAVE_CONSOLE_H /* Macintosh port */
214 _fcreator = 'R*ch'; /* // 'KAHL'; //'*TEX'; //'ttxt'; */
216 console_options.top = 50;
217 console_options.left = 20;
219 console_options.nrows = 32;
220 console_options.ncols = 80;
222 console_options.pause_atexit = 1;
223 console_options.title = "\pHugs";
225 console_options.procID = 5;
226 argc = ccommand(&argv);
229 CStackBase = &argc; /* Save stack base for use in gc */
231 /* If first arg is +Q or -Q, be entirely silent, and automatically run
232 main after loading scripts. Useful for running the nofib suite. */
233 if (argc > 1 && (strcmp(argv[1],"+Q") == 0 || strcmp(argv[1],"-Q")==0)) {
235 if (strcmp(argv[1],"-Q") == 0) {
240 Printf("__ __ __ __ ____ ___ _________________________________________\n");
241 Printf("|| || || || || || ||__ STGHugs: Based on the Haskell 98 standard\n");
242 Printf("||___|| ||__|| ||__|| __|| Copyright (c) 1994-1999\n");
243 Printf("||---|| ___|| World Wide Web: http://haskell.org/hugs\n");
244 Printf("|| || Report bugs to: hugs-bugs@haskell.org\n");
245 Printf("|| || Version: %s _________________________________________\n\n",HUGS_VERSION);
247 /* Get the absolute path to the directory containing the hugs
248 executable, so that we know where the Prelude and nHandle.so/.dll are.
249 We do this by reading env var STGHUGSDIR. This needs to succeed, so
250 setInstallDir won't return unless it succeeds.
252 setInstallDir ( argv[0] );
255 Printf(" Ported to Macintosh by Hans Aberg, compiled " __DATE__ ".\n\n");
258 interpreter(argc,argv);
259 Printf("[Leaving Hugs]\n");
270 /* --------------------------------------------------------------------------
271 * Initialization, interpret command line args and read prelude:
272 * ------------------------------------------------------------------------*/
274 static Void local initialize(argc,argv)/* Interpreter initialization */
279 char argv_0_orig[1000];
281 setLastEdit((String)0,0);
288 hugsEdit = strCopy(fromEnv("EDITOR","c:\\windows\\notepad.exe"));
292 hugsEdit = strCopy(fromEnv("EDITOR",NULL));
294 hugsPath = strCopy(HUGSPATH);
295 readOptions("-p\"%s> \" -r$$");
297 projectPath = strCopy(readRegChildStrings(HKEY_LOCAL_MACHINE,ProjectRoot,
298 "HUGSPATH", PATHSEP, ""));
299 readOptions(readRegString(HKEY_LOCAL_MACHINE,HugsRoot,"Options",""));
300 readOptions(readRegString(HKEY_CURRENT_USER, HugsRoot,"Options",""));
301 #endif /* USE_REGISTRY */
302 readOptions(fromEnv("STGHUGSFLAGS",""));
304 strncpy(argv_0_orig,argv[0],1000); /* startupHaskell mangles argv[0] */
305 startupHaskell (argc,argv);
306 argc = prog_argc; argv = prog_argv;
308 namesUpto = numScripts = 0;
310 /* Pre-scan flags to see if -c or +c is present. This needs to
311 precede adding the stack entry for Prelude. On the other hand,
312 that stack entry needs to be made before the cmd line args are
313 properly examined. Hence the following pre-scan of them.
315 for (i=1; i < argc; ++i) {
316 if (strcmp(argv[i], "--")==0) break;
317 if (strcmp(argv[i], "-c")==0) combined = FALSE;
318 if (strcmp(argv[i], "+c")==0) combined = TRUE;
321 addStackEntry("Prelude");
322 if (combined) addStackEntry("PrelHugs");
324 for (i=1; i < argc; ++i) { /* process command line arguments */
325 if (strcmp(argv[i], "--")==0) break;
326 if (strcmp(argv[i],"+")==0 && i+1<argc) {
328 ERRMSG(0) "Multiple project filenames on command line"
333 } else if (argv[i] && argv[i][0]/* workaround for /bin/sh silliness*/
334 && !processOption(argv[i])) {
335 addStackEntry(argv[i]);
341 char exe_name[N_INSTALLDIR + 6];
342 strcpy(exe_name, installDir);
343 strcat(exe_name, "hugs");
344 DEBUG_LoadSymbols(exe_name);
350 if (!scriptName[0]) {
351 Printf("Prelude not found on current path: \"%s\"\n",
352 hugsPath ? hugsPath : "");
353 fatal("Unable to load prelude");
358 Printf("Haskell 98 mode: Restart with command line option -98 to enable extensions\n");
360 Printf("Hugs mode: Restart with command line option +98 for Haskell 98 mode\n");
364 Printf("Combined mode: Restart with command line -c for standalone mode\n\n" );
366 Printf("Standalone mode: Restart with command line +c for combined mode\n\n" );
371 evalModule = findText(""); /* evaluate wrt last module by default */
375 "\nUsing project file, ignoring additional filenames\n");
377 loadProject(strCopy(proj));
382 /* --------------------------------------------------------------------------
383 * Command line options:
384 * ------------------------------------------------------------------------*/
386 struct options { /* command line option toggles */
387 char c; /* table defined in main app. */
392 extern struct options toggle[];
394 static Void local toggleSet(c,state) /* Set command line toggle */
398 for (i=0; toggle[i].c; ++i)
399 if (toggle[i].c == c) {
400 *toggle[i].flag = state;
403 ERRMSG(0) "Unknown toggle `%c'", c
407 static Void local togglesIn(state) /* Print current list of toggles in*/
408 Bool state; { /* given state */
411 for (i=0; toggle[i].c; ++i)
412 if (*toggle[i].flag == state && (!haskell98 || toggle[i].h98)) {
414 Putchar((char)(state ? '+' : '-'));
415 Putchar(toggle[i].c);
422 static Void local optionInfo() { /* Print information about command */
423 static String fmts = "%-5s%s\n"; /* line settings */
424 static String fmtc = "%-5c%s\n";
427 Printf("TOGGLES: groups begin with +/- to turn options on/off resp.\n");
428 for (i=0; toggle[i].c; ++i) {
429 if (!haskell98 || toggle[i].h98) {
430 Printf(fmtc,toggle[i].c,toggle[i].description);
434 Printf("\nOTHER OPTIONS: (leading + or - makes no difference)\n");
435 Printf(fmts,"hnum","Set heap size (cannot be changed within Hugs)");
436 Printf(fmts,"pstr","Set prompt string to str");
437 Printf(fmts,"rstr","Set repeat last expression string to str");
438 Printf(fmts,"Pstr","Set search path for modules to str");
439 Printf(fmts,"Estr","Use editor setting given by str");
440 Printf(fmts,"cnum","Set constraint cutoff limit");
441 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
442 Printf(fmts,"Fstr","Set preprocessor filter to str");
445 Printf("\nCurrent settings: ");
448 Printf("-h%d",heapSize);
452 printString(repeatStr);
453 Printf(" -c%d",cutoff);
454 Printf("\nSearch path : -P");
455 printString(hugsPath);
458 if (projectPath!=NULL) {
459 Printf("\nProject Path : %s",projectPath);
462 Printf("\nEditor setting : -E");
463 printString(hugsEdit);
464 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
465 Printf("\nPreprocessor : -F");
466 printString(preprocessor);
468 Printf("\nCompatibility : %s", haskell98 ? "Haskell 98 (+98)"
469 : "Hugs Extensions (-98)");
473 #if USE_REGISTRY || HUGS_FOR_WINDOWS
481 #define PUTInt(optc,i) \
482 sprintf(next,"-%c%d",optc,i); \
485 #define PUTStr(c,s) \
486 next=PUTStr_aux(next,c,s)
488 static String local PUTStr_aux ( String,Char, String));
490 static String local PUTStr_aux(next,c,s)
496 sprintf(next,"-%c\"",c);
499 PUTS(unlexChar(*t,'"'));
507 static String local optionsToStr() { /* convert options to string */
508 static char buffer[2000];
509 String next = buffer;
512 for (i=0; toggle[i].c; ++i) {
513 PUTC(*toggle[i].flag ? '+' : '-');
517 PUTS(haskell98 ? "+98 " : "-98 ");
518 PUTInt('h',hpSize); PUTC(' ');
520 PUTStr('r',repeatStr);
521 PUTStr('P',hugsPath);
522 PUTStr('E',hugsEdit);
523 PUTInt('c',cutoff); PUTC(' ');
524 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
525 PUTStr('F',preprocessor);
530 #endif /* USE_REGISTRY */
537 static Void local readOptions(options) /* read options from string */
541 stringInput(options);
542 while ((s=readFilename())!=0) {
543 if (*s && !processOption(s)) {
544 ERRMSG(0) "Option string must begin with `+' or `-'"
551 static Bool local processOption(s) /* process string s for options, */
552 String s; { /* return FALSE if none found. */
564 case 'Q' : break; /* already handled */
566 case 'p' : if (s[1]) {
567 if (prompt) free(prompt);
568 prompt = strCopy(s+1);
572 case 'r' : if (s[1]) {
573 if (repeatStr) free(repeatStr);
574 repeatStr = strCopy(s+1);
579 String p = substPath(s+1,hugsPath ? hugsPath : "");
580 if (hugsPath) free(hugsPath);
585 case 'E' : if (hugsEdit) free(hugsEdit);
586 hugsEdit = strCopy(s+1);
589 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
590 case 'F' : if (preprocessor) free(preprocessor);
591 preprocessor = strCopy(s+1);
595 case 'h' : setHeapSize(s+1);
598 case 'c' : if (heapBuilt()) {
600 "You can't enable/disable combined"
601 " operation inside Hugs\n" );
603 /* don't do anything, since pre-scan of args
604 will have got it already */
608 case 'D' : /* hack */
610 extern void setRtsFlags( int x );
611 setRtsFlags(argToInt(s+1));
615 default : if (strcmp("98",s)==0) {
616 if (heapBuilt() && ((state && !haskell98) ||
617 (!state && haskell98))) {
619 "Haskell 98 compatibility cannot be changed"
620 " while the interpreter is running\n");
633 static Void local setHeapSize(s)
636 hpSize = argToInt(s);
637 if (hpSize < MINIMUMHEAP)
638 hpSize = MINIMUMHEAP;
639 else if (MAXIMUMHEAP && hpSize > MAXIMUMHEAP)
640 hpSize = MAXIMUMHEAP;
641 if (heapBuilt() && hpSize != heapSize) {
642 /* ToDo: should this use a message box in winhugs? */
644 FPrintf(stderr,"Change to heap size will not take effect until you rerun Hugs\n");
646 FPrintf(stderr,"You cannot change heap size from inside Hugs\n");
654 static Int local argToInt(s) /* read integer from argument str */
659 if (*s=='\0' || !isascii((int)(*s)) || !isdigit((int)(*s))) {
660 ERRMSG(0) "Missing integer in option setting \"%s\"", t
665 Int d = (*s++) - '0';
666 if (n > ((MAXPOSINT - d)/10)) {
667 ERRMSG(0) "Option setting \"%s\" is too large", t
671 } while (isascii((int)(*s)) && isdigit((int)(*s)));
673 if (*s=='K' || *s=='k') {
674 if (n > (MAXPOSINT/1000)) {
675 ERRMSG(0) "Option setting \"%s\" is too large", t
682 #if MAXPOSINT > 1000000 /* waste of time on 16 bit systems */
683 if (*s=='M' || *s=='m') {
684 if (n > (MAXPOSINT/1000000)) {
685 ERRMSG(0) "Option setting \"%s\" is too large", t
693 #if MAXPOSINT > 1000000000
694 if (*s=='G' || *s=='g') {
695 if (n > (MAXPOSINT/1000000000)) {
696 ERRMSG(0) "Option setting \"%s\" is too large", t
705 ERRMSG(0) "Unwanted characters after option setting \"%s\"", t
712 /* --------------------------------------------------------------------------
713 * Print Menu of list of commands:
714 * ------------------------------------------------------------------------*/
716 static struct cmd cmds[] = {
717 {":?", HELP}, {":cd", CHGDIR}, {":also", ALSO},
718 {":type", TYPEOF}, {":!", SYSTEM}, {":load", LOAD},
719 {":reload", RELOAD}, {":gc", COLLECT}, {":edit", EDIT},
720 {":quit", QUIT}, {":set", SET}, {":find", FIND},
721 {":names", NAMES}, {":info", INFO}, {":project", PROJECT},
722 {":dump", DUMP}, {":ztats", STATS},
723 {":module",SETMODULE},
725 #if EXPLAIN_INSTANCE_RESOLUTION
728 {":version", PNTVER},
733 static Void local menu() {
734 Printf("LIST OF COMMANDS: Any command may be abbreviated to :c where\n");
735 Printf("c is the first character in the full name.\n\n");
736 Printf(":load <filenames> load modules from specified files\n");
737 Printf(":load clear all files except prelude\n");
738 Printf(":also <filenames> read additional modules\n");
739 Printf(":reload repeat last load command\n");
740 Printf(":project <filename> use project file\n");
741 Printf(":edit <filename> edit file\n");
742 Printf(":edit edit last module\n");
743 Printf(":module <module> set module for evaluating expressions\n");
744 Printf("<expr> evaluate expression\n");
745 Printf(":type <expr> print type of expression\n");
746 Printf(":? display this list of commands\n");
747 Printf(":set <options> set command line options\n");
748 Printf(":set help on command line options\n");
749 Printf(":names [pat] list names currently in scope\n");
750 Printf(":info <names> describe named objects\n");
751 Printf(":browse <modules> browse names defined in <modules>\n");
752 #if EXPLAIN_INSTANCE_RESOLUTION
753 Printf(":xplain <context> explain instance resolution for <context>\n");
755 Printf(":find <name> edit module containing definition of name\n");
756 Printf(":!command shell escape\n");
757 Printf(":cd dir change directory\n");
758 Printf(":gc force garbage collection\n");
759 Printf(":version print Hugs version\n");
760 Printf(":dump <name> print STG code for named fn\n");
761 #ifdef CRUDE_PROFILING
762 Printf(":ztats <name> print reduction stats\n");
764 Printf(":quit exit Hugs interpreter\n");
767 static Void local guidance() {
768 Printf("Command not recognised. ");
772 static Void local forHelp() {
773 Printf("Type :? for help\n");
776 /* --------------------------------------------------------------------------
777 * Setting of command line options:
778 * ------------------------------------------------------------------------*/
780 struct options toggle[] = { /* List of command line toggles */
781 {'s', 1, "Print no. reductions/cells after eval", &showStats},
782 {'t', 1, "Print type after evaluation", &addType},
783 {'g', 1, "Print no. cells recovered after gc", &gcMessages},
784 {'l', 1, "Literate modules as default", &literateScripts},
785 {'e', 1, "Warn about errors in literate modules", &literateErrors},
786 {'.', 1, "Print dots to show progress", &useDots},
787 {'q', 1, "Print nothing to show progress", &quiet},
788 {'w', 1, "Always show which modules are loaded", &listScripts},
789 {'k', 1, "Show kind errors in full", &kindExpert},
790 {'o', 0, "Allow overlapping instances", &allowOverlap},
791 {'S', 1, "Debug: show generated SC code", &debugSC},
792 {'a', 1, "Raise exception on assert failure", &flagAssert},
793 #if EXPLAIN_INSTANCE_RESOLUTION
794 {'x', 1, "Explain instance resolution", &showInstRes},
797 {'m', 0, "Use multi instance resolution", &multiInstRes},
802 static Void local set() { /* change command line options from*/
803 String s; /* Hugs command line */
805 if ((s=readFilename())!=0) {
807 if (!processOption(s)) {
808 ERRMSG(0) "Option string must begin with `+' or `-'"
811 } while ((s=readFilename())!=0);
813 writeRegString("Options", optionsToStr());
820 /* --------------------------------------------------------------------------
821 * Change directory command:
822 * ------------------------------------------------------------------------*/
824 static Void local changeDir() { /* change directory */
825 String s = readFilename();
827 ERRMSG(0) "Unable to change to directory \"%s\"", s
832 /* --------------------------------------------------------------------------
833 * Loading project and script files:
834 * ------------------------------------------------------------------------*/
836 static Void local loadProject(s) /* Load project file */
840 projInput(currProject);
841 scriptFile = currProject;
842 forgetScriptsFrom(N_PRELUDE_SCRIPTS);
843 while ((s=readFilename())!=0)
846 ERRMSG(0) "Empty project file"
850 projectLoaded = TRUE;
853 static Void local clearProject() { /* clear name for current project */
857 projectLoaded = FALSE;
859 setLastEdit((String)0,0);
865 static Void local makeStackEntry ( ScriptInfo* ent, String iname )
868 Bool sAvail, iAvail, oAvail;
869 Time sTime, iTime, oTime;
870 Long sSize, iSize, oSize;
873 ok = findFilesForModule (
877 &sAvail, &sTime, &sSize,
878 &iAvail, &iTime, &iSize,
879 &oAvail, &oTime, &oSize
883 "Can't find source or object+interface for module \"%s\"",
884 /* "Can't find source for module \"%s\"", */
888 /* findFilesForModule should enforce this */
889 if (!(sAvail || (oAvail && iAvail)))
891 /* Load objects in preference to sources if both are available */
892 /* 11 Oct 99: disable object loading in the interim.
893 Will probably only reinstate when HEP becomes available.
897 ? (oAvail && iAvail && timeEarlier(sTime,oTime))
903 /* ToDo: namesUpto overflow */
904 ent->modName = strCopy(iname);
907 ent->fromSource = !fromObj;
909 ent->postponed = FALSE;
910 ent->lastChange = sTime; /* ToDo: is this right? */
911 ent->size = fromObj ? iSize : sSize;
912 ent->oSize = fromObj ? oSize : 0;
913 ent->objLoaded = FALSE;
918 static Void nukeEnding( String s )
921 if (l > 4 && strncmp(s+l-4,".u_o" ,4)==0) s[l-4] = 0; else
922 if (l > 5 && strncmp(s+l-5,".u_hi",5)==0) s[l-5] = 0; else
923 if (l > 3 && strncmp(s+l-3,".hs" ,3)==0) s[l-3] = 0; else
924 if (l > 4 && strncmp(s+l-4,".lhs" ,4)==0) s[l-4] = 0; else
925 if (l > 4 && strncmp(s+l-4,".dll" ,4)==0) s[l-4] = 0; else
926 if (l > 4 && strncmp(s+l-4,".DLL" ,4)==0) s[l-4] = 0;
929 static Void local addStackEntry(s) /* Add script to list of scripts */
930 String s; { /* to be read in ... */
935 if (namesUpto>=NUM_SCRIPTS) {
936 ERRMSG(0) "Too many module files (maximum of %d allowed)",
943 for (s2 = s; *s2; s2++)
944 if (*s2 == SLASH && *(s2+1)) s = s2+1;
947 for (i = 0; i < namesUpto; i++)
948 if (strcmp(scriptInfo[i].modName,s)==0)
952 makeStackEntry ( &scriptInfo[namesUpto], strCopy(s) );
958 /* Return TRUE if no imports were needed; FALSE otherwise. */
959 static Bool local addScript(stacknum) /* read single file */
962 static char name[FILENAME_MAX+1];
963 Int len = scriptInfo[stacknum].size;
965 #if HUGS_FOR_WINDOWS /* Set clock cursor while loading */
967 SetCursor(LoadCursor(NULL, IDC_WAIT));
970 // setLastEdit(name,0);
972 strcpy(name, scriptInfo[stacknum].path);
973 strcat(name, scriptInfo[stacknum].modName);
974 if (scriptInfo[stacknum].fromSource)
975 strcat(name, scriptInfo[stacknum].srcExt); else
976 strcat(name, ".u_hi");
980 if (scriptInfo[stacknum].fromSource) {
982 didPrelude = processInterfaces();
984 preludeLoaded = TRUE;
988 lastWasObject = FALSE;
989 Printf("Reading script \"%s\":\n",name);
990 needsImports = FALSE;
991 parseScript(name,len);
992 if (needsImports) return FALSE;
1000 char nameObj[FILENAME_MAX+1];
1003 Printf("Reading iface \"%s\":\n", name);
1005 needsImports = FALSE;
1007 // set nameObj for the benefit of openGHCIface
1008 strcpy(nameObj, scriptInfo[stacknum].path);
1009 strcat(nameObj, scriptInfo[stacknum].modName);
1010 strcat(nameObj, DLL_ENDING);
1011 sizeObj = scriptInfo[stacknum].oSize;
1013 iface = readInterface(name,len);
1014 imports = zsnd(iface); iface = zfst(iface);
1016 if (nonNull(imports)) chase(imports);
1018 lastWasObject = TRUE;
1020 iface_info = ztriple(iface, findText(nameObj), mkInt(sizeObj) );
1021 ifaces_outstanding = cons(iface_info,ifaces_outstanding);
1023 if (needsImports) return FALSE;
1032 Bool chase(imps) /* Process list of import requests */
1036 Int origPos = numScripts; /* keep track of original position */
1037 String origName = scriptInfo[origPos].modName;
1038 for (; nonNull(imps); imps=tl(imps)) {
1039 String iname = textToStr(textOf(hd(imps)));
1041 for (; i<namesUpto; i++)
1042 if (strcmp(scriptInfo[i].modName,iname)==0)
1044 //fprintf(stderr, "import name = %s num = %d\n", iname, i );
1047 /* We should have filled in the details of each module
1048 the first time we hear about it.
1050 assert(scriptInfo[i].details);
1053 if (i>=origPos) { /* Neither loaded or queued */
1059 needsImports = TRUE;
1060 if (scriptInfo[origPos].fromSource)
1061 scriptInfo[origPos].postponed = TRUE;
1063 if (i==namesUpto) { /* Name not found (i==namesUpto) */
1064 /* Find out where it lives, whether source or object, etc */
1065 makeStackEntry ( &scriptInfo[i], iname );
1069 if (scriptInfo[i].postponed && scriptInfo[i].fromSource) {
1070 /* Check for recursive dependency */
1072 "Recursive import dependency between \"%s\" and \"%s\"",
1073 scriptInfo[origPos].modName, iname
1076 /* Move stack entry i to somewhere below origPos. If i denotes
1077 * an object, destination is immediately below origPos.
1078 * Otherwise, it's underneath the queue of objects below origPos.
1080 dstPosn = origPos-1;
1081 if (scriptInfo[i].fromSource)
1082 while (!scriptInfo[dstPosn].fromSource && dstPosn > 0)
1086 tmp = scriptInfo[i];
1087 for (; i > dstPosn; i--) scriptInfo[i] = scriptInfo[i-1];
1088 scriptInfo[dstPosn] = tmp;
1089 if (dstPosn < nextNumScripts) nextNumScripts = dstPosn;
1093 return needsImports;
1096 static Void local forgetScriptsFrom(scno)/* remove scripts from system */
1100 for (i=scno; i<namesUpto; ++i)
1102 free(scriptName[i]);
1104 dropScriptsFrom(scno-1);
1106 if (numScripts>namesUpto)
1110 /* --------------------------------------------------------------------------
1111 * Commands for loading and removing script files:
1112 * ------------------------------------------------------------------------*/
1114 static Void local load() { /* read filenames from command line */
1115 String s; /* and add to list of scripts waiting */
1117 while ((s=readFilename())!=0)
1119 readScripts(N_PRELUDE_SCRIPTS);
1122 static Void local project() { /* read list of script names from */
1123 String s; /* project file */
1125 if ((s=readFilename()) || currProject) {
1127 s = strCopy(currProject);
1128 else if (readFilename()) {
1129 ERRMSG(0) "Too many project files"
1136 ERRMSG(0) "No project filename specified"
1140 readScripts(N_PRELUDE_SCRIPTS);
1143 static Void local readScripts(n) /* Reread current list of scripts, */
1144 Int n; { /* loading everything after and */
1145 Time timeStamp; /* including the first script which*/
1146 Long fileSize; /* has been either changed or added*/
1147 static char name[FILENAME_MAX+1];
1150 lastWasObject = FALSE;
1151 ppSmStack("readscripts-begin");
1152 #if HUGS_FOR_WINDOWS
1153 SetCursor(LoadCursor(NULL, IDC_WAIT));
1157 for (; n<numScripts; n++) { /* Scan previously loaded scripts */
1158 ppSmStack("readscripts-loop1");
1159 getFileInfo(scriptName[n], &timeStamp, &fileSize);
1160 if (timeChanged(timeStamp,lastChange[n])) {
1161 dropScriptsFrom(n-1);
1166 for (; n<NUM_SCRIPTS; n++) /* No scripts have been postponed */
1167 postponed[n] = FALSE; /* at this stage */
1170 while (numScripts<namesUpto) { /* Process any remaining scripts */
1171 ppSmStack("readscripts-loop2");
1172 getFileInfo(scriptName[numScripts], &timeStamp, &fileSize);
1173 timeSet(lastChange[numScripts],timeStamp);
1174 if (numScripts>0) /* no new script for prelude */
1175 startNewScript(scriptName[numScripts]);
1176 if (addScript(scriptName[numScripts],fileSize))
1179 dropScriptsFrom(numScripts-1);
1185 for (; n<numScripts; n++) {
1186 ppSmStack("readscripts-loop2");
1187 strcpy(name, scriptInfo[n].path);
1188 strcat(name, scriptInfo[n].modName);
1189 if (scriptInfo[n].fromSource)
1190 strcat(name, scriptInfo[n].srcExt); else
1191 strcat(name, ".u_hi"); //ToDo: should be .o
1192 getFileInfo(name,&timeStamp, &fileSize);
1193 if (timeChanged(timeStamp,scriptInfo[n].lastChange)) {
1194 dropScriptsFrom(n-1);
1199 for (; n<NUM_SCRIPTS; n++)
1200 scriptInfo[n].postponed = FALSE;
1204 while (numScripts < namesUpto) {
1205 ppSmStack ( "readscripts-loop2" );
1207 if (scriptInfo[numScripts].fromSource) {
1210 startNewScript(scriptInfo[numScripts].modName);
1211 nextNumScripts = NUM_SCRIPTS; //bogus initialisation
1212 if (addScript(numScripts)) {
1214 assert(nextNumScripts==NUM_SCRIPTS);
1217 dropScriptsFrom(numScripts-1);
1221 if (scriptInfo[numScripts].objLoaded) {
1224 scriptInfo[numScripts].objLoaded = TRUE;
1227 startNewScript(scriptInfo[numScripts].modName);
1229 nextNumScripts = NUM_SCRIPTS;
1230 if (addScript(numScripts)) {
1232 assert(nextNumScripts==NUM_SCRIPTS);
1234 //while (!scriptInfo[numScripts].fromSource && numScripts > 0)
1236 //if (scriptInfo[numScripts].fromSource)
1238 numScripts = nextNumScripts;
1239 assert(nextNumScripts<NUM_SCRIPTS);
1243 if (numScripts==namesUpto) ppSmStack( "readscripts-final") ;
1246 didPrelude = processInterfaces();
1248 preludeLoaded = TRUE;
1249 everybody(POSTPREL);
1253 { Int m = namesUpto-1;
1254 Text mtext = findText(scriptInfo[m].modName);
1256 /* Hack to avoid starting up in PrelHugs */
1257 if (mtext == findText("PrelHugs")) mtext = findText("Prelude");
1260 /* Commented out till we understand what
1261 * this is trying to do.
1262 * Problem, you cant find a module till later.
1265 setCurrModule(findModule(mtext));
1275 setLastEdit((String)0, 0);
1276 ppSmStack("readscripts-end ");
1279 static Void local whatScripts() { /* list scripts in current session */
1281 Printf("\nHugs session for:");
1283 Printf(" (project: %s)",currProject);
1284 for (i=0; i<numScripts; ++i)
1285 Printf("\n%s%s",scriptInfo[i].path, scriptInfo[i].modName);
1289 /* --------------------------------------------------------------------------
1290 * Access to external editor:
1291 * ------------------------------------------------------------------------*/
1293 static Void local editor() { /* interpreter-editor interface */
1294 String newFile = readFilename();
1296 setLastEdit(newFile,0);
1297 if (readFilename()) {
1298 ERRMSG(0) "Multiple filenames not permitted"
1305 static Void local find() { /* edit file containing definition */
1307 This just plain wont work no more.
1309 String nm = readFilename(); /* of specified name */
1311 ERRMSG(0) "No name specified"
1314 else if (readFilename()) {
1315 ERRMSG(0) "Multiple names not permitted"
1321 setCurrModule(findEvalModule());
1323 if (nonNull(c=findTycon(t=findText(nm)))) {
1324 if (startEdit(tycon(c).line,scriptName[scriptThisTycon(c)])) {
1325 readScripts(N_PRELUDE_SCRIPTS);
1327 } else if (nonNull(c=findName(t))) {
1328 if (startEdit(name(c).line,scriptName[scriptThisName(c)])) {
1329 readScripts(N_PRELUDE_SCRIPTS);
1332 ERRMSG(0) "No current definition for name \"%s\"", nm
1339 static Void local runEditor() { /* run editor on script lastEdit */
1340 if (startEdit(lastEdLine,lastEdit)) /* at line lastEdLine */
1341 readScripts(N_PRELUDE_SCRIPTS);
1344 static Void local setLastEdit(fname,line)/* keep name of last file to edit */
1349 lastEdit = strCopy(fname);
1351 #if HUGS_FOR_WINDOWS
1352 DrawStatusLine(hWndMain); /* Redo status line */
1356 /* --------------------------------------------------------------------------
1357 * Read and evaluate an expression:
1358 * ------------------------------------------------------------------------*/
1360 static Void local setModule(){/*set module in which to evaluate expressions*/
1361 String s = readFilename();
1362 if (!s) s = ""; /* :m clears the current module selection */
1363 evalModule = findText(s);
1364 setLastEdit(fileOfModule(findEvalModule()),0);
1367 static Module local findEvalModule() { /*Module in which to eval expressions*/
1368 Module m = findModule(evalModule);
1374 static Void local evaluator() { /* evaluate expr and print value */
1378 setCurrModule(findEvalModule());
1380 startNewScript(0); /* Enables recovery of storage */
1381 /* allocated during evaluation */
1384 defaultDefns = combined ? stdDefaults : evalDefaults;
1385 type = typeCheckExp(TRUE);
1387 if (isPolyType(type)) {
1388 ks = polySigOf(type);
1389 bd = monotypeOf(type);
1394 if (whatIs(bd)==QUAL) {
1395 ERRMSG(0) "Unresolved overloading" ETHEN
1396 ERRTEXT "\n*** Type : " ETHEN ERRTYPE(type);
1397 ERRTEXT "\n*** Expression : " ETHEN ERREXPR(inputExpr);
1407 if (isProgType(ks,bd)) {
1408 inputExpr = ap(nameRunIO_toplevel,inputExpr);
1412 Cell d = provePred(ks,NIL,ap(classShow,bd));
1414 ERRMSG(0) "Cannot find \"show\" function for:" ETHEN
1415 ERRTEXT "\n*** expression : " ETHEN ERREXPR(inputExpr);
1416 ERRTEXT "\n*** of type : " ETHEN ERRTYPE(type);
1420 inputExpr = ap2(nameShow, d,inputExpr);
1421 inputExpr = ap (namePutStr, inputExpr);
1422 inputExpr = ap (nameRunIO_toplevel, inputExpr);
1424 evalExp(); printf("\n");
1427 printType(stdout,type);
1434 printf ( "result type is " );
1435 printType ( stdout, type );
1444 static Void local stopAnyPrinting() { /* terminate printing of expression,*/
1445 if (printing) { /* after successful termination or */
1446 printing = FALSE; /* runtime error (e.g. interrupt) */
1449 #define plural(v) v, (v==1?"":"s")
1450 Printf("%lu cell%s",plural(numCells));
1452 Printf(", %u garbage collection%s",plural(numGcs));
1461 /* --------------------------------------------------------------------------
1462 * Print type of input expression:
1463 * ------------------------------------------------------------------------*/
1465 static Void local showtype() { /* print type of expression (if any)*/
1468 setCurrModule(findEvalModule());
1469 startNewScript(0); /* Enables recovery of storage */
1470 /* allocated during evaluation */
1473 defaultDefns = evalDefaults;
1474 type = typeCheckExp(FALSE);
1475 printExp(stdout,inputExpr);
1477 printType(stdout,type);
1482 static Void local browseit(mod,t,all)
1489 Printf("module %s where\n",textToStr(module(mod).text));
1490 for (cs = module(mod).names; nonNull(cs); cs=tl(cs)) {
1492 /* only look at things defined in this module,
1493 unless `all' flag is set */
1494 if (all || name(nm).mod == mod) {
1495 /* unwanted artifacts, like lambda lifted values,
1496 are in the list of names, but have no types */
1497 if (nonNull(name(nm).type)) {
1498 printExp(stdout,nm);
1500 printType(stdout,name(nm).type);
1502 Printf(" -- data constructor");
1503 } else if (isMfun(nm)) {
1504 Printf(" -- class member");
1505 } else if (isSfun(nm)) {
1506 Printf(" -- selector function");
1514 Printf("Unknown module %s\n",t);
1519 static Void local browse() { /* browse modules */
1520 Int count = 0; /* or give menu of commands */
1524 setCurrModule(findEvalModule());
1525 startNewScript(0); /* for recovery of storage */
1526 for (; (s=readFilename())!=0; count++)
1527 if (strcmp(s,"all") == 0) {
1531 browseit(findModule(findText(s)),s,all);
1533 browseit(findEvalModule(),NULL,all);
1537 #if EXPLAIN_INSTANCE_RESOLUTION
1538 static Void local xplain() { /* print type of expression (if any)*/
1540 Bool sir = showInstRes;
1542 setCurrModule(findEvalModule());
1543 startNewScript(0); /* Enables recovery of storage */
1544 /* allocated during evaluation */
1548 d = provePred(NIL,NIL,hd(inputContext));
1550 fprintf(stdout, "not Sat\n");
1552 fprintf(stdout, "Sat\n");
1558 /* --------------------------------------------------------------------------
1559 * Enhanced help system: print current list of scripts or give information
1561 * ------------------------------------------------------------------------*/
1563 static String local objToStr(m,c)
1566 #if 1 || DISPLAY_QUANTIFIERS
1567 static char newVar[60];
1568 switch (whatIs(c)) {
1569 case NAME : if (m == name(c).mod) {
1570 sprintf(newVar,"%s", textToStr(name(c).text));
1572 sprintf(newVar,"%s.%s",
1573 textToStr(module(name(c).mod).text),
1574 textToStr(name(c).text));
1578 case TYCON : if (m == tycon(c).mod) {
1579 sprintf(newVar,"%s", textToStr(tycon(c).text));
1581 sprintf(newVar,"%s.%s",
1582 textToStr(module(tycon(c).mod).text),
1583 textToStr(tycon(c).text));
1587 case CLASS : if (m == cclass(c).mod) {
1588 sprintf(newVar,"%s", textToStr(cclass(c).text));
1590 sprintf(newVar,"%s.%s",
1591 textToStr(module(cclass(c).mod).text),
1592 textToStr(cclass(c).text));
1596 default : internal("objToStr");
1600 static char newVar[33];
1601 switch (whatIs(c)) {
1602 case NAME : sprintf(newVar,"%s", textToStr(name(c).text));
1605 case TYCON : sprintf(newVar,"%s", textToStr(tycon(c).text));
1608 case CLASS : sprintf(newVar,"%s", textToStr(cclass(c).text));
1611 default : internal("objToStr");
1619 static Void dumpStg ( void )
1623 setCurrModule(findEvalModule());
1627 /* request to locate a symbol by name */
1628 if (s && (*s == '?')) {
1629 Text t = findText(s+1);
1630 locateSymbolByName(t);
1634 /* request to dump a bit of the heap */
1635 if (s && (*s == '-' || isdigit(*s))) {
1642 /* request to dump a symbol table entry */
1644 || !(*s == 't' || *s == 'n' || *s == 'c' || *s == 'i')
1645 || !isdigit(s[1])) {
1646 fprintf(stderr, ":d -- bad request `%s'\n", s );
1651 case 't': dumpTycon(i); break;
1652 case 'n': dumpName(i); break;
1653 case 'c': dumpClass(i); break;
1654 case 'i': dumpInst(i); break;
1655 default: fprintf(stderr, ":d -- `%c' not implemented\n", *s );
1661 static Void local dumpStg( void ) { /* print STG stuff */
1666 Cell v; /* really StgVar */
1667 setCurrModule(findEvalModule());
1669 for (; (s=readFilename())!=0;) {
1672 /* find the name while ignoring module scopes */
1673 for (i=NAMEMIN; i<nameHw; i++)
1674 if (name(i).text == t) n = i;
1676 /* perhaps it's an "idNNNNNN" thing? */
1679 s[0]=='i' && s[1]=='d' && isdigit(s[2])) {
1682 while (isdigit(s[i])) {
1683 v = v * 10 + (s[i]-'0');
1687 n = nameFromStgVar(v);
1690 if (isNull(n) && whatIs(v)==STGVAR) {
1691 Printf ( "\n{- `%s' has no nametable entry -}\n", s );
1692 printStg(stderr, v );
1695 Printf ( "Unknown reference `%s'\n", s );
1698 Printf ( "Not a Name: `%s'\n", s );
1700 if (isNull(name(n).stgVar)) {
1701 Printf ( "Doesn't have a STG tree: %s\n", s );
1703 Printf ( "\n{- stgVar of `%s' is id%d -}\n", s, -name(n).stgVar);
1704 printStg(stderr, name(n).stgVar);
1710 static Void local info() { /* describe objects */
1711 Int count = 0; /* or give menu of commands */
1714 setCurrModule(findEvalModule());
1715 startNewScript(0); /* for recovery of storage */
1716 for (; (s=readFilename())!=0; count++) {
1717 describe(findText(s));
1725 static Void local describe(t) /* describe an object */
1727 Tycon tc = findTycon(t);
1728 Class cl = findClass(t);
1729 Name nm = findName(t);
1731 if (nonNull(tc)) { /* as a type constructor */
1735 for (i=0; i<tycon(tc).arity; ++i) {
1736 t = ap(t,mkOffset(i));
1738 Printf("-- type constructor");
1740 Printf(" with kind ");
1741 printKind(stdout,tycon(tc).kind);
1744 switch (tycon(tc).what) {
1745 case SYNONYM : Printf("type ");
1746 printType(stdout,t);
1748 printType(stdout,tycon(tc).defn);
1752 case DATATYPE : { List cs = tycon(tc).defn;
1753 if (tycon(tc).what==DATATYPE) {
1758 printType(stdout,t);
1760 mapProc(printSyntax,cs);
1762 Printf("\n-- constructors:");
1764 for (; hasCfun(cs); cs=tl(cs)) {
1766 printExp(stdout,hd(cs));
1768 printType(stdout,name(hd(cs)).type);
1771 Printf("\n-- selectors:");
1773 for (; nonNull(cs); cs=tl(cs)) {
1775 printExp(stdout,hd(cs));
1777 printType(stdout,name(hd(cs)).type);
1782 case RESTRICTSYN : Printf("type ");
1783 printType(stdout,t);
1784 Printf(" = <restricted>");
1788 if (nonNull(in=findFirstInst(tc))) {
1789 Printf("\n-- instances:\n");
1792 in = findNextInst(tc,in);
1793 } while (nonNull(in));
1798 if (nonNull(cl)) { /* as a class */
1799 List ins = cclass(cl).instances;
1800 Kinds ks = cclass(cl).kinds;
1801 if (nonNull(ks) && isNull(tl(ks)) && hd(ks)==STAR) {
1802 Printf("-- type class");
1804 Printf("-- constructor class");
1806 Printf(" with arity ");
1807 printKinds(stdout,ks);
1811 mapProc(printSyntax,cclass(cl).members);
1813 if (nonNull(cclass(cl).supers)) {
1814 printContext(stdout,cclass(cl).supers);
1817 printPred(stdout,cclass(cl).head);
1819 if (nonNull(cclass(cl).fds)) {
1820 List fds = cclass(cl).fds;
1822 for (; nonNull(fds); fds=tl(fds)) {
1824 printFD(stdout,hd(fds));
1829 if (nonNull(cclass(cl).members)) {
1830 List ms = cclass(cl).members;
1833 Type t = name(hd(ms)).type;
1834 if (isPolyType(t)) {
1838 printExp(stdout,hd(ms));
1840 if (isNull(tl(fst(snd(t))))) {
1843 t = ap(QUAL,pair(tl(fst(snd(t))),snd(snd(t))));
1845 printType(stdout,t);
1847 } while (nonNull(ms));
1851 Printf("\n-- instances:\n");
1855 } while (nonNull(ins));
1860 if (nonNull(nm)) { /* as a function/name */
1862 printExp(stdout,nm);
1864 if (nonNull(name(nm).type)) {
1865 printType(stdout,name(nm).type);
1867 Printf("<unknown type>");
1870 Printf(" -- data constructor");
1871 } else if (isMfun(nm)) {
1872 Printf(" -- class member");
1873 } else if (isSfun(nm)) {
1874 Printf(" -- selector function");
1880 if (isNull(tc) && isNull(cl) && isNull(nm)) {
1881 Printf("Unknown reference `%s'\n",textToStr(t));
1885 static Void local printSyntax(nm)
1887 Syntax sy = syntaxOf(nm);
1888 Text t = name(nm).text;
1889 String s = textToStr(t);
1890 if (sy != defaultSyntax(t)) {
1892 switch (assocOf(sy)) {
1893 case LEFT_ASS : Putchar('l'); break;
1894 case RIGHT_ASS : Putchar('r'); break;
1895 case NON_ASS : break;
1897 Printf(" %i ",precOf(sy));
1898 if (isascii((int)(*s)) && isalpha((int)(*s))) {
1907 static Void local showInst(in) /* Display instance decl header */
1909 Printf("instance ");
1910 if (nonNull(inst(in).specifics)) {
1911 printContext(stdout,inst(in).specifics);
1914 printPred(stdout,inst(in).head);
1918 /* --------------------------------------------------------------------------
1919 * List all names currently in scope:
1920 * ------------------------------------------------------------------------*/
1922 static Void local listNames() { /* list names matching optional pat*/
1923 String pat = readFilename();
1925 Int width = getTerminalWidth() - 1;
1928 Module mod = findEvalModule();
1930 if (pat) { /* First gather names to list */
1932 names = addNamesMatching(pat,names);
1933 } while ((pat=readFilename())!=0);
1935 names = addNamesMatching((String)0,names);
1937 if (isNull(names)) { /* Then print them out */
1938 ERRMSG(0) "No names selected"
1941 for (termPos=0; nonNull(names); names=tl(names)) {
1942 String s = objToStr(mod,hd(names));
1944 if (termPos+1+l>width) {
1947 } else if (termPos>0) {
1955 Printf("\n(%d names listed)\n", count);
1958 /* --------------------------------------------------------------------------
1959 * print a prompt and read a line of input:
1960 * ------------------------------------------------------------------------*/
1962 static Void local promptForInput(moduleName)
1963 String moduleName; {
1964 char promptBuffer[1000];
1966 /* This is portable but could overflow buffer */
1967 sprintf(promptBuffer,prompt,moduleName);
1969 /* Works on ANSI C - but pre-ANSI compilers return a pointer to
1970 * promptBuffer instead.
1972 if (sprintf(promptBuffer,prompt,moduleName) >= 1000) {
1973 /* Reset prompt to a safe default to avoid an infinite loop */
1975 prompt = strCopy("? ");
1976 internal("Combined prompt and evaluation module name too long");
1980 stringInput("main\0"); else
1981 consoleInput(promptBuffer);
1984 /* --------------------------------------------------------------------------
1985 * main read-eval-print loop, with error trapping:
1986 * ------------------------------------------------------------------------*/
1988 static jmp_buf catch_error; /* jump buffer for error trapping */
1990 static Void local interpreter(argc,argv)/* main interpreter loop */
1993 Int errorNumber = setjmp(catch_error);
1995 if (errorNumber && autoMain) {
1996 fprintf(stderr, "hugs +Q: compilation failed -- can't run `main'\n" );
2000 breakOn(TRUE); /* enable break trapping */
2001 if (numScripts==0) { /* only succeeds on first time, */
2002 if (errorNumber) /* before prelude has been loaded */
2003 fatal("Unable to load prelude");
2004 initialize(argc,argv);
2008 /* initialize calls startupHaskell, which trashes our signal handlers */
2013 everybody(RESET); /* reset to sensible initial state */
2014 dropScriptsFrom(numScripts-1); /* remove partially loaded scripts */
2015 /* not counting prelude as a script*/
2017 promptForInput(textToStr(module(findEvalModule()).text));
2019 cmd = readCommand(cmds, (Char)':', (Char)'!');
2024 case EDIT : editor();
2028 case LOAD : clearProject();
2029 forgetScriptsFrom(N_PRELUDE_SCRIPTS);
2032 case ALSO : clearProject();
2033 forgetScriptsFrom(numScripts);
2036 case RELOAD : readScripts(N_PRELUDE_SCRIPTS);
2038 case PROJECT: project();
2043 case EVAL : evaluator();
2045 case TYPEOF : showtype();
2047 case BROWSE : browse();
2049 #if EXPLAIN_INSTANCE_RESOLUTION
2050 case XPLAIN : xplain();
2053 case NAMES : listNames();
2057 case BADCMD : guidance();
2062 #ifdef CRUDE_PROFILING
2066 case SYSTEM : if (shellEsc(readLine()))
2067 Printf("Warning: Shell escape terminated abnormally\n");
2069 case CHGDIR : changeDir();
2073 case PNTVER: Printf("-- Hugs Version %s\n",
2076 case DUMP : dumpStg();
2079 case COLLECT: consGC = FALSE;
2082 Printf("Garbage collection recovered %d cells\n",
2089 Printf("Elapsed time (ms): %ld (user), %ld (system)\n",
2090 millisecs(userElapsed), millisecs(systElapsed));
2092 if (autoMain) break;
2097 /* --------------------------------------------------------------------------
2098 * Display progress towards goal:
2099 * ------------------------------------------------------------------------*/
2101 static Target currTarget;
2102 static Bool aiming = FALSE;
2105 static Int charCount;
2107 Void setGoal(what, t) /* Set goal for what to be t */
2112 #if EXPLAIN_INSTANCE_RESOLUTION
2116 currTarget = (t?t:1);
2119 currPos = strlen(what);
2120 maxPos = getTerminalWidth() - 1;
2124 for (charCount=0; *what; charCount++)
2129 Void soFar(t) /* Indicate progress towards goal */
2130 Target t; { /* has now reached t */
2133 #if EXPLAIN_INSTANCE_RESOLUTION
2138 Int newPos = (Int)((maxPos * ((long)t))/currTarget);
2143 if (newPos>currPos) {
2146 while (newPos>++currPos);
2153 Void done() { /* Goal has now been achieved */
2156 #if EXPLAIN_INSTANCE_RESOLUTION
2161 while (maxPos>currPos++)
2166 for (; charCount>0; charCount--) {
2175 static Void local failed() { /* Goal cannot be reached due to */
2176 if (aiming) { /* errors */
2183 /* --------------------------------------------------------------------------
2185 * ------------------------------------------------------------------------*/
2187 Cell errAssert(l) /* message to use when raising asserts, etc */
2192 str = mkStr(findText(scriptFile));
2194 str = mkStr(findText(""));
2196 return (ap2(nameTangleMessage,str,mkInt(l)));
2200 Void errHead(l) /* print start of error message */
2202 failed(); /* failed to reach target ... */
2204 FPrintf(errorStream,"ERROR");
2207 FPrintf(errorStream," \"%s\"", scriptFile);
2208 setLastEdit(scriptFile,l);
2209 if (l) FPrintf(errorStream," (line %d)",l);
2212 FPrintf(errorStream,": ");
2213 FFlush(errorStream);
2216 Void errFail() { /* terminate error message and */
2217 Putc('\n',errorStream); /* produce exception to return to */
2218 FFlush(errorStream); /* main command loop */
2219 longjmp(catch_error,1);
2222 Void errAbort() { /* altern. form of error handling */
2223 failed(); /* used when suitable error message*/
2224 stopAnyPrinting(); /* has already been printed */
2228 Void internal(msg) /* handle internal error */
2230 #if HUGS_FOR_WINDOWS
2232 wsprintf(buf,"INTERNAL ERROR: %s",msg);
2233 MessageBox(hWndMain, buf, appName, MB_ICONHAND | MB_OK);
2237 Printf("INTERNAL ERROR: %s\n",msg);
2239 longjmp(catch_error,1);
2242 Void fatal(msg) /* handle fatal error */
2244 #if HUGS_FOR_WINDOWS
2246 wsprintf(buf,"FATAL ERROR: %s",msg);
2247 MessageBox(hWndMain, buf, appName, MB_ICONHAND | MB_OK);
2250 Printf("\nFATAL ERROR: %s\n",msg);
2255 sigHandler(breakHandler) { /* respond to break interrupt */
2256 #if HUGS_FOR_WINDOWS
2257 MessageBox(GetFocus(), "Interrupted!", appName, MB_ICONSTOP | MB_OK);
2260 Printf("{Interrupted!}\n");
2262 breakOn(TRUE); /* reinstall signal handler - redundant on BSD systems */
2263 /* but essential on POSIX (and other?) systems */
2269 longjmp(catch_error,1);
2270 sigResume;/*NOTREACHED*/
2273 /* --------------------------------------------------------------------------
2274 * Read value from environment variable or registry:
2275 * ------------------------------------------------------------------------*/
2277 String fromEnv(var,def) /* return value of: */
2278 String var; /* environment variable named by var */
2279 String def; { /* or: default value given by def */
2280 String s = getenv(var);
2281 return (s ? s : def);
2284 /* --------------------------------------------------------------------------
2285 * String manipulation routines:
2286 * ------------------------------------------------------------------------*/
2288 static String local strCopy(s) /* make malloced copy of a string */
2292 if ((t=(char *)malloc(strlen(s)+1))==0) {
2293 ERRMSG(0) "String storage space exhausted"
2296 for (r=t; (*r++ = *s++)!=0; ) {
2303 /* --------------------------------------------------------------------------
2305 * We can redirect compiler output (prompts, error messages, etc) by
2306 * tweaking these functions.
2307 * ------------------------------------------------------------------------*/
2309 #if REDIRECT_OUTPUT && !HUGS_FOR_WINDOWS
2311 #ifdef HAVE_STDARG_H
2314 #include <varargs.h>
2317 /* ----------------------------------------------------------------------- */
2319 #define BufferSize 10000 /* size of redirected output buffer */
2321 typedef struct _HugsStream {
2322 char buffer[BufferSize]; /* buffer for redirected output */
2323 Int next; /* next space in buffer */
2326 static Void local vBufferedPrintf ( HugsStream*, const char*, va_list );
2327 static Void local bufferedPutchar ( HugsStream*, Char );
2328 static String local bufferClear ( HugsStream *stream );
2330 static Void local vBufferedPrintf(stream, fmt, ap)
2334 Int spaceLeft = BufferSize - stream->next;
2335 char* p = &stream->buffer[stream->next];
2336 Int charsAdded = vsnprintf(p, spaceLeft, fmt, ap);
2337 if (0 <= charsAdded && charsAdded < spaceLeft)
2338 stream->next += charsAdded;
2339 #if 1 /* we can either buffer the first n chars or buffer the last n chars */
2345 static Void local bufferedPutchar(stream, c)
2348 if (BufferSize - stream->next >= 2) {
2349 stream->buffer[stream->next++] = c;
2350 stream->buffer[stream->next] = '\0';
2354 static String local bufferClear(stream)
2355 HugsStream *stream; {
2356 if (stream->next == 0) {
2360 return stream->buffer;
2364 /* ----------------------------------------------------------------------- */
2366 static HugsStream outputStreamH;
2368 * We rely on standard C semantics to initialise outputStreamH.next to 0.
2371 Void hugsEnableOutput(f)
2376 String hugsClearOutputBuffer() {
2377 return bufferClear(&outputStreamH);
2380 #ifdef HAVE_STDARG_H
2381 Void hugsPrintf(const char *fmt, ...) {
2382 va_list ap; /* pointer into argument list */
2383 va_start(ap, fmt); /* make ap point to first arg after fmt */
2384 if (!disableOutput) {
2387 vBufferedPrintf(&outputStreamH, fmt, ap);
2389 va_end(ap); /* clean up */
2392 Void hugsPrintf(fmt, va_alist)
2395 va_list ap; /* pointer into argument list */
2396 va_start(ap); /* make ap point to first arg after fmt */
2397 if (!disableOutput) {
2400 vBufferedPrintf(&outputStreamH, fmt, ap);
2402 va_end(ap); /* clean up */
2408 if (!disableOutput) {
2411 bufferedPutchar(&outputStreamH, c);
2415 Void hugsFlushStdout() {
2416 if (!disableOutput) {
2423 if (!disableOutput) {
2428 #ifdef HAVE_STDARG_H
2429 Void hugsFPrintf(FILE *fp, const char* fmt, ...) {
2432 if (!disableOutput) {
2433 vfprintf(fp, fmt, ap);
2435 vBufferedPrintf(&outputStreamH, fmt, ap);
2440 Void hugsFPrintf(FILE *fp, const char* fmt, va_list)
2446 if (!disableOutput) {
2447 vfprintf(fp, fmt, ap);
2449 vBufferedPrintf(&outputStreamH, fmt, ap);
2455 Void hugsPutc(c, fp)
2458 if (!disableOutput) {
2461 bufferedPutchar(&outputStreamH, c);
2465 #endif /* REDIRECT_OUTPUT && !HUGS_FOR_WINDOWS */
2466 /* --------------------------------------------------------------------------
2467 * Send message to each component of system:
2468 * ------------------------------------------------------------------------*/
2470 Void everybody(what) /* send command `what' to each component of*/
2471 Int what; { /* system to respond as appropriate ... */
2473 fprintf ( stderr, "EVERYBODY %d\n", what );
2475 machdep(what); /* The order of calling each component is */
2476 storage(what); /* important for the PREPREL command */
2479 translateControl(what);
2481 staticAnalysis(what);
2482 deriveControl(what);
2488 /* --------------------------------------------------------------------------
2489 * Hugs for Windows code (WinMain and related functions)
2490 * ------------------------------------------------------------------------*/
2492 #if HUGS_FOR_WINDOWS
2493 #include "winhugs.c"