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/02/08 15:32:29 $
14 * ------------------------------------------------------------------------*/
32 #include "Assembler.h" /* DEBUG_LoadSymbols */
34 Bool haskell98 = TRUE; /* TRUE => Haskell 98 compatibility*/
36 #if EXPLAIN_INSTANCE_RESOLUTION
37 Bool showInstRes = FALSE;
40 Bool multiInstRes = FALSE;
43 #define N_PRELUDE_SCRIPTS (combined ? 30 : 1)
45 /* --------------------------------------------------------------------------
46 * Local function prototypes:
47 * ------------------------------------------------------------------------*/
49 static Void local initialize Args((Int,String []));
50 static Void local promptForInput Args((String));
51 static Void local interpreter Args((Int,String []));
52 static Void local menu Args((Void));
53 static Void local guidance Args((Void));
54 static Void local forHelp Args((Void));
55 static Void local set Args((Void));
56 static Void local changeDir Args((Void));
57 static Void local load Args((Void));
58 static Void local project Args((Void));
59 static Void local readScripts Args((Int));
60 static Void local whatScripts Args((Void));
61 static Void local editor Args((Void));
62 static Void local find Args((Void));
63 static Bool local startEdit Args((Int,String));
64 static Void local runEditor Args((Void));
65 static Void local setModule Args((Void));
66 static Module local findEvalModule Args((Void));
67 static Void local evaluator Args((Void));
68 static Void local stopAnyPrinting Args((Void));
69 static Void local showtype Args((Void));
70 static String local objToStr Args((Module, Cell));
71 static Void local info Args((Void));
72 static Void local printSyntax Args((Name));
73 static Void local showInst Args((Inst));
74 static Void local describe Args((Text));
75 static Void local listNames Args((Void));
77 static Void local toggleSet Args((Char,Bool));
78 static Void local togglesIn Args((Bool));
79 static Void local optionInfo Args((Void));
80 #if USE_REGISTRY || HUGS_FOR_WINDOWS
81 static String local optionsToStr Args((Void));
83 static Void local readOptions Args((String));
84 static Bool local processOption Args((String));
85 static Void local setHeapSize Args((String));
86 static Int local argToInt Args((String));
88 static Void local loadProject Args((String));
89 static Void local clearProject Args((Void));
90 static Bool local addScript Args((Int));
91 static Void local forgetScriptsFrom Args((Script));
92 static Void local setLastEdit Args((String,Int));
93 static Void local failed Args((Void));
94 static String local strCopy Args((String));
95 static Void local browseit Args((Module,String,Bool));
96 static Void local browse Args((Void));
98 /* --------------------------------------------------------------------------
99 * Machine dependent code for Hugs interpreter:
100 * ------------------------------------------------------------------------*/
102 Bool combined = TRUE;
109 /* --------------------------------------------------------------------------
111 * ------------------------------------------------------------------------*/
113 static Bool printing = FALSE; /* TRUE => currently printing value*/
114 static Bool showStats = FALSE; /* TRUE => print stats after eval */
115 static Bool listScripts = TRUE; /* TRUE => list scripts after loading*/
116 static Bool addType = FALSE; /* TRUE => print type with value */
117 static Bool useDots = RISCOS; /* TRUE => use dots in progress */
118 static Bool quiet = FALSE; /* TRUE => don't show progress */
119 static Bool lastWasObject = FALSE;
120 Bool preludeLoaded = FALSE;
121 Bool debugSC = FALSE;
125 String modName; /* Module name */
126 Bool details; /* FALSE => remaining fields are invalid */
127 String path; /* Path to module */
128 String srcExt; /* ".hs" or ".lhs" if fromSource */
129 Time lastChange; /* Time of last change to script */
130 Bool fromSource; /* FALSE => load object code */
131 Bool postponed; /* Indicates postponed load */
138 static Void local makeStackEntry Args((ScriptInfo*,String));
139 static Void local addStackEntry Args((String));
141 static ScriptInfo scriptInfo[NUM_SCRIPTS];
143 static Int numScripts; /* Number of scripts loaded */
144 static Int nextNumScripts;
145 static Int namesUpto; /* Number of script names set */
146 static Bool needsImports; /* set to TRUE if imports required */
147 String scriptFile; /* Name of current script (if any) */
151 static Text evalModule = 0; /* Name of module we eval exprs in */
152 static String currProject = 0; /* Name of current project file */
153 static Bool projectLoaded = FALSE; /* TRUE => project file loaded */
155 static Bool autoMain = FALSE;
156 static String lastEdit = 0; /* Name of script to edit (if any) */
157 static Int lastEdLine = 0; /* Editor line number (if possible)*/
158 static String prompt = 0; /* Prompt string */
159 static Int hpSize = DEFAULTHEAP; /* Desired heap size */
160 String hugsEdit = 0; /* String for editor command */
161 String hugsPath = 0; /* String for file search path */
163 List ifaces_outstanding = NIL;
166 static Bool disableOutput = FALSE; /* redirect output to buffer? */
169 String bool2str ( Bool b )
171 if (b) return "Yes"; else return "No ";
174 void ppSmStack ( String who )
178 fflush(stdout);fflush(stderr);
180 printf ( "ppSmStack %s: numScripts = %d namesUpto = %d needsImports = %s\n",
181 who, numScripts, namesUpto, bool2str(needsImports) );
182 assert (namesUpto >= numScripts);
183 printf ( " Det FrS Pst ObL Module Ext Size ModTime Path\n" );
184 for (i = namesUpto-1; i >= 0; i--) {
185 printf ( "%c%2d: %3s %3s %3s %3s %16s %-4s %5ld %8lx %s\n",
186 (i==numScripts ? '*' : ' '),
187 i, bool2str(scriptInfo[i].details),
188 bool2str(scriptInfo[i].fromSource),
189 bool2str(scriptInfo[i].postponed),
190 bool2str(scriptInfo[i].objLoaded),
191 scriptInfo[i].modName,
192 scriptInfo[i].fromSource ? scriptInfo[i].srcExt : "",
194 scriptInfo[i].lastChange,
198 fflush(stdout);fflush(stderr);
204 /* --------------------------------------------------------------------------
206 * ------------------------------------------------------------------------*/
208 #ifndef NO_MAIN /* we omit main when building the "Hugs server" */
210 Main main Args((Int, String [])); /* now every func has a prototype */
215 #ifdef HAVE_CONSOLE_H /* Macintosh port */
217 _fcreator = 'R*ch'; /* // 'KAHL'; //'*TEX'; //'ttxt'; */
219 console_options.top = 50;
220 console_options.left = 20;
222 console_options.nrows = 32;
223 console_options.ncols = 80;
225 console_options.pause_atexit = 1;
226 console_options.title = "\pHugs";
228 console_options.procID = 5;
229 argc = ccommand(&argv);
232 CStackBase = &argc; /* Save stack base for use in gc */
234 /* If first arg is +Q or -Q, be entirely silent, and automatically run
235 main after loading scripts. Useful for running the nofib suite. */
236 if (argc > 1 && (strcmp(argv[1],"+Q") == 0 || strcmp(argv[1],"-Q")==0)) {
238 if (strcmp(argv[1],"-Q") == 0) {
243 Printf("__ __ __ __ ____ ___ _________________________________________\n");
244 Printf("|| || || || || || ||__ STGHugs: Based on the Haskell 98 standard\n");
245 Printf("||___|| ||__|| ||__|| __|| Copyright (c) 1994-1999\n");
246 Printf("||---|| ___|| World Wide Web: http://haskell.org/hugs\n");
247 Printf("|| || Report bugs to: hugs-bugs@haskell.org\n");
248 Printf("|| || Version: %s _________________________________________\n\n",HUGS_VERSION);
250 /* Get the absolute path to the directory containing the hugs
251 executable, so that we know where the Prelude and nHandle.so/.dll are.
252 We do this by reading env var STGHUGSDIR. This needs to succeed, so
253 setInstallDir won't return unless it succeeds.
255 setInstallDir ( argv[0] );
258 Printf(" Ported to Macintosh by Hans Aberg, compiled " __DATE__ ".\n\n");
261 interpreter(argc,argv);
262 Printf("[Leaving Hugs]\n");
273 /* --------------------------------------------------------------------------
274 * Initialization, interpret command line args and read prelude:
275 * ------------------------------------------------------------------------*/
277 static Void local initialize(argc,argv)/* Interpreter initialization */
282 char argv_0_orig[1000];
284 setLastEdit((String)0,0);
291 hugsEdit = strCopy(fromEnv("EDITOR","c:\\windows\\notepad.exe"));
295 hugsEdit = strCopy(fromEnv("EDITOR",NULL));
297 hugsPath = strCopy(HUGSPATH);
298 readOptions("-p\"%s> \" -r$$");
300 projectPath = strCopy(readRegChildStrings(HKEY_LOCAL_MACHINE,ProjectRoot,
301 "HUGSPATH", PATHSEP, ""));
302 readOptions(readRegString(HKEY_LOCAL_MACHINE,HugsRoot,"Options",""));
303 readOptions(readRegString(HKEY_CURRENT_USER, HugsRoot,"Options",""));
304 #endif /* USE_REGISTRY */
305 readOptions(fromEnv("STGHUGSFLAGS",""));
307 strncpy(argv_0_orig,argv[0],1000); /* startupHaskell mangles argv[0] */
308 startupHaskell (argc,argv);
309 argc = prog_argc; argv = prog_argv;
311 namesUpto = numScripts = 0;
313 /* Pre-scan flags to see if -c or +c is present. This needs to
314 precede adding the stack entry for Prelude. On the other hand,
315 that stack entry needs to be made before the cmd line args are
316 properly examined. Hence the following pre-scan of them.
318 for (i=1; i < argc; ++i) {
319 if (strcmp(argv[i], "--")==0) break;
320 if (strcmp(argv[i], "-c")==0) combined = FALSE;
321 if (strcmp(argv[i], "+c")==0) combined = TRUE;
324 addStackEntry("Prelude");
325 if (combined) addStackEntry("PrelHugs");
327 for (i=1; i < argc; ++i) { /* process command line arguments */
328 if (strcmp(argv[i], "--")==0) break;
329 if (strcmp(argv[i],"+")==0 && i+1<argc) {
331 ERRMSG(0) "Multiple project filenames on command line"
336 } else if (argv[i] && argv[i][0]/* workaround for /bin/sh silliness*/
337 && !processOption(argv[i])) {
338 addStackEntry(argv[i]);
344 char exe_name[N_INSTALLDIR + 6];
345 strcpy(exe_name, installDir);
346 strcat(exe_name, "hugs");
347 DEBUG_LoadSymbols(exe_name);
353 if (!scriptName[0]) {
354 Printf("Prelude not found on current path: \"%s\"\n",
355 hugsPath ? hugsPath : "");
356 fatal("Unable to load prelude");
361 Printf("Haskell 98 mode: Restart with command line option -98 to enable extensions\n");
363 Printf("Hugs mode: Restart with command line option +98 for Haskell 98 mode\n");
367 Printf("Combined mode: Restart with command line -c for standalone mode\n\n" );
369 Printf("Standalone mode: Restart with command line +c for combined mode\n\n" );
374 evalModule = findText(""); /* evaluate wrt last module by default */
378 "\nUsing project file, ignoring additional filenames\n");
380 loadProject(strCopy(proj));
385 /* --------------------------------------------------------------------------
386 * Command line options:
387 * ------------------------------------------------------------------------*/
389 struct options { /* command line option toggles */
390 char c; /* table defined in main app. */
395 extern struct options toggle[];
397 static Void local toggleSet(c,state) /* Set command line toggle */
401 for (i=0; toggle[i].c; ++i)
402 if (toggle[i].c == c) {
403 *toggle[i].flag = state;
406 ERRMSG(0) "Unknown toggle `%c'", c
410 static Void local togglesIn(state) /* Print current list of toggles in*/
411 Bool state; { /* given state */
414 for (i=0; toggle[i].c; ++i)
415 if (*toggle[i].flag == state && (!haskell98 || toggle[i].h98)) {
417 Putchar((char)(state ? '+' : '-'));
418 Putchar(toggle[i].c);
425 static Void local optionInfo() { /* Print information about command */
426 static String fmts = "%-5s%s\n"; /* line settings */
427 static String fmtc = "%-5c%s\n";
430 Printf("TOGGLES: groups begin with +/- to turn options on/off resp.\n");
431 for (i=0; toggle[i].c; ++i) {
432 if (!haskell98 || toggle[i].h98) {
433 Printf(fmtc,toggle[i].c,toggle[i].description);
437 Printf("\nOTHER OPTIONS: (leading + or - makes no difference)\n");
438 Printf(fmts,"hnum","Set heap size (cannot be changed within Hugs)");
439 Printf(fmts,"pstr","Set prompt string to str");
440 Printf(fmts,"rstr","Set repeat last expression string to str");
441 Printf(fmts,"Pstr","Set search path for modules to str");
442 Printf(fmts,"Estr","Use editor setting given by str");
443 Printf(fmts,"cnum","Set constraint cutoff limit");
444 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
445 Printf(fmts,"Fstr","Set preprocessor filter to str");
448 Printf("\nCurrent settings: ");
451 Printf("-h%d",heapSize);
455 printString(repeatStr);
456 Printf(" -c%d",cutoff);
457 Printf("\nSearch path : -P");
458 printString(hugsPath);
461 if (projectPath!=NULL) {
462 Printf("\nProject Path : %s",projectPath);
465 Printf("\nEditor setting : -E");
466 printString(hugsEdit);
467 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
468 Printf("\nPreprocessor : -F");
469 printString(preprocessor);
471 Printf("\nCompatibility : %s", haskell98 ? "Haskell 98 (+98)"
472 : "Hugs Extensions (-98)");
476 #if USE_REGISTRY || HUGS_FOR_WINDOWS
484 #define PUTInt(optc,i) \
485 sprintf(next,"-%c%d",optc,i); \
488 #define PUTStr(c,s) \
489 next=PUTStr_aux(next,c,s)
491 static String local PUTStr_aux Args((String,Char, String));
493 static String local PUTStr_aux(next,c,s)
499 sprintf(next,"-%c\"",c);
502 PUTS(unlexChar(*t,'"'));
510 static String local optionsToStr() { /* convert options to string */
511 static char buffer[2000];
512 String next = buffer;
515 for (i=0; toggle[i].c; ++i) {
516 PUTC(*toggle[i].flag ? '+' : '-');
520 PUTS(haskell98 ? "+98 " : "-98 ");
521 PUTInt('h',hpSize); PUTC(' ');
523 PUTStr('r',repeatStr);
524 PUTStr('P',hugsPath);
525 PUTStr('E',hugsEdit);
526 PUTInt('c',cutoff); PUTC(' ');
527 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
528 PUTStr('F',preprocessor);
533 #endif /* USE_REGISTRY */
540 static Void local readOptions(options) /* read options from string */
544 stringInput(options);
545 while ((s=readFilename())!=0) {
546 if (*s && !processOption(s)) {
547 ERRMSG(0) "Option string must begin with `+' or `-'"
554 static Bool local processOption(s) /* process string s for options, */
555 String s; { /* return FALSE if none found. */
567 case 'Q' : break; /* already handled */
569 case 'p' : if (s[1]) {
570 if (prompt) free(prompt);
571 prompt = strCopy(s+1);
575 case 'r' : if (s[1]) {
576 if (repeatStr) free(repeatStr);
577 repeatStr = strCopy(s+1);
582 String p = substPath(s+1,hugsPath ? hugsPath : "");
583 if (hugsPath) free(hugsPath);
588 case 'E' : if (hugsEdit) free(hugsEdit);
589 hugsEdit = strCopy(s+1);
592 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
593 case 'F' : if (preprocessor) free(preprocessor);
594 preprocessor = strCopy(s+1);
598 case 'h' : setHeapSize(s+1);
601 case 'c' : if (heapBuilt()) {
603 "You can't enable/disable combined"
604 " operation inside Hugs\n" );
606 /* don't do anything, since pre-scan of args
607 will have got it already */
611 case 'D' : /* hack */
613 extern void setRtsFlags( int x );
614 setRtsFlags(argToInt(s+1));
618 default : if (strcmp("98",s)==0) {
619 if (heapBuilt() && ((state && !haskell98) ||
620 (!state && haskell98))) {
622 "Haskell 98 compatibility cannot be changed"
623 " while the interpreter is running\n");
636 static Void local setHeapSize(s)
639 hpSize = argToInt(s);
640 if (hpSize < MINIMUMHEAP)
641 hpSize = MINIMUMHEAP;
642 else if (MAXIMUMHEAP && hpSize > MAXIMUMHEAP)
643 hpSize = MAXIMUMHEAP;
644 if (heapBuilt() && hpSize != heapSize) {
645 /* ToDo: should this use a message box in winhugs? */
647 FPrintf(stderr,"Change to heap size will not take effect until you rerun Hugs\n");
649 FPrintf(stderr,"You cannot change heap size from inside Hugs\n");
657 static Int local argToInt(s) /* read integer from argument str */
662 if (*s=='\0' || !isascii((int)(*s)) || !isdigit((int)(*s))) {
663 ERRMSG(0) "Missing integer in option setting \"%s\"", t
668 Int d = (*s++) - '0';
669 if (n > ((MAXPOSINT - d)/10)) {
670 ERRMSG(0) "Option setting \"%s\" is too large", t
674 } while (isascii((int)(*s)) && isdigit((int)(*s)));
676 if (*s=='K' || *s=='k') {
677 if (n > (MAXPOSINT/1000)) {
678 ERRMSG(0) "Option setting \"%s\" is too large", t
685 #if MAXPOSINT > 1000000 /* waste of time on 16 bit systems */
686 if (*s=='M' || *s=='m') {
687 if (n > (MAXPOSINT/1000000)) {
688 ERRMSG(0) "Option setting \"%s\" is too large", t
696 #if MAXPOSINT > 1000000000
697 if (*s=='G' || *s=='g') {
698 if (n > (MAXPOSINT/1000000000)) {
699 ERRMSG(0) "Option setting \"%s\" is too large", t
708 ERRMSG(0) "Unwanted characters after option setting \"%s\"", t
715 /* --------------------------------------------------------------------------
716 * Print Menu of list of commands:
717 * ------------------------------------------------------------------------*/
719 static struct cmd cmds[] = {
720 {":?", HELP}, {":cd", CHGDIR}, {":also", ALSO},
721 {":type", TYPEOF}, {":!", SYSTEM}, {":load", LOAD},
722 {":reload", RELOAD}, {":gc", COLLECT}, {":edit", EDIT},
723 {":quit", QUIT}, {":set", SET}, {":find", FIND},
724 {":names", NAMES}, {":info", INFO}, {":project", PROJECT},
725 {":dump", DUMP}, {":ztats", STATS},
726 {":module",SETMODULE},
728 #if EXPLAIN_INSTANCE_RESOLUTION
731 {":version", PNTVER},
736 static Void local menu() {
737 Printf("LIST OF COMMANDS: Any command may be abbreviated to :c where\n");
738 Printf("c is the first character in the full name.\n\n");
739 Printf(":load <filenames> load modules from specified files\n");
740 Printf(":load clear all files except prelude\n");
741 Printf(":also <filenames> read additional modules\n");
742 Printf(":reload repeat last load command\n");
743 Printf(":project <filename> use project file\n");
744 Printf(":edit <filename> edit file\n");
745 Printf(":edit edit last module\n");
746 Printf(":module <module> set module for evaluating expressions\n");
747 Printf("<expr> evaluate expression\n");
748 Printf(":type <expr> print type of expression\n");
749 Printf(":? display this list of commands\n");
750 Printf(":set <options> set command line options\n");
751 Printf(":set help on command line options\n");
752 Printf(":names [pat] list names currently in scope\n");
753 Printf(":info <names> describe named objects\n");
754 Printf(":browse <modules> browse names defined in <modules>\n");
755 #if EXPLAIN_INSTANCE_RESOLUTION
756 Printf(":xplain <context> explain instance resolution for <context>\n");
758 Printf(":find <name> edit module containing definition of name\n");
759 Printf(":!command shell escape\n");
760 Printf(":cd dir change directory\n");
761 Printf(":gc force garbage collection\n");
762 Printf(":version print Hugs version\n");
763 Printf(":dump <name> print STG code for named fn\n");
764 #ifdef CRUDE_PROFILING
765 Printf(":ztats <name> print reduction stats\n");
767 Printf(":quit exit Hugs interpreter\n");
770 static Void local guidance() {
771 Printf("Command not recognised. ");
775 static Void local forHelp() {
776 Printf("Type :? for help\n");
779 /* --------------------------------------------------------------------------
780 * Setting of command line options:
781 * ------------------------------------------------------------------------*/
783 struct options toggle[] = { /* List of command line toggles */
784 {'s', 1, "Print no. reductions/cells after eval", &showStats},
785 {'t', 1, "Print type after evaluation", &addType},
786 {'g', 1, "Print no. cells recovered after gc", &gcMessages},
787 {'l', 1, "Literate modules as default", &literateScripts},
788 {'e', 1, "Warn about errors in literate modules", &literateErrors},
789 {'.', 1, "Print dots to show progress", &useDots},
790 {'q', 1, "Print nothing to show progress", &quiet},
791 {'w', 1, "Always show which modules are loaded", &listScripts},
792 {'k', 1, "Show kind errors in full", &kindExpert},
793 {'o', 0, "Allow overlapping instances", &allowOverlap},
797 {'D', 1, "Debug: show generated code", &debugCode},
799 #if EXPLAIN_INSTANCE_RESOLUTION
800 {'x', 1, "Explain instance resolution", &showInstRes},
803 {'m', 0, "Use multi instance resolution", &multiInstRes},
806 {'D', 1, "Debug: show generated G code", &debugCode},
808 {'S', 1, "Debug: show generated SC code", &debugSC},
812 static Void local set() { /* change command line options from*/
813 String s; /* Hugs command line */
815 if ((s=readFilename())!=0) {
817 if (!processOption(s)) {
818 ERRMSG(0) "Option string must begin with `+' or `-'"
821 } while ((s=readFilename())!=0);
823 writeRegString("Options", optionsToStr());
830 /* --------------------------------------------------------------------------
831 * Change directory command:
832 * ------------------------------------------------------------------------*/
834 static Void local changeDir() { /* change directory */
835 String s = readFilename();
837 ERRMSG(0) "Unable to change to directory \"%s\"", s
842 /* --------------------------------------------------------------------------
843 * Loading project and script files:
844 * ------------------------------------------------------------------------*/
846 static Void local loadProject(s) /* Load project file */
850 projInput(currProject);
851 scriptFile = currProject;
852 forgetScriptsFrom(N_PRELUDE_SCRIPTS);
853 while ((s=readFilename())!=0)
856 ERRMSG(0) "Empty project file"
860 projectLoaded = TRUE;
863 static Void local clearProject() { /* clear name for current project */
867 projectLoaded = FALSE;
869 setLastEdit((String)0,0);
875 static Void local makeStackEntry ( ScriptInfo* ent, String iname )
878 Bool sAvail, iAvail, oAvail;
879 Time sTime, iTime, oTime;
880 Long sSize, iSize, oSize;
883 ok = findFilesForModule (
887 &sAvail, &sTime, &sSize,
888 &iAvail, &iTime, &iSize,
889 &oAvail, &oTime, &oSize
893 "Can't find source or object+interface for module \"%s\"",
894 /* "Can't find source for module \"%s\"", */
898 /* findFilesForModule should enforce this */
899 if (!(sAvail || (oAvail && iAvail)))
901 /* Load objects in preference to sources if both are available */
902 /* 11 Oct 99: disable object loading in the interim.
903 Will probably only reinstate when HEP becomes available.
907 ? (oAvail && iAvail && timeEarlier(sTime,oTime))
913 /* ToDo: namesUpto overflow */
914 ent->modName = strCopy(iname);
917 ent->fromSource = !fromObj;
919 ent->postponed = FALSE;
920 ent->lastChange = sTime; /* ToDo: is this right? */
921 ent->size = fromObj ? iSize : sSize;
922 ent->oSize = fromObj ? oSize : 0;
923 ent->objLoaded = FALSE;
928 static Void nukeEnding( String s )
931 if (l > 4 && strncmp(s+l-4,".u_o" ,4)==0) s[l-4] = 0; else
932 if (l > 5 && strncmp(s+l-5,".u_hi",5)==0) s[l-5] = 0; else
933 if (l > 3 && strncmp(s+l-3,".hs" ,3)==0) s[l-3] = 0; else
934 if (l > 4 && strncmp(s+l-4,".lhs" ,4)==0) s[l-4] = 0; else
935 if (l > 4 && strncmp(s+l-4,".dll" ,4)==0) s[l-4] = 0; else
936 if (l > 4 && strncmp(s+l-4,".DLL" ,4)==0) s[l-4] = 0;
939 static Void local addStackEntry(s) /* Add script to list of scripts */
940 String s; { /* to be read in ... */
945 if (namesUpto>=NUM_SCRIPTS) {
946 ERRMSG(0) "Too many module files (maximum of %d allowed)",
953 for (s2 = s; *s2; s2++)
954 if (*s2 == SLASH && *(s2+1)) s = s2+1;
957 for (i = 0; i < namesUpto; i++)
958 if (strcmp(scriptInfo[i].modName,s)==0)
962 makeStackEntry ( &scriptInfo[namesUpto], strCopy(s) );
968 /* Return TRUE if no imports were needed; FALSE otherwise. */
969 static Bool local addScript(stacknum) /* read single file */
972 static char name[FILENAME_MAX+1];
973 Int len = scriptInfo[stacknum].size;
975 #if HUGS_FOR_WINDOWS /* Set clock cursor while loading */
977 SetCursor(LoadCursor(NULL, IDC_WAIT));
980 // setLastEdit(name,0);
982 strcpy(name, scriptInfo[stacknum].path);
983 strcat(name, scriptInfo[stacknum].modName);
984 if (scriptInfo[stacknum].fromSource)
985 strcat(name, scriptInfo[stacknum].srcExt); else
986 strcat(name, ".u_hi");
990 if (scriptInfo[stacknum].fromSource) {
992 didPrelude = processInterfaces();
994 preludeLoaded = TRUE;
998 lastWasObject = FALSE;
999 Printf("Reading script \"%s\":\n",name);
1000 needsImports = FALSE;
1001 parseScript(name,len);
1002 if (needsImports) return FALSE;
1010 char nameObj[FILENAME_MAX+1];
1013 Printf("Reading iface \"%s\":\n", name);
1015 needsImports = FALSE;
1017 // set nameObj for the benefit of openGHCIface
1018 strcpy(nameObj, scriptInfo[stacknum].path);
1019 strcat(nameObj, scriptInfo[stacknum].modName);
1020 strcat(nameObj, DLL_ENDING);
1021 sizeObj = scriptInfo[stacknum].oSize;
1023 iface = readInterface(name,len);
1024 imports = zsnd(iface); iface = zfst(iface);
1026 if (nonNull(imports)) chase(imports);
1028 lastWasObject = TRUE;
1030 iface_info = ztriple(iface, findText(nameObj), mkInt(sizeObj) );
1031 ifaces_outstanding = cons(iface_info,ifaces_outstanding);
1033 if (needsImports) return FALSE;
1042 Bool chase(imps) /* Process list of import requests */
1046 Int origPos = numScripts; /* keep track of original position */
1047 String origName = scriptInfo[origPos].modName;
1048 for (; nonNull(imps); imps=tl(imps)) {
1049 String iname = textToStr(textOf(hd(imps)));
1051 for (; i<namesUpto; i++)
1052 if (strcmp(scriptInfo[i].modName,iname)==0)
1054 //fprintf(stderr, "import name = %s num = %d\n", iname, i );
1057 /* We should have filled in the details of each module
1058 the first time we hear about it.
1060 assert(scriptInfo[i].details);
1063 if (i>=origPos) { /* Neither loaded or queued */
1069 needsImports = TRUE;
1070 if (scriptInfo[origPos].fromSource)
1071 scriptInfo[origPos].postponed = TRUE;
1073 if (i==namesUpto) { /* Name not found (i==namesUpto) */
1074 /* Find out where it lives, whether source or object, etc */
1075 makeStackEntry ( &scriptInfo[i], iname );
1079 if (scriptInfo[i].postponed && scriptInfo[i].fromSource) {
1080 /* Check for recursive dependency */
1082 "Recursive import dependency between \"%s\" and \"%s\"",
1083 scriptInfo[origPos].modName, iname
1086 /* Move stack entry i to somewhere below origPos. If i denotes
1087 * an object, destination is immediately below origPos.
1088 * Otherwise, it's underneath the queue of objects below origPos.
1090 dstPosn = origPos-1;
1091 if (scriptInfo[i].fromSource)
1092 while (!scriptInfo[dstPosn].fromSource && dstPosn > 0)
1096 tmp = scriptInfo[i];
1097 for (; i > dstPosn; i--) scriptInfo[i] = scriptInfo[i-1];
1098 scriptInfo[dstPosn] = tmp;
1099 if (dstPosn < nextNumScripts) nextNumScripts = dstPosn;
1103 return needsImports;
1106 static Void local forgetScriptsFrom(scno)/* remove scripts from system */
1110 for (i=scno; i<namesUpto; ++i)
1112 free(scriptName[i]);
1114 dropScriptsFrom(scno-1);
1116 if (numScripts>namesUpto)
1120 /* --------------------------------------------------------------------------
1121 * Commands for loading and removing script files:
1122 * ------------------------------------------------------------------------*/
1124 static Void local load() { /* read filenames from command line */
1125 String s; /* and add to list of scripts waiting */
1127 while ((s=readFilename())!=0)
1129 readScripts(N_PRELUDE_SCRIPTS);
1132 static Void local project() { /* read list of script names from */
1133 String s; /* project file */
1135 if ((s=readFilename()) || currProject) {
1137 s = strCopy(currProject);
1138 else if (readFilename()) {
1139 ERRMSG(0) "Too many project files"
1146 ERRMSG(0) "No project filename specified"
1150 readScripts(N_PRELUDE_SCRIPTS);
1153 static Void local readScripts(n) /* Reread current list of scripts, */
1154 Int n; { /* loading everything after and */
1155 Time timeStamp; /* including the first script which*/
1156 Long fileSize; /* has been either changed or added*/
1157 static char name[FILENAME_MAX+1];
1160 lastWasObject = FALSE;
1161 ppSmStack("readscripts-begin");
1162 #if HUGS_FOR_WINDOWS
1163 SetCursor(LoadCursor(NULL, IDC_WAIT));
1167 for (; n<numScripts; n++) { /* Scan previously loaded scripts */
1168 ppSmStack("readscripts-loop1");
1169 getFileInfo(scriptName[n], &timeStamp, &fileSize);
1170 if (timeChanged(timeStamp,lastChange[n])) {
1171 dropScriptsFrom(n-1);
1176 for (; n<NUM_SCRIPTS; n++) /* No scripts have been postponed */
1177 postponed[n] = FALSE; /* at this stage */
1180 while (numScripts<namesUpto) { /* Process any remaining scripts */
1181 ppSmStack("readscripts-loop2");
1182 getFileInfo(scriptName[numScripts], &timeStamp, &fileSize);
1183 timeSet(lastChange[numScripts],timeStamp);
1184 if (numScripts>0) /* no new script for prelude */
1185 startNewScript(scriptName[numScripts]);
1186 if (addScript(scriptName[numScripts],fileSize))
1189 dropScriptsFrom(numScripts-1);
1195 for (; n<numScripts; n++) {
1196 ppSmStack("readscripts-loop2");
1197 strcpy(name, scriptInfo[n].path);
1198 strcat(name, scriptInfo[n].modName);
1199 if (scriptInfo[n].fromSource)
1200 strcat(name, scriptInfo[n].srcExt); else
1201 strcat(name, ".u_hi"); //ToDo: should be .o
1202 getFileInfo(name,&timeStamp, &fileSize);
1203 if (timeChanged(timeStamp,scriptInfo[n].lastChange)) {
1204 dropScriptsFrom(n-1);
1209 for (; n<NUM_SCRIPTS; n++)
1210 scriptInfo[n].postponed = FALSE;
1214 while (numScripts < namesUpto) {
1215 ppSmStack ( "readscripts-loop2" );
1217 if (scriptInfo[numScripts].fromSource) {
1220 startNewScript(scriptInfo[numScripts].modName);
1221 nextNumScripts = NUM_SCRIPTS; //bogus initialisation
1222 if (addScript(numScripts)) {
1224 assert(nextNumScripts==NUM_SCRIPTS);
1227 dropScriptsFrom(numScripts-1);
1231 if (scriptInfo[numScripts].objLoaded) {
1234 scriptInfo[numScripts].objLoaded = TRUE;
1237 startNewScript(scriptInfo[numScripts].modName);
1239 nextNumScripts = NUM_SCRIPTS;
1240 if (addScript(numScripts)) {
1242 assert(nextNumScripts==NUM_SCRIPTS);
1244 //while (!scriptInfo[numScripts].fromSource && numScripts > 0)
1246 //if (scriptInfo[numScripts].fromSource)
1248 numScripts = nextNumScripts;
1249 assert(nextNumScripts<NUM_SCRIPTS);
1253 if (numScripts==namesUpto) ppSmStack( "readscripts-final") ;
1256 didPrelude = processInterfaces();
1258 preludeLoaded = TRUE;
1259 everybody(POSTPREL);
1263 { Int m = namesUpto-1;
1264 Text mtext = findText(scriptInfo[m].modName);
1266 /* Hack to avoid starting up in PrelHugs */
1267 if (mtext == findText("PrelHugs")) mtext = findText("Prelude");
1270 /* Commented out till we understand what
1271 * this is trying to do.
1272 * Problem, you cant find a module till later.
1275 setCurrModule(findModule(mtext));
1285 setLastEdit((String)0, 0);
1286 ppSmStack("readscripts-end ");
1289 static Void local whatScripts() { /* list scripts in current session */
1291 Printf("\nHugs session for:");
1293 Printf(" (project: %s)",currProject);
1294 for (i=0; i<numScripts; ++i)
1295 Printf("\n%s%s",scriptInfo[i].path, scriptInfo[i].modName);
1299 /* --------------------------------------------------------------------------
1300 * Access to external editor:
1301 * ------------------------------------------------------------------------*/
1303 static Void local editor() { /* interpreter-editor interface */
1304 String newFile = readFilename();
1306 setLastEdit(newFile,0);
1307 if (readFilename()) {
1308 ERRMSG(0) "Multiple filenames not permitted"
1315 static Void local find() { /* edit file containing definition */
1317 This just plain wont work no more.
1319 String nm = readFilename(); /* of specified name */
1321 ERRMSG(0) "No name specified"
1324 else if (readFilename()) {
1325 ERRMSG(0) "Multiple names not permitted"
1331 setCurrModule(findEvalModule());
1333 if (nonNull(c=findTycon(t=findText(nm)))) {
1334 if (startEdit(tycon(c).line,scriptName[scriptThisTycon(c)])) {
1335 readScripts(N_PRELUDE_SCRIPTS);
1337 } else if (nonNull(c=findName(t))) {
1338 if (startEdit(name(c).line,scriptName[scriptThisName(c)])) {
1339 readScripts(N_PRELUDE_SCRIPTS);
1342 ERRMSG(0) "No current definition for name \"%s\"", nm
1349 static Void local runEditor() { /* run editor on script lastEdit */
1350 if (startEdit(lastEdLine,lastEdit)) /* at line lastEdLine */
1351 readScripts(N_PRELUDE_SCRIPTS);
1354 static Void local setLastEdit(fname,line)/* keep name of last file to edit */
1359 lastEdit = strCopy(fname);
1361 #if HUGS_FOR_WINDOWS
1362 DrawStatusLine(hWndMain); /* Redo status line */
1366 /* --------------------------------------------------------------------------
1367 * Read and evaluate an expression:
1368 * ------------------------------------------------------------------------*/
1370 static Void local setModule(){/*set module in which to evaluate expressions*/
1371 String s = readFilename();
1372 if (!s) s = ""; /* :m clears the current module selection */
1373 evalModule = findText(s);
1374 setLastEdit(fileOfModule(findEvalModule()),0);
1377 static Module local findEvalModule() { /*Module in which to eval expressions*/
1378 Module m = findModule(evalModule);
1384 static Void local evaluator() { /* evaluate expr and print value */
1388 setCurrModule(findEvalModule());
1390 startNewScript(0); /* Enables recovery of storage */
1391 /* allocated during evaluation */
1394 defaultDefns = combined ? stdDefaults : evalDefaults;
1395 type = typeCheckExp(TRUE);
1397 if (isPolyType(type)) {
1398 ks = polySigOf(type);
1399 bd = monotypeOf(type);
1404 if (whatIs(bd)==QUAL) {
1405 ERRMSG(0) "Unresolved overloading" ETHEN
1406 ERRTEXT "\n*** Type : " ETHEN ERRTYPE(type);
1407 ERRTEXT "\n*** Expression : " ETHEN ERREXPR(inputExpr);
1417 if (isProgType(ks,bd)) {
1418 inputExpr = ap(nameRunIO_toplevel,inputExpr);
1422 Cell d = provePred(ks,NIL,ap(classShow,bd));
1424 ERRMSG(0) "Cannot find \"show\" function for:" ETHEN
1425 ERRTEXT "\n*** expression : " ETHEN ERREXPR(inputExpr);
1426 ERRTEXT "\n*** of type : " ETHEN ERRTYPE(type);
1430 inputExpr = ap2(nameShow, d,inputExpr);
1431 inputExpr = ap (namePutStr, inputExpr);
1432 inputExpr = ap (nameRunIO_toplevel, inputExpr);
1434 evalExp(); printf("\n");
1437 printType(stdout,type);
1444 printf ( "result type is " );
1445 printType ( stdout, type );
1454 static Void local stopAnyPrinting() { /* terminate printing of expression,*/
1455 if (printing) { /* after successful termination or */
1456 printing = FALSE; /* runtime error (e.g. interrupt) */
1459 #define plural(v) v, (v==1?"":"s")
1460 Printf("%lu cell%s",plural(numCells));
1462 Printf(", %u garbage collection%s",plural(numGcs));
1471 /* --------------------------------------------------------------------------
1472 * Print type of input expression:
1473 * ------------------------------------------------------------------------*/
1475 static Void local showtype() { /* print type of expression (if any)*/
1478 setCurrModule(findEvalModule());
1479 startNewScript(0); /* Enables recovery of storage */
1480 /* allocated during evaluation */
1483 defaultDefns = evalDefaults;
1484 type = typeCheckExp(FALSE);
1485 printExp(stdout,inputExpr);
1487 printType(stdout,type);
1492 static Void local browseit(mod,t,all)
1499 Printf("module %s where\n",textToStr(module(mod).text));
1500 for (cs = module(mod).names; nonNull(cs); cs=tl(cs)) {
1502 /* only look at things defined in this module,
1503 unless `all' flag is set */
1504 if (all || name(nm).mod == mod) {
1505 /* unwanted artifacts, like lambda lifted values,
1506 are in the list of names, but have no types */
1507 if (nonNull(name(nm).type)) {
1508 printExp(stdout,nm);
1510 printType(stdout,name(nm).type);
1512 Printf(" -- data constructor");
1513 } else if (isMfun(nm)) {
1514 Printf(" -- class member");
1515 } else if (isSfun(nm)) {
1516 Printf(" -- selector function");
1524 Printf("Unknown module %s\n",t);
1529 static Void local browse() { /* browse modules */
1530 Int count = 0; /* or give menu of commands */
1534 setCurrModule(findEvalModule());
1535 startNewScript(0); /* for recovery of storage */
1536 for (; (s=readFilename())!=0; count++)
1537 if (strcmp(s,"all") == 0) {
1541 browseit(findModule(findText(s)),s,all);
1543 browseit(findEvalModule(),NULL,all);
1547 #if EXPLAIN_INSTANCE_RESOLUTION
1548 static Void local xplain() { /* print type of expression (if any)*/
1550 Bool sir = showInstRes;
1552 setCurrModule(findEvalModule());
1553 startNewScript(0); /* Enables recovery of storage */
1554 /* allocated during evaluation */
1558 d = provePred(NIL,NIL,hd(inputContext));
1560 fprintf(stdout, "not Sat\n");
1562 fprintf(stdout, "Sat\n");
1568 /* --------------------------------------------------------------------------
1569 * Enhanced help system: print current list of scripts or give information
1571 * ------------------------------------------------------------------------*/
1573 static String local objToStr(m,c)
1576 #if 1 || DISPLAY_QUANTIFIERS
1577 static char newVar[60];
1578 switch (whatIs(c)) {
1579 case NAME : if (m == name(c).mod) {
1580 sprintf(newVar,"%s", textToStr(name(c).text));
1582 sprintf(newVar,"%s.%s",
1583 textToStr(module(name(c).mod).text),
1584 textToStr(name(c).text));
1588 case TYCON : if (m == tycon(c).mod) {
1589 sprintf(newVar,"%s", textToStr(tycon(c).text));
1591 sprintf(newVar,"%s.%s",
1592 textToStr(module(tycon(c).mod).text),
1593 textToStr(tycon(c).text));
1597 case CLASS : if (m == cclass(c).mod) {
1598 sprintf(newVar,"%s", textToStr(cclass(c).text));
1600 sprintf(newVar,"%s.%s",
1601 textToStr(module(cclass(c).mod).text),
1602 textToStr(cclass(c).text));
1606 default : internal("objToStr");
1610 static char newVar[33];
1611 switch (whatIs(c)) {
1612 case NAME : sprintf(newVar,"%s", textToStr(name(c).text));
1615 case TYCON : sprintf(newVar,"%s", textToStr(tycon(c).text));
1618 case CLASS : sprintf(newVar,"%s", textToStr(cclass(c).text));
1621 default : internal("objToStr");
1629 static Void dumpStg ( void )
1633 setCurrModule(findEvalModule());
1637 /* request to locate a symbol by name */
1638 if (s && (*s == '?')) {
1639 Text t = findText(s+1);
1640 locateSymbolByName(t);
1644 /* request to dump a bit of the heap */
1645 if (s && (*s == '-' || isdigit(*s))) {
1652 /* request to dump a symbol table entry */
1654 || !(*s == 't' || *s == 'n' || *s == 'c' || *s == 'i')
1655 || !isdigit(s[1])) {
1656 fprintf(stderr, ":d -- bad request `%s'\n", s );
1661 case 't': dumpTycon(i); break;
1662 case 'n': dumpName(i); break;
1663 case 'c': dumpClass(i); break;
1664 case 'i': dumpInst(i); break;
1665 default: fprintf(stderr, ":d -- `%c' not implemented\n", *s );
1671 static Void local dumpStg( void ) { /* print STG stuff */
1676 Cell v; /* really StgVar */
1677 setCurrModule(findEvalModule());
1679 for (; (s=readFilename())!=0;) {
1682 /* find the name while ignoring module scopes */
1683 for (i=NAMEMIN; i<nameHw; i++)
1684 if (name(i).text == t) n = i;
1686 /* perhaps it's an "idNNNNNN" thing? */
1689 s[0]=='i' && s[1]=='d' && isdigit(s[2])) {
1692 while (isdigit(s[i])) {
1693 v = v * 10 + (s[i]-'0');
1697 n = nameFromStgVar(v);
1700 if (isNull(n) && whatIs(v)==STGVAR) {
1701 Printf ( "\n{- `%s' has no nametable entry -}\n", s );
1702 printStg(stderr, v );
1705 Printf ( "Unknown reference `%s'\n", s );
1708 Printf ( "Not a Name: `%s'\n", s );
1710 if (isNull(name(n).stgVar)) {
1711 Printf ( "Doesn't have a STG tree: %s\n", s );
1713 Printf ( "\n{- stgVar of `%s' is id%d -}\n", s, -name(n).stgVar);
1714 printStg(stderr, name(n).stgVar);
1720 static Void local info() { /* describe objects */
1721 Int count = 0; /* or give menu of commands */
1724 setCurrModule(findEvalModule());
1725 startNewScript(0); /* for recovery of storage */
1726 for (; (s=readFilename())!=0; count++) {
1727 describe(findText(s));
1735 static Void local describe(t) /* describe an object */
1737 Tycon tc = findTycon(t);
1738 Class cl = findClass(t);
1739 Name nm = findName(t);
1741 if (nonNull(tc)) { /* as a type constructor */
1745 for (i=0; i<tycon(tc).arity; ++i) {
1746 t = ap(t,mkOffset(i));
1748 Printf("-- type constructor");
1750 Printf(" with kind ");
1751 printKind(stdout,tycon(tc).kind);
1754 switch (tycon(tc).what) {
1755 case SYNONYM : Printf("type ");
1756 printType(stdout,t);
1758 printType(stdout,tycon(tc).defn);
1762 case DATATYPE : { List cs = tycon(tc).defn;
1763 if (tycon(tc).what==DATATYPE) {
1768 printType(stdout,t);
1770 mapProc(printSyntax,cs);
1772 Printf("\n-- constructors:");
1774 for (; hasCfun(cs); cs=tl(cs)) {
1776 printExp(stdout,hd(cs));
1778 printType(stdout,name(hd(cs)).type);
1781 Printf("\n-- selectors:");
1783 for (; nonNull(cs); cs=tl(cs)) {
1785 printExp(stdout,hd(cs));
1787 printType(stdout,name(hd(cs)).type);
1792 case RESTRICTSYN : Printf("type ");
1793 printType(stdout,t);
1794 Printf(" = <restricted>");
1798 if (nonNull(in=findFirstInst(tc))) {
1799 Printf("\n-- instances:\n");
1802 in = findNextInst(tc,in);
1803 } while (nonNull(in));
1808 if (nonNull(cl)) { /* as a class */
1809 List ins = cclass(cl).instances;
1810 Kinds ks = cclass(cl).kinds;
1811 if (nonNull(ks) && isNull(tl(ks)) && hd(ks)==STAR) {
1812 Printf("-- type class");
1814 Printf("-- constructor class");
1816 Printf(" with arity ");
1817 printKinds(stdout,ks);
1821 mapProc(printSyntax,cclass(cl).members);
1823 if (nonNull(cclass(cl).supers)) {
1824 printContext(stdout,cclass(cl).supers);
1827 printPred(stdout,cclass(cl).head);
1829 if (nonNull(cclass(cl).fds)) {
1830 List fds = cclass(cl).fds;
1832 for (; nonNull(fds); fds=tl(fds)) {
1834 printFD(stdout,hd(fds));
1839 if (nonNull(cclass(cl).members)) {
1840 List ms = cclass(cl).members;
1843 Type t = name(hd(ms)).type;
1844 if (isPolyType(t)) {
1848 printExp(stdout,hd(ms));
1850 if (isNull(tl(fst(snd(t))))) {
1853 t = ap(QUAL,pair(tl(fst(snd(t))),snd(snd(t))));
1855 printType(stdout,t);
1857 } while (nonNull(ms));
1861 Printf("\n-- instances:\n");
1865 } while (nonNull(ins));
1870 if (nonNull(nm)) { /* as a function/name */
1872 printExp(stdout,nm);
1874 if (nonNull(name(nm).type)) {
1875 printType(stdout,name(nm).type);
1877 Printf("<unknown type>");
1879 printf("\n");print(name(nm).type,10);printf("\n");
1881 Printf(" -- data constructor");
1882 } else if (isMfun(nm)) {
1883 Printf(" -- class member");
1884 } else if (isSfun(nm)) {
1885 Printf(" -- selector function");
1891 if (isNull(tc) && isNull(cl) && isNull(nm)) {
1892 Printf("Unknown reference `%s'\n",textToStr(t));
1896 static Void local printSyntax(nm)
1898 Syntax sy = syntaxOf(nm);
1899 Text t = name(nm).text;
1900 String s = textToStr(t);
1901 if (sy != defaultSyntax(t)) {
1903 switch (assocOf(sy)) {
1904 case LEFT_ASS : Putchar('l'); break;
1905 case RIGHT_ASS : Putchar('r'); break;
1906 case NON_ASS : break;
1908 Printf(" %i ",precOf(sy));
1909 if (isascii((int)(*s)) && isalpha((int)(*s))) {
1918 static Void local showInst(in) /* Display instance decl header */
1920 Printf("instance ");
1921 if (nonNull(inst(in).specifics)) {
1922 printContext(stdout,inst(in).specifics);
1925 printPred(stdout,inst(in).head);
1929 /* --------------------------------------------------------------------------
1930 * List all names currently in scope:
1931 * ------------------------------------------------------------------------*/
1933 static Void local listNames() { /* list names matching optional pat*/
1934 String pat = readFilename();
1936 Int width = getTerminalWidth() - 1;
1939 Module mod = findEvalModule();
1941 if (pat) { /* First gather names to list */
1943 names = addNamesMatching(pat,names);
1944 } while ((pat=readFilename())!=0);
1946 names = addNamesMatching((String)0,names);
1948 if (isNull(names)) { /* Then print them out */
1949 ERRMSG(0) "No names selected"
1952 for (termPos=0; nonNull(names); names=tl(names)) {
1953 String s = objToStr(mod,hd(names));
1955 if (termPos+1+l>width) {
1958 } else if (termPos>0) {
1966 Printf("\n(%d names listed)\n", count);
1969 /* --------------------------------------------------------------------------
1970 * print a prompt and read a line of input:
1971 * ------------------------------------------------------------------------*/
1973 static Void local promptForInput(moduleName)
1974 String moduleName; {
1975 char promptBuffer[1000];
1977 /* This is portable but could overflow buffer */
1978 sprintf(promptBuffer,prompt,moduleName);
1980 /* Works on ANSI C - but pre-ANSI compilers return a pointer to
1981 * promptBuffer instead.
1983 if (sprintf(promptBuffer,prompt,moduleName) >= 1000) {
1984 /* Reset prompt to a safe default to avoid an infinite loop */
1986 prompt = strCopy("? ");
1987 internal("Combined prompt and evaluation module name too long");
1991 stringInput("main\0"); else
1992 consoleInput(promptBuffer);
1995 /* --------------------------------------------------------------------------
1996 * main read-eval-print loop, with error trapping:
1997 * ------------------------------------------------------------------------*/
1999 static jmp_buf catch_error; /* jump buffer for error trapping */
2001 static Void local interpreter(argc,argv)/* main interpreter loop */
2004 Int errorNumber = setjmp(catch_error);
2006 if (errorNumber && autoMain) {
2007 fprintf(stderr, "hugs +Q: compilation failed -- can't run `main'\n" );
2011 breakOn(TRUE); /* enable break trapping */
2012 if (numScripts==0) { /* only succeeds on first time, */
2013 if (errorNumber) /* before prelude has been loaded */
2014 fatal("Unable to load prelude");
2015 initialize(argc,argv);
2019 /* initialize calls startupHaskell, which trashes our signal handlers */
2024 everybody(RESET); /* reset to sensible initial state */
2025 dropScriptsFrom(numScripts-1); /* remove partially loaded scripts */
2026 /* not counting prelude as a script*/
2028 promptForInput(textToStr(module(findEvalModule()).text));
2030 cmd = readCommand(cmds, (Char)':', (Char)'!');
2035 case EDIT : editor();
2039 case LOAD : clearProject();
2040 forgetScriptsFrom(N_PRELUDE_SCRIPTS);
2043 case ALSO : clearProject();
2044 forgetScriptsFrom(numScripts);
2047 case RELOAD : readScripts(N_PRELUDE_SCRIPTS);
2049 case PROJECT: project();
2054 case EVAL : evaluator();
2056 case TYPEOF : showtype();
2058 case BROWSE : browse();
2060 #if EXPLAIN_INSTANCE_RESOLUTION
2061 case XPLAIN : xplain();
2064 case NAMES : listNames();
2068 case BADCMD : guidance();
2073 #ifdef CRUDE_PROFILING
2077 case SYSTEM : if (shellEsc(readLine()))
2078 Printf("Warning: Shell escape terminated abnormally\n");
2080 case CHGDIR : changeDir();
2084 case PNTVER: Printf("-- Hugs Version %s\n",
2087 case DUMP : dumpStg();
2090 case COLLECT: consGC = FALSE;
2093 Printf("Garbage collection recovered %d cells\n",
2100 Printf("Elapsed time (ms): %ld (user), %ld (system)\n",
2101 millisecs(userElapsed), millisecs(systElapsed));
2103 if (autoMain) break;
2108 /* --------------------------------------------------------------------------
2109 * Display progress towards goal:
2110 * ------------------------------------------------------------------------*/
2112 static Target currTarget;
2113 static Bool aiming = FALSE;
2116 static Int charCount;
2118 Void setGoal(what, t) /* Set goal for what to be t */
2123 #if EXPLAIN_INSTANCE_RESOLUTION
2127 currTarget = (t?t:1);
2130 currPos = strlen(what);
2131 maxPos = getTerminalWidth() - 1;
2135 for (charCount=0; *what; charCount++)
2140 Void soFar(t) /* Indicate progress towards goal */
2141 Target t; { /* has now reached t */
2144 #if EXPLAIN_INSTANCE_RESOLUTION
2149 Int newPos = (Int)((maxPos * ((long)t))/currTarget);
2154 if (newPos>currPos) {
2157 while (newPos>++currPos);
2164 Void done() { /* Goal has now been achieved */
2167 #if EXPLAIN_INSTANCE_RESOLUTION
2172 while (maxPos>currPos++)
2177 for (; charCount>0; charCount--) {
2186 static Void local failed() { /* Goal cannot be reached due to */
2187 if (aiming) { /* errors */
2194 /* --------------------------------------------------------------------------
2196 * ------------------------------------------------------------------------*/
2198 Void errHead(l) /* print start of error message */
2200 failed(); /* failed to reach target ... */
2202 FPrintf(errorStream,"ERROR");
2205 FPrintf(errorStream," \"%s\"", scriptFile);
2206 setLastEdit(scriptFile,l);
2207 if (l) FPrintf(errorStream," (line %d)",l);
2210 FPrintf(errorStream,": ");
2211 FFlush(errorStream);
2214 Void errFail() { /* terminate error message and */
2215 Putc('\n',errorStream); /* produce exception to return to */
2216 FFlush(errorStream); /* main command loop */
2217 longjmp(catch_error,1);
2220 Void errAbort() { /* altern. form of error handling */
2221 failed(); /* used when suitable error message*/
2222 stopAnyPrinting(); /* has already been printed */
2226 Void internal(msg) /* handle internal error */
2228 #if HUGS_FOR_WINDOWS
2230 wsprintf(buf,"INTERNAL ERROR: %s",msg);
2231 MessageBox(hWndMain, buf, appName, MB_ICONHAND | MB_OK);
2235 Printf("INTERNAL ERROR: %s\n",msg);
2237 longjmp(catch_error,1);
2240 Void fatal(msg) /* handle fatal error */
2242 #if HUGS_FOR_WINDOWS
2244 wsprintf(buf,"FATAL ERROR: %s",msg);
2245 MessageBox(hWndMain, buf, appName, MB_ICONHAND | MB_OK);
2248 Printf("\nFATAL ERROR: %s\n",msg);
2253 sigHandler(breakHandler) { /* respond to break interrupt */
2254 #if HUGS_FOR_WINDOWS
2255 MessageBox(GetFocus(), "Interrupted!", appName, MB_ICONSTOP | MB_OK);
2258 Printf("{Interrupted!}\n");
2260 breakOn(TRUE); /* reinstall signal handler - redundant on BSD systems */
2261 /* but essential on POSIX (and other?) systems */
2267 longjmp(catch_error,1);
2268 sigResume;/*NOTREACHED*/
2271 /* --------------------------------------------------------------------------
2272 * Read value from environment variable or registry:
2273 * ------------------------------------------------------------------------*/
2275 String fromEnv(var,def) /* return value of: */
2276 String var; /* environment variable named by var */
2277 String def; { /* or: default value given by def */
2278 String s = getenv(var);
2279 return (s ? s : def);
2282 /* --------------------------------------------------------------------------
2283 * String manipulation routines:
2284 * ------------------------------------------------------------------------*/
2286 static String local strCopy(s) /* make malloced copy of a string */
2290 if ((t=(char *)malloc(strlen(s)+1))==0) {
2291 ERRMSG(0) "String storage space exhausted"
2294 for (r=t; (*r++ = *s++)!=0; ) {
2301 /* --------------------------------------------------------------------------
2303 * We can redirect compiler output (prompts, error messages, etc) by
2304 * tweaking these functions.
2305 * ------------------------------------------------------------------------*/
2307 #if REDIRECT_OUTPUT && !HUGS_FOR_WINDOWS
2309 #ifdef HAVE_STDARG_H
2312 #include <varargs.h>
2315 /* ----------------------------------------------------------------------- */
2317 #define BufferSize 10000 /* size of redirected output buffer */
2319 typedef struct _HugsStream {
2320 char buffer[BufferSize]; /* buffer for redirected output */
2321 Int next; /* next space in buffer */
2324 static Void local vBufferedPrintf Args((HugsStream*, const char*, va_list));
2325 static Void local bufferedPutchar Args((HugsStream*, Char));
2326 static String local bufferClear Args((HugsStream *stream));
2328 static Void local vBufferedPrintf(stream, fmt, ap)
2332 Int spaceLeft = BufferSize - stream->next;
2333 char* p = &stream->buffer[stream->next];
2334 Int charsAdded = vsnprintf(p, spaceLeft, fmt, ap);
2335 if (0 <= charsAdded && charsAdded < spaceLeft)
2336 stream->next += charsAdded;
2337 #if 1 /* we can either buffer the first n chars or buffer the last n chars */
2343 static Void local bufferedPutchar(stream, c)
2346 if (BufferSize - stream->next >= 2) {
2347 stream->buffer[stream->next++] = c;
2348 stream->buffer[stream->next] = '\0';
2352 static String local bufferClear(stream)
2353 HugsStream *stream; {
2354 if (stream->next == 0) {
2358 return stream->buffer;
2362 /* ----------------------------------------------------------------------- */
2364 static HugsStream outputStreamH;
2366 * We rely on standard C semantics to initialise outputStreamH.next to 0.
2369 Void hugsEnableOutput(f)
2374 String hugsClearOutputBuffer() {
2375 return bufferClear(&outputStreamH);
2378 #ifdef HAVE_STDARG_H
2379 Void hugsPrintf(const char *fmt, ...) {
2380 va_list ap; /* pointer into argument list */
2381 va_start(ap, fmt); /* make ap point to first arg after fmt */
2382 if (!disableOutput) {
2385 vBufferedPrintf(&outputStreamH, fmt, ap);
2387 va_end(ap); /* clean up */
2390 Void hugsPrintf(fmt, va_alist)
2393 va_list ap; /* pointer into argument list */
2394 va_start(ap); /* make ap point to first arg after fmt */
2395 if (!disableOutput) {
2398 vBufferedPrintf(&outputStreamH, fmt, ap);
2400 va_end(ap); /* clean up */
2406 if (!disableOutput) {
2409 bufferedPutchar(&outputStreamH, c);
2413 Void hugsFlushStdout() {
2414 if (!disableOutput) {
2421 if (!disableOutput) {
2426 #ifdef HAVE_STDARG_H
2427 Void hugsFPrintf(FILE *fp, const char* fmt, ...) {
2430 if (!disableOutput) {
2431 vfprintf(fp, fmt, ap);
2433 vBufferedPrintf(&outputStreamH, fmt, ap);
2438 Void hugsFPrintf(FILE *fp, const char* fmt, va_list)
2444 if (!disableOutput) {
2445 vfprintf(fp, fmt, ap);
2447 vBufferedPrintf(&outputStreamH, fmt, ap);
2453 Void hugsPutc(c, fp)
2456 if (!disableOutput) {
2459 bufferedPutchar(&outputStreamH, c);
2463 #endif /* REDIRECT_OUTPUT && !HUGS_FOR_WINDOWS */
2464 /* --------------------------------------------------------------------------
2465 * Send message to each component of system:
2466 * ------------------------------------------------------------------------*/
2468 Void everybody(what) /* send command `what' to each component of*/
2469 Int what; { /* system to respond as appropriate ... */
2471 fprintf ( stderr, "EVERYBODY %d\n", what );
2473 machdep(what); /* The order of calling each component is */
2474 storage(what); /* important for the PREPREL command */
2477 translateControl(what);
2479 staticAnalysis(what);
2480 deriveControl(what);
2486 /* --------------------------------------------------------------------------
2487 * Hugs for Windows code (WinMain and related functions)
2488 * ------------------------------------------------------------------------*/
2490 #if HUGS_FOR_WINDOWS
2491 #include "winhugs.c"