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/10 20:03:36 $
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 Args((Int,String []));
45 static Void local promptForInput Args((String));
46 static Void local interpreter Args((Int,String []));
47 static Void local menu Args((Void));
48 static Void local guidance Args((Void));
49 static Void local forHelp Args((Void));
50 static Void local set Args((Void));
51 static Void local changeDir Args((Void));
52 static Void local load Args((Void));
53 static Void local project Args((Void));
54 static Void local readScripts Args((Int));
55 static Void local whatScripts Args((Void));
56 static Void local editor Args((Void));
57 static Void local find Args((Void));
58 static Bool local startEdit Args((Int,String));
59 static Void local runEditor Args((Void));
60 static Void local setModule Args((Void));
61 static Module local findEvalModule Args((Void));
62 static Void local evaluator Args((Void));
63 static Void local stopAnyPrinting Args((Void));
64 static Void local showtype Args((Void));
65 static String local objToStr Args((Module, Cell));
66 static Void local info Args((Void));
67 static Void local printSyntax Args((Name));
68 static Void local showInst Args((Inst));
69 static Void local describe Args((Text));
70 static Void local listNames Args((Void));
72 static Void local toggleSet Args((Char,Bool));
73 static Void local togglesIn Args((Bool));
74 static Void local optionInfo Args((Void));
75 #if USE_REGISTRY || HUGS_FOR_WINDOWS
76 static String local optionsToStr Args((Void));
78 static Void local readOptions Args((String));
79 static Bool local processOption Args((String));
80 static Void local setHeapSize Args((String));
81 static Int local argToInt Args((String));
83 static Void local loadProject Args((String));
84 static Void local clearProject Args((Void));
85 static Bool local addScript Args((Int));
86 static Void local forgetScriptsFrom Args((Script));
87 static Void local setLastEdit Args((String,Int));
88 static Void local failed Args((Void));
89 static String local strCopy Args((String));
90 static Void local browseit Args((Module,String,Bool));
91 static Void local browse Args((Void));
93 /* --------------------------------------------------------------------------
94 * Machine dependent code for Hugs interpreter:
95 * ------------------------------------------------------------------------*/
104 /* --------------------------------------------------------------------------
106 * ------------------------------------------------------------------------*/
108 static Bool printing = FALSE; /* TRUE => currently printing value*/
109 static Bool showStats = FALSE; /* TRUE => print stats after eval */
110 static Bool listScripts = TRUE; /* TRUE => list scripts after loading*/
111 static Bool addType = FALSE; /* TRUE => print type with value */
112 static Bool useDots = RISCOS; /* TRUE => use dots in progress */
113 static Bool quiet = FALSE; /* TRUE => don't show progress */
114 static Bool lastWasObject = FALSE;
115 Bool preludeLoaded = FALSE;
116 Bool debugSC = FALSE;
120 String modName; /* Module name */
121 Bool details; /* FALSE => remaining fields are invalid */
122 String path; /* Path to module */
123 String srcExt; /* ".hs" or ".lhs" if fromSource */
124 Time lastChange; /* Time of last change to script */
125 Bool fromSource; /* FALSE => load object code */
126 Bool postponed; /* Indicates postponed load */
133 static Void local makeStackEntry Args((ScriptInfo*,String));
134 static Void local addStackEntry Args((String));
136 static ScriptInfo scriptInfo[NUM_SCRIPTS];
138 static Int numScripts; /* Number of scripts loaded */
139 static Int nextNumScripts;
140 static Int namesUpto; /* Number of script names set */
141 static Bool needsImports; /* set to TRUE if imports required */
142 String scriptFile; /* Name of current script (if any) */
146 static Text evalModule = 0; /* Name of module we eval exprs in */
147 static String currProject = 0; /* Name of current project file */
148 static Bool projectLoaded = FALSE; /* TRUE => project file loaded */
150 static Bool autoMain = FALSE;
151 static String lastEdit = 0; /* Name of script to edit (if any) */
152 static Int lastEdLine = 0; /* Editor line number (if possible)*/
153 static String prompt = 0; /* Prompt string */
154 static Int hpSize = DEFAULTHEAP; /* Desired heap size */
155 String hugsEdit = 0; /* String for editor command */
156 String hugsPath = 0; /* String for file search path */
158 List ifaces_outstanding = NIL;
161 static Bool disableOutput = FALSE; /* redirect output to buffer? */
164 String bool2str ( Bool b )
166 if (b) return "Yes"; else return "No ";
169 void ppSmStack ( String who )
173 fflush(stdout);fflush(stderr);
175 printf ( "ppSmStack %s: numScripts = %d namesUpto = %d needsImports = %s\n",
176 who, numScripts, namesUpto, bool2str(needsImports) );
177 assert (namesUpto >= numScripts);
178 printf ( " Det FrS Pst ObL Module Ext Size ModTime Path\n" );
179 for (i = namesUpto-1; i >= 0; i--) {
180 printf ( "%c%2d: %3s %3s %3s %3s %16s %-4s %5ld %8lx %s\n",
181 (i==numScripts ? '*' : ' '),
182 i, bool2str(scriptInfo[i].details),
183 bool2str(scriptInfo[i].fromSource),
184 bool2str(scriptInfo[i].postponed),
185 bool2str(scriptInfo[i].objLoaded),
186 scriptInfo[i].modName,
187 scriptInfo[i].fromSource ? scriptInfo[i].srcExt : "",
189 scriptInfo[i].lastChange,
193 fflush(stdout);fflush(stderr);
199 /* --------------------------------------------------------------------------
201 * ------------------------------------------------------------------------*/
203 #ifndef NO_MAIN /* we omit main when building the "Hugs server" */
205 Main main Args((Int, String [])); /* now every func has a prototype */
210 #ifdef HAVE_CONSOLE_H /* Macintosh port */
212 _fcreator = 'R*ch'; /* // 'KAHL'; //'*TEX'; //'ttxt'; */
214 console_options.top = 50;
215 console_options.left = 20;
217 console_options.nrows = 32;
218 console_options.ncols = 80;
220 console_options.pause_atexit = 1;
221 console_options.title = "\pHugs";
223 console_options.procID = 5;
224 argc = ccommand(&argv);
227 CStackBase = &argc; /* Save stack base for use in gc */
229 /* If first arg is +Q or -Q, be entirely silent, and automatically run
230 main after loading scripts. Useful for running the nofib suite. */
231 if (argc > 1 && (strcmp(argv[1],"+Q") == 0 || strcmp(argv[1],"-Q")==0)) {
233 if (strcmp(argv[1],"-Q") == 0) {
238 Printf("__ __ __ __ ____ ___ _________________________________________\n");
239 Printf("|| || || || || || ||__ STGHugs: Based on the Haskell 98 standard\n");
240 Printf("||___|| ||__|| ||__|| __|| Copyright (c) 1994-1999\n");
241 Printf("||---|| ___|| World Wide Web: http://haskell.org/hugs\n");
242 Printf("|| || Report bugs to: hugs-bugs@haskell.org\n");
243 Printf("|| || Version: %s _________________________________________\n\n",HUGS_VERSION);
245 /* Get the absolute path to the directory containing the hugs
246 executable, so that we know where the Prelude and nHandle.so/.dll are.
247 We do this by reading env var STGHUGSDIR. This needs to succeed, so
248 setInstallDir won't return unless it succeeds.
250 setInstallDir ( argv[0] );
253 Printf(" Ported to Macintosh by Hans Aberg, compiled " __DATE__ ".\n\n");
256 interpreter(argc,argv);
257 Printf("[Leaving Hugs]\n");
268 /* --------------------------------------------------------------------------
269 * Initialization, interpret command line args and read prelude:
270 * ------------------------------------------------------------------------*/
272 static Void local initialize(argc,argv)/* Interpreter initialization */
277 char argv_0_orig[1000];
279 setLastEdit((String)0,0);
286 hugsEdit = strCopy(fromEnv("EDITOR","c:\\windows\\notepad.exe"));
290 hugsEdit = strCopy(fromEnv("EDITOR",NULL));
292 hugsPath = strCopy(HUGSPATH);
293 readOptions("-p\"%s> \" -r$$");
295 projectPath = strCopy(readRegChildStrings(HKEY_LOCAL_MACHINE,ProjectRoot,
296 "HUGSPATH", PATHSEP, ""));
297 readOptions(readRegString(HKEY_LOCAL_MACHINE,HugsRoot,"Options",""));
298 readOptions(readRegString(HKEY_CURRENT_USER, HugsRoot,"Options",""));
299 #endif /* USE_REGISTRY */
300 readOptions(fromEnv("STGHUGSFLAGS",""));
302 strncpy(argv_0_orig,argv[0],1000); /* startupHaskell mangles argv[0] */
303 startupHaskell (argc,argv);
304 argc = prog_argc; argv = prog_argv;
306 namesUpto = numScripts = 0;
308 /* Pre-scan flags to see if -c or +c is present. This needs to
309 precede adding the stack entry for Prelude. On the other hand,
310 that stack entry needs to be made before the cmd line args are
311 properly examined. Hence the following pre-scan of them.
313 for (i=1; i < argc; ++i) {
314 if (strcmp(argv[i], "--")==0) break;
315 if (strcmp(argv[i], "-c")==0) combined = FALSE;
316 if (strcmp(argv[i], "+c")==0) combined = TRUE;
319 addStackEntry("Prelude");
320 if (combined) addStackEntry("PrelHugs");
322 for (i=1; i < argc; ++i) { /* process command line arguments */
323 if (strcmp(argv[i], "--")==0) break;
324 if (strcmp(argv[i],"+")==0 && i+1<argc) {
326 ERRMSG(0) "Multiple project filenames on command line"
331 } else if (argv[i] && argv[i][0]/* workaround for /bin/sh silliness*/
332 && !processOption(argv[i])) {
333 addStackEntry(argv[i]);
339 char exe_name[N_INSTALLDIR + 6];
340 strcpy(exe_name, installDir);
341 strcat(exe_name, "hugs");
342 DEBUG_LoadSymbols(exe_name);
348 if (!scriptName[0]) {
349 Printf("Prelude not found on current path: \"%s\"\n",
350 hugsPath ? hugsPath : "");
351 fatal("Unable to load prelude");
356 Printf("Haskell 98 mode: Restart with command line option -98 to enable extensions\n");
358 Printf("Hugs mode: Restart with command line option +98 for Haskell 98 mode\n");
362 Printf("Combined mode: Restart with command line -c for standalone mode\n\n" );
364 Printf("Standalone mode: Restart with command line +c for combined mode\n\n" );
369 evalModule = findText(""); /* evaluate wrt last module by default */
373 "\nUsing project file, ignoring additional filenames\n");
375 loadProject(strCopy(proj));
380 /* --------------------------------------------------------------------------
381 * Command line options:
382 * ------------------------------------------------------------------------*/
384 struct options { /* command line option toggles */
385 char c; /* table defined in main app. */
390 extern struct options toggle[];
392 static Void local toggleSet(c,state) /* Set command line toggle */
396 for (i=0; toggle[i].c; ++i)
397 if (toggle[i].c == c) {
398 *toggle[i].flag = state;
401 ERRMSG(0) "Unknown toggle `%c'", c
405 static Void local togglesIn(state) /* Print current list of toggles in*/
406 Bool state; { /* given state */
409 for (i=0; toggle[i].c; ++i)
410 if (*toggle[i].flag == state && (!haskell98 || toggle[i].h98)) {
412 Putchar((char)(state ? '+' : '-'));
413 Putchar(toggle[i].c);
420 static Void local optionInfo() { /* Print information about command */
421 static String fmts = "%-5s%s\n"; /* line settings */
422 static String fmtc = "%-5c%s\n";
425 Printf("TOGGLES: groups begin with +/- to turn options on/off resp.\n");
426 for (i=0; toggle[i].c; ++i) {
427 if (!haskell98 || toggle[i].h98) {
428 Printf(fmtc,toggle[i].c,toggle[i].description);
432 Printf("\nOTHER OPTIONS: (leading + or - makes no difference)\n");
433 Printf(fmts,"hnum","Set heap size (cannot be changed within Hugs)");
434 Printf(fmts,"pstr","Set prompt string to str");
435 Printf(fmts,"rstr","Set repeat last expression string to str");
436 Printf(fmts,"Pstr","Set search path for modules to str");
437 Printf(fmts,"Estr","Use editor setting given by str");
438 Printf(fmts,"cnum","Set constraint cutoff limit");
439 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
440 Printf(fmts,"Fstr","Set preprocessor filter to str");
443 Printf("\nCurrent settings: ");
446 Printf("-h%d",heapSize);
450 printString(repeatStr);
451 Printf(" -c%d",cutoff);
452 Printf("\nSearch path : -P");
453 printString(hugsPath);
456 if (projectPath!=NULL) {
457 Printf("\nProject Path : %s",projectPath);
460 Printf("\nEditor setting : -E");
461 printString(hugsEdit);
462 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
463 Printf("\nPreprocessor : -F");
464 printString(preprocessor);
466 Printf("\nCompatibility : %s", haskell98 ? "Haskell 98 (+98)"
467 : "Hugs Extensions (-98)");
471 #if USE_REGISTRY || HUGS_FOR_WINDOWS
479 #define PUTInt(optc,i) \
480 sprintf(next,"-%c%d",optc,i); \
483 #define PUTStr(c,s) \
484 next=PUTStr_aux(next,c,s)
486 static String local PUTStr_aux Args((String,Char, String));
488 static String local PUTStr_aux(next,c,s)
494 sprintf(next,"-%c\"",c);
497 PUTS(unlexChar(*t,'"'));
505 static String local optionsToStr() { /* convert options to string */
506 static char buffer[2000];
507 String next = buffer;
510 for (i=0; toggle[i].c; ++i) {
511 PUTC(*toggle[i].flag ? '+' : '-');
515 PUTS(haskell98 ? "+98 " : "-98 ");
516 PUTInt('h',hpSize); PUTC(' ');
518 PUTStr('r',repeatStr);
519 PUTStr('P',hugsPath);
520 PUTStr('E',hugsEdit);
521 PUTInt('c',cutoff); PUTC(' ');
522 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
523 PUTStr('F',preprocessor);
528 #endif /* USE_REGISTRY */
535 static Void local readOptions(options) /* read options from string */
539 stringInput(options);
540 while ((s=readFilename())!=0) {
541 if (*s && !processOption(s)) {
542 ERRMSG(0) "Option string must begin with `+' or `-'"
549 static Bool local processOption(s) /* process string s for options, */
550 String s; { /* return FALSE if none found. */
562 case 'Q' : break; /* already handled */
564 case 'p' : if (s[1]) {
565 if (prompt) free(prompt);
566 prompt = strCopy(s+1);
570 case 'r' : if (s[1]) {
571 if (repeatStr) free(repeatStr);
572 repeatStr = strCopy(s+1);
577 String p = substPath(s+1,hugsPath ? hugsPath : "");
578 if (hugsPath) free(hugsPath);
583 case 'E' : if (hugsEdit) free(hugsEdit);
584 hugsEdit = strCopy(s+1);
587 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
588 case 'F' : if (preprocessor) free(preprocessor);
589 preprocessor = strCopy(s+1);
593 case 'h' : setHeapSize(s+1);
596 case 'c' : if (heapBuilt()) {
598 "You can't enable/disable combined"
599 " operation inside Hugs\n" );
601 /* don't do anything, since pre-scan of args
602 will have got it already */
606 case 'D' : /* hack */
608 extern void setRtsFlags( int x );
609 setRtsFlags(argToInt(s+1));
613 default : if (strcmp("98",s)==0) {
614 if (heapBuilt() && ((state && !haskell98) ||
615 (!state && haskell98))) {
617 "Haskell 98 compatibility cannot be changed"
618 " while the interpreter is running\n");
631 static Void local setHeapSize(s)
634 hpSize = argToInt(s);
635 if (hpSize < MINIMUMHEAP)
636 hpSize = MINIMUMHEAP;
637 else if (MAXIMUMHEAP && hpSize > MAXIMUMHEAP)
638 hpSize = MAXIMUMHEAP;
639 if (heapBuilt() && hpSize != heapSize) {
640 /* ToDo: should this use a message box in winhugs? */
642 FPrintf(stderr,"Change to heap size will not take effect until you rerun Hugs\n");
644 FPrintf(stderr,"You cannot change heap size from inside Hugs\n");
652 static Int local argToInt(s) /* read integer from argument str */
657 if (*s=='\0' || !isascii((int)(*s)) || !isdigit((int)(*s))) {
658 ERRMSG(0) "Missing integer in option setting \"%s\"", t
663 Int d = (*s++) - '0';
664 if (n > ((MAXPOSINT - d)/10)) {
665 ERRMSG(0) "Option setting \"%s\" is too large", t
669 } while (isascii((int)(*s)) && isdigit((int)(*s)));
671 if (*s=='K' || *s=='k') {
672 if (n > (MAXPOSINT/1000)) {
673 ERRMSG(0) "Option setting \"%s\" is too large", t
680 #if MAXPOSINT > 1000000 /* waste of time on 16 bit systems */
681 if (*s=='M' || *s=='m') {
682 if (n > (MAXPOSINT/1000000)) {
683 ERRMSG(0) "Option setting \"%s\" is too large", t
691 #if MAXPOSINT > 1000000000
692 if (*s=='G' || *s=='g') {
693 if (n > (MAXPOSINT/1000000000)) {
694 ERRMSG(0) "Option setting \"%s\" is too large", t
703 ERRMSG(0) "Unwanted characters after option setting \"%s\"", t
710 /* --------------------------------------------------------------------------
711 * Print Menu of list of commands:
712 * ------------------------------------------------------------------------*/
714 static struct cmd cmds[] = {
715 {":?", HELP}, {":cd", CHGDIR}, {":also", ALSO},
716 {":type", TYPEOF}, {":!", SYSTEM}, {":load", LOAD},
717 {":reload", RELOAD}, {":gc", COLLECT}, {":edit", EDIT},
718 {":quit", QUIT}, {":set", SET}, {":find", FIND},
719 {":names", NAMES}, {":info", INFO}, {":project", PROJECT},
720 {":dump", DUMP}, {":ztats", STATS},
721 {":module",SETMODULE},
723 #if EXPLAIN_INSTANCE_RESOLUTION
726 {":version", PNTVER},
731 static Void local menu() {
732 Printf("LIST OF COMMANDS: Any command may be abbreviated to :c where\n");
733 Printf("c is the first character in the full name.\n\n");
734 Printf(":load <filenames> load modules from specified files\n");
735 Printf(":load clear all files except prelude\n");
736 Printf(":also <filenames> read additional modules\n");
737 Printf(":reload repeat last load command\n");
738 Printf(":project <filename> use project file\n");
739 Printf(":edit <filename> edit file\n");
740 Printf(":edit edit last module\n");
741 Printf(":module <module> set module for evaluating expressions\n");
742 Printf("<expr> evaluate expression\n");
743 Printf(":type <expr> print type of expression\n");
744 Printf(":? display this list of commands\n");
745 Printf(":set <options> set command line options\n");
746 Printf(":set help on command line options\n");
747 Printf(":names [pat] list names currently in scope\n");
748 Printf(":info <names> describe named objects\n");
749 Printf(":browse <modules> browse names defined in <modules>\n");
750 #if EXPLAIN_INSTANCE_RESOLUTION
751 Printf(":xplain <context> explain instance resolution for <context>\n");
753 Printf(":find <name> edit module containing definition of name\n");
754 Printf(":!command shell escape\n");
755 Printf(":cd dir change directory\n");
756 Printf(":gc force garbage collection\n");
757 Printf(":version print Hugs version\n");
758 Printf(":dump <name> print STG code for named fn\n");
759 #ifdef CRUDE_PROFILING
760 Printf(":ztats <name> print reduction stats\n");
762 Printf(":quit exit Hugs interpreter\n");
765 static Void local guidance() {
766 Printf("Command not recognised. ");
770 static Void local forHelp() {
771 Printf("Type :? for help\n");
774 /* --------------------------------------------------------------------------
775 * Setting of command line options:
776 * ------------------------------------------------------------------------*/
778 struct options toggle[] = { /* List of command line toggles */
779 {'s', 1, "Print no. reductions/cells after eval", &showStats},
780 {'t', 1, "Print type after evaluation", &addType},
781 {'g', 1, "Print no. cells recovered after gc", &gcMessages},
782 {'l', 1, "Literate modules as default", &literateScripts},
783 {'e', 1, "Warn about errors in literate modules", &literateErrors},
784 {'.', 1, "Print dots to show progress", &useDots},
785 {'q', 1, "Print nothing to show progress", &quiet},
786 {'w', 1, "Always show which modules are loaded", &listScripts},
787 {'k', 1, "Show kind errors in full", &kindExpert},
788 {'o', 0, "Allow overlapping instances", &allowOverlap},
789 {'S', 1, "Debug: show generated SC code", &debugSC},
790 #if EXPLAIN_INSTANCE_RESOLUTION
791 {'x', 1, "Explain instance resolution", &showInstRes},
794 {'m', 0, "Use multi instance resolution", &multiInstRes},
799 static Void local set() { /* change command line options from*/
800 String s; /* Hugs command line */
802 if ((s=readFilename())!=0) {
804 if (!processOption(s)) {
805 ERRMSG(0) "Option string must begin with `+' or `-'"
808 } while ((s=readFilename())!=0);
810 writeRegString("Options", optionsToStr());
817 /* --------------------------------------------------------------------------
818 * Change directory command:
819 * ------------------------------------------------------------------------*/
821 static Void local changeDir() { /* change directory */
822 String s = readFilename();
824 ERRMSG(0) "Unable to change to directory \"%s\"", s
829 /* --------------------------------------------------------------------------
830 * Loading project and script files:
831 * ------------------------------------------------------------------------*/
833 static Void local loadProject(s) /* Load project file */
837 projInput(currProject);
838 scriptFile = currProject;
839 forgetScriptsFrom(N_PRELUDE_SCRIPTS);
840 while ((s=readFilename())!=0)
843 ERRMSG(0) "Empty project file"
847 projectLoaded = TRUE;
850 static Void local clearProject() { /* clear name for current project */
854 projectLoaded = FALSE;
856 setLastEdit((String)0,0);
862 static Void local makeStackEntry ( ScriptInfo* ent, String iname )
865 Bool sAvail, iAvail, oAvail;
866 Time sTime, iTime, oTime;
867 Long sSize, iSize, oSize;
870 ok = findFilesForModule (
874 &sAvail, &sTime, &sSize,
875 &iAvail, &iTime, &iSize,
876 &oAvail, &oTime, &oSize
880 "Can't find source or object+interface for module \"%s\"",
881 /* "Can't find source for module \"%s\"", */
885 /* findFilesForModule should enforce this */
886 if (!(sAvail || (oAvail && iAvail)))
888 /* Load objects in preference to sources if both are available */
889 /* 11 Oct 99: disable object loading in the interim.
890 Will probably only reinstate when HEP becomes available.
894 ? (oAvail && iAvail && timeEarlier(sTime,oTime))
900 /* ToDo: namesUpto overflow */
901 ent->modName = strCopy(iname);
904 ent->fromSource = !fromObj;
906 ent->postponed = FALSE;
907 ent->lastChange = sTime; /* ToDo: is this right? */
908 ent->size = fromObj ? iSize : sSize;
909 ent->oSize = fromObj ? oSize : 0;
910 ent->objLoaded = FALSE;
915 static Void nukeEnding( String s )
918 if (l > 4 && strncmp(s+l-4,".u_o" ,4)==0) s[l-4] = 0; else
919 if (l > 5 && strncmp(s+l-5,".u_hi",5)==0) s[l-5] = 0; else
920 if (l > 3 && strncmp(s+l-3,".hs" ,3)==0) s[l-3] = 0; else
921 if (l > 4 && strncmp(s+l-4,".lhs" ,4)==0) s[l-4] = 0; else
922 if (l > 4 && strncmp(s+l-4,".dll" ,4)==0) s[l-4] = 0; else
923 if (l > 4 && strncmp(s+l-4,".DLL" ,4)==0) s[l-4] = 0;
926 static Void local addStackEntry(s) /* Add script to list of scripts */
927 String s; { /* to be read in ... */
932 if (namesUpto>=NUM_SCRIPTS) {
933 ERRMSG(0) "Too many module files (maximum of %d allowed)",
940 for (s2 = s; *s2; s2++)
941 if (*s2 == SLASH && *(s2+1)) s = s2+1;
944 for (i = 0; i < namesUpto; i++)
945 if (strcmp(scriptInfo[i].modName,s)==0)
949 makeStackEntry ( &scriptInfo[namesUpto], strCopy(s) );
955 /* Return TRUE if no imports were needed; FALSE otherwise. */
956 static Bool local addScript(stacknum) /* read single file */
959 static char name[FILENAME_MAX+1];
960 Int len = scriptInfo[stacknum].size;
962 #if HUGS_FOR_WINDOWS /* Set clock cursor while loading */
964 SetCursor(LoadCursor(NULL, IDC_WAIT));
967 // setLastEdit(name,0);
969 strcpy(name, scriptInfo[stacknum].path);
970 strcat(name, scriptInfo[stacknum].modName);
971 if (scriptInfo[stacknum].fromSource)
972 strcat(name, scriptInfo[stacknum].srcExt); else
973 strcat(name, ".u_hi");
977 if (scriptInfo[stacknum].fromSource) {
979 didPrelude = processInterfaces();
981 preludeLoaded = TRUE;
985 lastWasObject = FALSE;
986 Printf("Reading script \"%s\":\n",name);
987 needsImports = FALSE;
988 parseScript(name,len);
989 if (needsImports) return FALSE;
997 char nameObj[FILENAME_MAX+1];
1000 Printf("Reading iface \"%s\":\n", name);
1002 needsImports = FALSE;
1004 // set nameObj for the benefit of openGHCIface
1005 strcpy(nameObj, scriptInfo[stacknum].path);
1006 strcat(nameObj, scriptInfo[stacknum].modName);
1007 strcat(nameObj, DLL_ENDING);
1008 sizeObj = scriptInfo[stacknum].oSize;
1010 iface = readInterface(name,len);
1011 imports = zsnd(iface); iface = zfst(iface);
1013 if (nonNull(imports)) chase(imports);
1015 lastWasObject = TRUE;
1017 iface_info = ztriple(iface, findText(nameObj), mkInt(sizeObj) );
1018 ifaces_outstanding = cons(iface_info,ifaces_outstanding);
1020 if (needsImports) return FALSE;
1029 Bool chase(imps) /* Process list of import requests */
1033 Int origPos = numScripts; /* keep track of original position */
1034 String origName = scriptInfo[origPos].modName;
1035 for (; nonNull(imps); imps=tl(imps)) {
1036 String iname = textToStr(textOf(hd(imps)));
1038 for (; i<namesUpto; i++)
1039 if (strcmp(scriptInfo[i].modName,iname)==0)
1041 //fprintf(stderr, "import name = %s num = %d\n", iname, i );
1044 /* We should have filled in the details of each module
1045 the first time we hear about it.
1047 assert(scriptInfo[i].details);
1050 if (i>=origPos) { /* Neither loaded or queued */
1056 needsImports = TRUE;
1057 if (scriptInfo[origPos].fromSource)
1058 scriptInfo[origPos].postponed = TRUE;
1060 if (i==namesUpto) { /* Name not found (i==namesUpto) */
1061 /* Find out where it lives, whether source or object, etc */
1062 makeStackEntry ( &scriptInfo[i], iname );
1066 if (scriptInfo[i].postponed && scriptInfo[i].fromSource) {
1067 /* Check for recursive dependency */
1069 "Recursive import dependency between \"%s\" and \"%s\"",
1070 scriptInfo[origPos].modName, iname
1073 /* Move stack entry i to somewhere below origPos. If i denotes
1074 * an object, destination is immediately below origPos.
1075 * Otherwise, it's underneath the queue of objects below origPos.
1077 dstPosn = origPos-1;
1078 if (scriptInfo[i].fromSource)
1079 while (!scriptInfo[dstPosn].fromSource && dstPosn > 0)
1083 tmp = scriptInfo[i];
1084 for (; i > dstPosn; i--) scriptInfo[i] = scriptInfo[i-1];
1085 scriptInfo[dstPosn] = tmp;
1086 if (dstPosn < nextNumScripts) nextNumScripts = dstPosn;
1090 return needsImports;
1093 static Void local forgetScriptsFrom(scno)/* remove scripts from system */
1097 for (i=scno; i<namesUpto; ++i)
1099 free(scriptName[i]);
1101 dropScriptsFrom(scno-1);
1103 if (numScripts>namesUpto)
1107 /* --------------------------------------------------------------------------
1108 * Commands for loading and removing script files:
1109 * ------------------------------------------------------------------------*/
1111 static Void local load() { /* read filenames from command line */
1112 String s; /* and add to list of scripts waiting */
1114 while ((s=readFilename())!=0)
1116 readScripts(N_PRELUDE_SCRIPTS);
1119 static Void local project() { /* read list of script names from */
1120 String s; /* project file */
1122 if ((s=readFilename()) || currProject) {
1124 s = strCopy(currProject);
1125 else if (readFilename()) {
1126 ERRMSG(0) "Too many project files"
1133 ERRMSG(0) "No project filename specified"
1137 readScripts(N_PRELUDE_SCRIPTS);
1140 static Void local readScripts(n) /* Reread current list of scripts, */
1141 Int n; { /* loading everything after and */
1142 Time timeStamp; /* including the first script which*/
1143 Long fileSize; /* has been either changed or added*/
1144 static char name[FILENAME_MAX+1];
1147 lastWasObject = FALSE;
1148 ppSmStack("readscripts-begin");
1149 #if HUGS_FOR_WINDOWS
1150 SetCursor(LoadCursor(NULL, IDC_WAIT));
1154 for (; n<numScripts; n++) { /* Scan previously loaded scripts */
1155 ppSmStack("readscripts-loop1");
1156 getFileInfo(scriptName[n], &timeStamp, &fileSize);
1157 if (timeChanged(timeStamp,lastChange[n])) {
1158 dropScriptsFrom(n-1);
1163 for (; n<NUM_SCRIPTS; n++) /* No scripts have been postponed */
1164 postponed[n] = FALSE; /* at this stage */
1167 while (numScripts<namesUpto) { /* Process any remaining scripts */
1168 ppSmStack("readscripts-loop2");
1169 getFileInfo(scriptName[numScripts], &timeStamp, &fileSize);
1170 timeSet(lastChange[numScripts],timeStamp);
1171 if (numScripts>0) /* no new script for prelude */
1172 startNewScript(scriptName[numScripts]);
1173 if (addScript(scriptName[numScripts],fileSize))
1176 dropScriptsFrom(numScripts-1);
1182 for (; n<numScripts; n++) {
1183 ppSmStack("readscripts-loop2");
1184 strcpy(name, scriptInfo[n].path);
1185 strcat(name, scriptInfo[n].modName);
1186 if (scriptInfo[n].fromSource)
1187 strcat(name, scriptInfo[n].srcExt); else
1188 strcat(name, ".u_hi"); //ToDo: should be .o
1189 getFileInfo(name,&timeStamp, &fileSize);
1190 if (timeChanged(timeStamp,scriptInfo[n].lastChange)) {
1191 dropScriptsFrom(n-1);
1196 for (; n<NUM_SCRIPTS; n++)
1197 scriptInfo[n].postponed = FALSE;
1201 while (numScripts < namesUpto) {
1202 ppSmStack ( "readscripts-loop2" );
1204 if (scriptInfo[numScripts].fromSource) {
1207 startNewScript(scriptInfo[numScripts].modName);
1208 nextNumScripts = NUM_SCRIPTS; //bogus initialisation
1209 if (addScript(numScripts)) {
1211 assert(nextNumScripts==NUM_SCRIPTS);
1214 dropScriptsFrom(numScripts-1);
1218 if (scriptInfo[numScripts].objLoaded) {
1221 scriptInfo[numScripts].objLoaded = TRUE;
1224 startNewScript(scriptInfo[numScripts].modName);
1226 nextNumScripts = NUM_SCRIPTS;
1227 if (addScript(numScripts)) {
1229 assert(nextNumScripts==NUM_SCRIPTS);
1231 //while (!scriptInfo[numScripts].fromSource && numScripts > 0)
1233 //if (scriptInfo[numScripts].fromSource)
1235 numScripts = nextNumScripts;
1236 assert(nextNumScripts<NUM_SCRIPTS);
1240 if (numScripts==namesUpto) ppSmStack( "readscripts-final") ;
1243 didPrelude = processInterfaces();
1245 preludeLoaded = TRUE;
1246 everybody(POSTPREL);
1250 { Int m = namesUpto-1;
1251 Text mtext = findText(scriptInfo[m].modName);
1253 /* Hack to avoid starting up in PrelHugs */
1254 if (mtext == findText("PrelHugs")) mtext = findText("Prelude");
1257 /* Commented out till we understand what
1258 * this is trying to do.
1259 * Problem, you cant find a module till later.
1262 setCurrModule(findModule(mtext));
1272 setLastEdit((String)0, 0);
1273 ppSmStack("readscripts-end ");
1276 static Void local whatScripts() { /* list scripts in current session */
1278 Printf("\nHugs session for:");
1280 Printf(" (project: %s)",currProject);
1281 for (i=0; i<numScripts; ++i)
1282 Printf("\n%s%s",scriptInfo[i].path, scriptInfo[i].modName);
1286 /* --------------------------------------------------------------------------
1287 * Access to external editor:
1288 * ------------------------------------------------------------------------*/
1290 static Void local editor() { /* interpreter-editor interface */
1291 String newFile = readFilename();
1293 setLastEdit(newFile,0);
1294 if (readFilename()) {
1295 ERRMSG(0) "Multiple filenames not permitted"
1302 static Void local find() { /* edit file containing definition */
1304 This just plain wont work no more.
1306 String nm = readFilename(); /* of specified name */
1308 ERRMSG(0) "No name specified"
1311 else if (readFilename()) {
1312 ERRMSG(0) "Multiple names not permitted"
1318 setCurrModule(findEvalModule());
1320 if (nonNull(c=findTycon(t=findText(nm)))) {
1321 if (startEdit(tycon(c).line,scriptName[scriptThisTycon(c)])) {
1322 readScripts(N_PRELUDE_SCRIPTS);
1324 } else if (nonNull(c=findName(t))) {
1325 if (startEdit(name(c).line,scriptName[scriptThisName(c)])) {
1326 readScripts(N_PRELUDE_SCRIPTS);
1329 ERRMSG(0) "No current definition for name \"%s\"", nm
1336 static Void local runEditor() { /* run editor on script lastEdit */
1337 if (startEdit(lastEdLine,lastEdit)) /* at line lastEdLine */
1338 readScripts(N_PRELUDE_SCRIPTS);
1341 static Void local setLastEdit(fname,line)/* keep name of last file to edit */
1346 lastEdit = strCopy(fname);
1348 #if HUGS_FOR_WINDOWS
1349 DrawStatusLine(hWndMain); /* Redo status line */
1353 /* --------------------------------------------------------------------------
1354 * Read and evaluate an expression:
1355 * ------------------------------------------------------------------------*/
1357 static Void local setModule(){/*set module in which to evaluate expressions*/
1358 String s = readFilename();
1359 if (!s) s = ""; /* :m clears the current module selection */
1360 evalModule = findText(s);
1361 setLastEdit(fileOfModule(findEvalModule()),0);
1364 static Module local findEvalModule() { /*Module in which to eval expressions*/
1365 Module m = findModule(evalModule);
1371 static Void local evaluator() { /* evaluate expr and print value */
1375 setCurrModule(findEvalModule());
1377 startNewScript(0); /* Enables recovery of storage */
1378 /* allocated during evaluation */
1381 defaultDefns = combined ? stdDefaults : evalDefaults;
1382 type = typeCheckExp(TRUE);
1384 if (isPolyType(type)) {
1385 ks = polySigOf(type);
1386 bd = monotypeOf(type);
1391 if (whatIs(bd)==QUAL) {
1392 ERRMSG(0) "Unresolved overloading" ETHEN
1393 ERRTEXT "\n*** Type : " ETHEN ERRTYPE(type);
1394 ERRTEXT "\n*** Expression : " ETHEN ERREXPR(inputExpr);
1404 if (isProgType(ks,bd)) {
1405 inputExpr = ap(nameRunIO_toplevel,inputExpr);
1409 Cell d = provePred(ks,NIL,ap(classShow,bd));
1411 ERRMSG(0) "Cannot find \"show\" function for:" ETHEN
1412 ERRTEXT "\n*** expression : " ETHEN ERREXPR(inputExpr);
1413 ERRTEXT "\n*** of type : " ETHEN ERRTYPE(type);
1417 inputExpr = ap2(nameShow, d,inputExpr);
1418 inputExpr = ap (namePutStr, inputExpr);
1419 inputExpr = ap (nameRunIO_toplevel, inputExpr);
1421 evalExp(); printf("\n");
1424 printType(stdout,type);
1431 printf ( "result type is " );
1432 printType ( stdout, type );
1441 static Void local stopAnyPrinting() { /* terminate printing of expression,*/
1442 if (printing) { /* after successful termination or */
1443 printing = FALSE; /* runtime error (e.g. interrupt) */
1446 #define plural(v) v, (v==1?"":"s")
1447 Printf("%lu cell%s",plural(numCells));
1449 Printf(", %u garbage collection%s",plural(numGcs));
1458 /* --------------------------------------------------------------------------
1459 * Print type of input expression:
1460 * ------------------------------------------------------------------------*/
1462 static Void local showtype() { /* print type of expression (if any)*/
1465 setCurrModule(findEvalModule());
1466 startNewScript(0); /* Enables recovery of storage */
1467 /* allocated during evaluation */
1470 defaultDefns = evalDefaults;
1471 type = typeCheckExp(FALSE);
1472 printExp(stdout,inputExpr);
1474 printType(stdout,type);
1479 static Void local browseit(mod,t,all)
1486 Printf("module %s where\n",textToStr(module(mod).text));
1487 for (cs = module(mod).names; nonNull(cs); cs=tl(cs)) {
1489 /* only look at things defined in this module,
1490 unless `all' flag is set */
1491 if (all || name(nm).mod == mod) {
1492 /* unwanted artifacts, like lambda lifted values,
1493 are in the list of names, but have no types */
1494 if (nonNull(name(nm).type)) {
1495 printExp(stdout,nm);
1497 printType(stdout,name(nm).type);
1499 Printf(" -- data constructor");
1500 } else if (isMfun(nm)) {
1501 Printf(" -- class member");
1502 } else if (isSfun(nm)) {
1503 Printf(" -- selector function");
1511 Printf("Unknown module %s\n",t);
1516 static Void local browse() { /* browse modules */
1517 Int count = 0; /* or give menu of commands */
1521 setCurrModule(findEvalModule());
1522 startNewScript(0); /* for recovery of storage */
1523 for (; (s=readFilename())!=0; count++)
1524 if (strcmp(s,"all") == 0) {
1528 browseit(findModule(findText(s)),s,all);
1530 browseit(findEvalModule(),NULL,all);
1534 #if EXPLAIN_INSTANCE_RESOLUTION
1535 static Void local xplain() { /* print type of expression (if any)*/
1537 Bool sir = showInstRes;
1539 setCurrModule(findEvalModule());
1540 startNewScript(0); /* Enables recovery of storage */
1541 /* allocated during evaluation */
1545 d = provePred(NIL,NIL,hd(inputContext));
1547 fprintf(stdout, "not Sat\n");
1549 fprintf(stdout, "Sat\n");
1555 /* --------------------------------------------------------------------------
1556 * Enhanced help system: print current list of scripts or give information
1558 * ------------------------------------------------------------------------*/
1560 static String local objToStr(m,c)
1563 #if 1 || DISPLAY_QUANTIFIERS
1564 static char newVar[60];
1565 switch (whatIs(c)) {
1566 case NAME : if (m == name(c).mod) {
1567 sprintf(newVar,"%s", textToStr(name(c).text));
1569 sprintf(newVar,"%s.%s",
1570 textToStr(module(name(c).mod).text),
1571 textToStr(name(c).text));
1575 case TYCON : if (m == tycon(c).mod) {
1576 sprintf(newVar,"%s", textToStr(tycon(c).text));
1578 sprintf(newVar,"%s.%s",
1579 textToStr(module(tycon(c).mod).text),
1580 textToStr(tycon(c).text));
1584 case CLASS : if (m == cclass(c).mod) {
1585 sprintf(newVar,"%s", textToStr(cclass(c).text));
1587 sprintf(newVar,"%s.%s",
1588 textToStr(module(cclass(c).mod).text),
1589 textToStr(cclass(c).text));
1593 default : internal("objToStr");
1597 static char newVar[33];
1598 switch (whatIs(c)) {
1599 case NAME : sprintf(newVar,"%s", textToStr(name(c).text));
1602 case TYCON : sprintf(newVar,"%s", textToStr(tycon(c).text));
1605 case CLASS : sprintf(newVar,"%s", textToStr(cclass(c).text));
1608 default : internal("objToStr");
1616 static Void dumpStg ( void )
1620 setCurrModule(findEvalModule());
1624 /* request to locate a symbol by name */
1625 if (s && (*s == '?')) {
1626 Text t = findText(s+1);
1627 locateSymbolByName(t);
1631 /* request to dump a bit of the heap */
1632 if (s && (*s == '-' || isdigit(*s))) {
1639 /* request to dump a symbol table entry */
1641 || !(*s == 't' || *s == 'n' || *s == 'c' || *s == 'i')
1642 || !isdigit(s[1])) {
1643 fprintf(stderr, ":d -- bad request `%s'\n", s );
1648 case 't': dumpTycon(i); break;
1649 case 'n': dumpName(i); break;
1650 case 'c': dumpClass(i); break;
1651 case 'i': dumpInst(i); break;
1652 default: fprintf(stderr, ":d -- `%c' not implemented\n", *s );
1658 static Void local dumpStg( void ) { /* print STG stuff */
1663 Cell v; /* really StgVar */
1664 setCurrModule(findEvalModule());
1666 for (; (s=readFilename())!=0;) {
1669 /* find the name while ignoring module scopes */
1670 for (i=NAMEMIN; i<nameHw; i++)
1671 if (name(i).text == t) n = i;
1673 /* perhaps it's an "idNNNNNN" thing? */
1676 s[0]=='i' && s[1]=='d' && isdigit(s[2])) {
1679 while (isdigit(s[i])) {
1680 v = v * 10 + (s[i]-'0');
1684 n = nameFromStgVar(v);
1687 if (isNull(n) && whatIs(v)==STGVAR) {
1688 Printf ( "\n{- `%s' has no nametable entry -}\n", s );
1689 printStg(stderr, v );
1692 Printf ( "Unknown reference `%s'\n", s );
1695 Printf ( "Not a Name: `%s'\n", s );
1697 if (isNull(name(n).stgVar)) {
1698 Printf ( "Doesn't have a STG tree: %s\n", s );
1700 Printf ( "\n{- stgVar of `%s' is id%d -}\n", s, -name(n).stgVar);
1701 printStg(stderr, name(n).stgVar);
1707 static Void local info() { /* describe objects */
1708 Int count = 0; /* or give menu of commands */
1711 setCurrModule(findEvalModule());
1712 startNewScript(0); /* for recovery of storage */
1713 for (; (s=readFilename())!=0; count++) {
1714 describe(findText(s));
1722 static Void local describe(t) /* describe an object */
1724 Tycon tc = findTycon(t);
1725 Class cl = findClass(t);
1726 Name nm = findName(t);
1728 if (nonNull(tc)) { /* as a type constructor */
1732 for (i=0; i<tycon(tc).arity; ++i) {
1733 t = ap(t,mkOffset(i));
1735 Printf("-- type constructor");
1737 Printf(" with kind ");
1738 printKind(stdout,tycon(tc).kind);
1741 switch (tycon(tc).what) {
1742 case SYNONYM : Printf("type ");
1743 printType(stdout,t);
1745 printType(stdout,tycon(tc).defn);
1749 case DATATYPE : { List cs = tycon(tc).defn;
1750 if (tycon(tc).what==DATATYPE) {
1755 printType(stdout,t);
1757 mapProc(printSyntax,cs);
1759 Printf("\n-- constructors:");
1761 for (; hasCfun(cs); cs=tl(cs)) {
1763 printExp(stdout,hd(cs));
1765 printType(stdout,name(hd(cs)).type);
1768 Printf("\n-- selectors:");
1770 for (; nonNull(cs); cs=tl(cs)) {
1772 printExp(stdout,hd(cs));
1774 printType(stdout,name(hd(cs)).type);
1779 case RESTRICTSYN : Printf("type ");
1780 printType(stdout,t);
1781 Printf(" = <restricted>");
1785 if (nonNull(in=findFirstInst(tc))) {
1786 Printf("\n-- instances:\n");
1789 in = findNextInst(tc,in);
1790 } while (nonNull(in));
1795 if (nonNull(cl)) { /* as a class */
1796 List ins = cclass(cl).instances;
1797 Kinds ks = cclass(cl).kinds;
1798 if (nonNull(ks) && isNull(tl(ks)) && hd(ks)==STAR) {
1799 Printf("-- type class");
1801 Printf("-- constructor class");
1803 Printf(" with arity ");
1804 printKinds(stdout,ks);
1808 mapProc(printSyntax,cclass(cl).members);
1810 if (nonNull(cclass(cl).supers)) {
1811 printContext(stdout,cclass(cl).supers);
1814 printPred(stdout,cclass(cl).head);
1816 if (nonNull(cclass(cl).fds)) {
1817 List fds = cclass(cl).fds;
1819 for (; nonNull(fds); fds=tl(fds)) {
1821 printFD(stdout,hd(fds));
1826 if (nonNull(cclass(cl).members)) {
1827 List ms = cclass(cl).members;
1830 Type t = name(hd(ms)).type;
1831 if (isPolyType(t)) {
1835 printExp(stdout,hd(ms));
1837 if (isNull(tl(fst(snd(t))))) {
1840 t = ap(QUAL,pair(tl(fst(snd(t))),snd(snd(t))));
1842 printType(stdout,t);
1844 } while (nonNull(ms));
1848 Printf("\n-- instances:\n");
1852 } while (nonNull(ins));
1857 if (nonNull(nm)) { /* as a function/name */
1859 printExp(stdout,nm);
1861 if (nonNull(name(nm).type)) {
1862 printType(stdout,name(nm).type);
1864 Printf("<unknown type>");
1867 Printf(" -- data constructor");
1868 } else if (isMfun(nm)) {
1869 Printf(" -- class member");
1870 } else if (isSfun(nm)) {
1871 Printf(" -- selector function");
1877 if (isNull(tc) && isNull(cl) && isNull(nm)) {
1878 Printf("Unknown reference `%s'\n",textToStr(t));
1882 static Void local printSyntax(nm)
1884 Syntax sy = syntaxOf(nm);
1885 Text t = name(nm).text;
1886 String s = textToStr(t);
1887 if (sy != defaultSyntax(t)) {
1889 switch (assocOf(sy)) {
1890 case LEFT_ASS : Putchar('l'); break;
1891 case RIGHT_ASS : Putchar('r'); break;
1892 case NON_ASS : break;
1894 Printf(" %i ",precOf(sy));
1895 if (isascii((int)(*s)) && isalpha((int)(*s))) {
1904 static Void local showInst(in) /* Display instance decl header */
1906 Printf("instance ");
1907 if (nonNull(inst(in).specifics)) {
1908 printContext(stdout,inst(in).specifics);
1911 printPred(stdout,inst(in).head);
1915 /* --------------------------------------------------------------------------
1916 * List all names currently in scope:
1917 * ------------------------------------------------------------------------*/
1919 static Void local listNames() { /* list names matching optional pat*/
1920 String pat = readFilename();
1922 Int width = getTerminalWidth() - 1;
1925 Module mod = findEvalModule();
1927 if (pat) { /* First gather names to list */
1929 names = addNamesMatching(pat,names);
1930 } while ((pat=readFilename())!=0);
1932 names = addNamesMatching((String)0,names);
1934 if (isNull(names)) { /* Then print them out */
1935 ERRMSG(0) "No names selected"
1938 for (termPos=0; nonNull(names); names=tl(names)) {
1939 String s = objToStr(mod,hd(names));
1941 if (termPos+1+l>width) {
1944 } else if (termPos>0) {
1952 Printf("\n(%d names listed)\n", count);
1955 /* --------------------------------------------------------------------------
1956 * print a prompt and read a line of input:
1957 * ------------------------------------------------------------------------*/
1959 static Void local promptForInput(moduleName)
1960 String moduleName; {
1961 char promptBuffer[1000];
1963 /* This is portable but could overflow buffer */
1964 sprintf(promptBuffer,prompt,moduleName);
1966 /* Works on ANSI C - but pre-ANSI compilers return a pointer to
1967 * promptBuffer instead.
1969 if (sprintf(promptBuffer,prompt,moduleName) >= 1000) {
1970 /* Reset prompt to a safe default to avoid an infinite loop */
1972 prompt = strCopy("? ");
1973 internal("Combined prompt and evaluation module name too long");
1977 stringInput("main\0"); else
1978 consoleInput(promptBuffer);
1981 /* --------------------------------------------------------------------------
1982 * main read-eval-print loop, with error trapping:
1983 * ------------------------------------------------------------------------*/
1985 static jmp_buf catch_error; /* jump buffer for error trapping */
1987 static Void local interpreter(argc,argv)/* main interpreter loop */
1990 Int errorNumber = setjmp(catch_error);
1992 if (errorNumber && autoMain) {
1993 fprintf(stderr, "hugs +Q: compilation failed -- can't run `main'\n" );
1997 breakOn(TRUE); /* enable break trapping */
1998 if (numScripts==0) { /* only succeeds on first time, */
1999 if (errorNumber) /* before prelude has been loaded */
2000 fatal("Unable to load prelude");
2001 initialize(argc,argv);
2005 /* initialize calls startupHaskell, which trashes our signal handlers */
2010 everybody(RESET); /* reset to sensible initial state */
2011 dropScriptsFrom(numScripts-1); /* remove partially loaded scripts */
2012 /* not counting prelude as a script*/
2014 promptForInput(textToStr(module(findEvalModule()).text));
2016 cmd = readCommand(cmds, (Char)':', (Char)'!');
2021 case EDIT : editor();
2025 case LOAD : clearProject();
2026 forgetScriptsFrom(N_PRELUDE_SCRIPTS);
2029 case ALSO : clearProject();
2030 forgetScriptsFrom(numScripts);
2033 case RELOAD : readScripts(N_PRELUDE_SCRIPTS);
2035 case PROJECT: project();
2040 case EVAL : evaluator();
2042 case TYPEOF : showtype();
2044 case BROWSE : browse();
2046 #if EXPLAIN_INSTANCE_RESOLUTION
2047 case XPLAIN : xplain();
2050 case NAMES : listNames();
2054 case BADCMD : guidance();
2059 #ifdef CRUDE_PROFILING
2063 case SYSTEM : if (shellEsc(readLine()))
2064 Printf("Warning: Shell escape terminated abnormally\n");
2066 case CHGDIR : changeDir();
2070 case PNTVER: Printf("-- Hugs Version %s\n",
2073 case DUMP : dumpStg();
2076 case COLLECT: consGC = FALSE;
2079 Printf("Garbage collection recovered %d cells\n",
2086 Printf("Elapsed time (ms): %ld (user), %ld (system)\n",
2087 millisecs(userElapsed), millisecs(systElapsed));
2089 if (autoMain) break;
2094 /* --------------------------------------------------------------------------
2095 * Display progress towards goal:
2096 * ------------------------------------------------------------------------*/
2098 static Target currTarget;
2099 static Bool aiming = FALSE;
2102 static Int charCount;
2104 Void setGoal(what, t) /* Set goal for what to be t */
2109 #if EXPLAIN_INSTANCE_RESOLUTION
2113 currTarget = (t?t:1);
2116 currPos = strlen(what);
2117 maxPos = getTerminalWidth() - 1;
2121 for (charCount=0; *what; charCount++)
2126 Void soFar(t) /* Indicate progress towards goal */
2127 Target t; { /* has now reached t */
2130 #if EXPLAIN_INSTANCE_RESOLUTION
2135 Int newPos = (Int)((maxPos * ((long)t))/currTarget);
2140 if (newPos>currPos) {
2143 while (newPos>++currPos);
2150 Void done() { /* Goal has now been achieved */
2153 #if EXPLAIN_INSTANCE_RESOLUTION
2158 while (maxPos>currPos++)
2163 for (; charCount>0; charCount--) {
2172 static Void local failed() { /* Goal cannot be reached due to */
2173 if (aiming) { /* errors */
2180 /* --------------------------------------------------------------------------
2182 * ------------------------------------------------------------------------*/
2184 Void errHead(l) /* print start of error message */
2186 failed(); /* failed to reach target ... */
2188 FPrintf(errorStream,"ERROR");
2191 FPrintf(errorStream," \"%s\"", scriptFile);
2192 setLastEdit(scriptFile,l);
2193 if (l) FPrintf(errorStream," (line %d)",l);
2196 FPrintf(errorStream,": ");
2197 FFlush(errorStream);
2200 Void errFail() { /* terminate error message and */
2201 Putc('\n',errorStream); /* produce exception to return to */
2202 FFlush(errorStream); /* main command loop */
2203 longjmp(catch_error,1);
2206 Void errAbort() { /* altern. form of error handling */
2207 failed(); /* used when suitable error message*/
2208 stopAnyPrinting(); /* has already been printed */
2212 Void internal(msg) /* handle internal error */
2214 #if HUGS_FOR_WINDOWS
2216 wsprintf(buf,"INTERNAL ERROR: %s",msg);
2217 MessageBox(hWndMain, buf, appName, MB_ICONHAND | MB_OK);
2221 Printf("INTERNAL ERROR: %s\n",msg);
2223 longjmp(catch_error,1);
2226 Void fatal(msg) /* handle fatal error */
2228 #if HUGS_FOR_WINDOWS
2230 wsprintf(buf,"FATAL ERROR: %s",msg);
2231 MessageBox(hWndMain, buf, appName, MB_ICONHAND | MB_OK);
2234 Printf("\nFATAL ERROR: %s\n",msg);
2239 sigHandler(breakHandler) { /* respond to break interrupt */
2240 #if HUGS_FOR_WINDOWS
2241 MessageBox(GetFocus(), "Interrupted!", appName, MB_ICONSTOP | MB_OK);
2244 Printf("{Interrupted!}\n");
2246 breakOn(TRUE); /* reinstall signal handler - redundant on BSD systems */
2247 /* but essential on POSIX (and other?) systems */
2253 longjmp(catch_error,1);
2254 sigResume;/*NOTREACHED*/
2257 /* --------------------------------------------------------------------------
2258 * Read value from environment variable or registry:
2259 * ------------------------------------------------------------------------*/
2261 String fromEnv(var,def) /* return value of: */
2262 String var; /* environment variable named by var */
2263 String def; { /* or: default value given by def */
2264 String s = getenv(var);
2265 return (s ? s : def);
2268 /* --------------------------------------------------------------------------
2269 * String manipulation routines:
2270 * ------------------------------------------------------------------------*/
2272 static String local strCopy(s) /* make malloced copy of a string */
2276 if ((t=(char *)malloc(strlen(s)+1))==0) {
2277 ERRMSG(0) "String storage space exhausted"
2280 for (r=t; (*r++ = *s++)!=0; ) {
2287 /* --------------------------------------------------------------------------
2289 * We can redirect compiler output (prompts, error messages, etc) by
2290 * tweaking these functions.
2291 * ------------------------------------------------------------------------*/
2293 #if REDIRECT_OUTPUT && !HUGS_FOR_WINDOWS
2295 #ifdef HAVE_STDARG_H
2298 #include <varargs.h>
2301 /* ----------------------------------------------------------------------- */
2303 #define BufferSize 10000 /* size of redirected output buffer */
2305 typedef struct _HugsStream {
2306 char buffer[BufferSize]; /* buffer for redirected output */
2307 Int next; /* next space in buffer */
2310 static Void local vBufferedPrintf Args((HugsStream*, const char*, va_list));
2311 static Void local bufferedPutchar Args((HugsStream*, Char));
2312 static String local bufferClear Args((HugsStream *stream));
2314 static Void local vBufferedPrintf(stream, fmt, ap)
2318 Int spaceLeft = BufferSize - stream->next;
2319 char* p = &stream->buffer[stream->next];
2320 Int charsAdded = vsnprintf(p, spaceLeft, fmt, ap);
2321 if (0 <= charsAdded && charsAdded < spaceLeft)
2322 stream->next += charsAdded;
2323 #if 1 /* we can either buffer the first n chars or buffer the last n chars */
2329 static Void local bufferedPutchar(stream, c)
2332 if (BufferSize - stream->next >= 2) {
2333 stream->buffer[stream->next++] = c;
2334 stream->buffer[stream->next] = '\0';
2338 static String local bufferClear(stream)
2339 HugsStream *stream; {
2340 if (stream->next == 0) {
2344 return stream->buffer;
2348 /* ----------------------------------------------------------------------- */
2350 static HugsStream outputStreamH;
2352 * We rely on standard C semantics to initialise outputStreamH.next to 0.
2355 Void hugsEnableOutput(f)
2360 String hugsClearOutputBuffer() {
2361 return bufferClear(&outputStreamH);
2364 #ifdef HAVE_STDARG_H
2365 Void hugsPrintf(const char *fmt, ...) {
2366 va_list ap; /* pointer into argument list */
2367 va_start(ap, fmt); /* make ap point to first arg after fmt */
2368 if (!disableOutput) {
2371 vBufferedPrintf(&outputStreamH, fmt, ap);
2373 va_end(ap); /* clean up */
2376 Void hugsPrintf(fmt, va_alist)
2379 va_list ap; /* pointer into argument list */
2380 va_start(ap); /* make ap point to first arg after fmt */
2381 if (!disableOutput) {
2384 vBufferedPrintf(&outputStreamH, fmt, ap);
2386 va_end(ap); /* clean up */
2392 if (!disableOutput) {
2395 bufferedPutchar(&outputStreamH, c);
2399 Void hugsFlushStdout() {
2400 if (!disableOutput) {
2407 if (!disableOutput) {
2412 #ifdef HAVE_STDARG_H
2413 Void hugsFPrintf(FILE *fp, const char* fmt, ...) {
2416 if (!disableOutput) {
2417 vfprintf(fp, fmt, ap);
2419 vBufferedPrintf(&outputStreamH, fmt, ap);
2424 Void hugsFPrintf(FILE *fp, const char* fmt, va_list)
2430 if (!disableOutput) {
2431 vfprintf(fp, fmt, ap);
2433 vBufferedPrintf(&outputStreamH, fmt, ap);
2439 Void hugsPutc(c, fp)
2442 if (!disableOutput) {
2445 bufferedPutchar(&outputStreamH, c);
2449 #endif /* REDIRECT_OUTPUT && !HUGS_FOR_WINDOWS */
2450 /* --------------------------------------------------------------------------
2451 * Send message to each component of system:
2452 * ------------------------------------------------------------------------*/
2454 Void everybody(what) /* send command `what' to each component of*/
2455 Int what; { /* system to respond as appropriate ... */
2457 fprintf ( stderr, "EVERYBODY %d\n", what );
2459 machdep(what); /* The order of calling each component is */
2460 storage(what); /* important for the PREPREL command */
2463 translateControl(what);
2465 staticAnalysis(what);
2466 deriveControl(what);
2472 /* --------------------------------------------------------------------------
2473 * Hugs for Windows code (WinMain and related functions)
2474 * ------------------------------------------------------------------------*/
2476 #if HUGS_FOR_WINDOWS
2477 #include "winhugs.c"