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: 1999/12/03 12:39:38 $
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 /* --------------------------------------------------------------------------
44 * Local function prototypes:
45 * ------------------------------------------------------------------------*/
47 static Void local initialize Args((Int,String []));
48 static Void local promptForInput Args((String));
49 static Void local interpreter Args((Int,String []));
50 static Void local menu Args((Void));
51 static Void local guidance Args((Void));
52 static Void local forHelp Args((Void));
53 static Void local set Args((Void));
54 static Void local changeDir Args((Void));
55 static Void local load Args((Void));
56 static Void local project Args((Void));
57 static Void local readScripts Args((Int));
58 static Void local whatScripts Args((Void));
59 static Void local editor Args((Void));
60 static Void local find Args((Void));
61 static Bool local startEdit Args((Int,String));
62 static Void local runEditor Args((Void));
63 static Void local setModule Args((Void));
64 static Module local findEvalModule Args((Void));
65 static Void local evaluator Args((Void));
66 static Void local stopAnyPrinting Args((Void));
67 static Void local showtype Args((Void));
68 static String local objToStr Args((Module, Cell));
69 static Void local info Args((Void));
70 static Void local printSyntax Args((Name));
71 static Void local showInst Args((Inst));
72 static Void local describe Args((Text));
73 static Void local listNames Args((Void));
75 static Void local toggleSet Args((Char,Bool));
76 static Void local togglesIn Args((Bool));
77 static Void local optionInfo Args((Void));
78 #if USE_REGISTRY || HUGS_FOR_WINDOWS
79 static String local optionsToStr Args((Void));
81 static Void local readOptions Args((String));
82 static Bool local processOption Args((String));
83 static Void local setHeapSize Args((String));
84 static Int local argToInt Args((String));
86 static Void local loadProject Args((String));
87 static Void local clearProject Args((Void));
88 static Bool local addScript Args((Int));
89 static Void local forgetScriptsFrom Args((Script));
90 static Void local setLastEdit Args((String,Int));
91 static Void local failed Args((Void));
92 static String local strCopy Args((String));
93 static Void local browseit Args((Module,String,Bool));
94 static Void local browse Args((Void));
96 /* --------------------------------------------------------------------------
97 * Machine dependent code for Hugs interpreter:
98 * ------------------------------------------------------------------------*/
105 /* --------------------------------------------------------------------------
107 * ------------------------------------------------------------------------*/
109 static Bool printing = FALSE; /* TRUE => currently printing value*/
110 static Bool showStats = FALSE; /* TRUE => print stats after eval */
111 static Bool listScripts = TRUE; /* TRUE => list scripts after loading*/
112 static Bool addType = FALSE; /* TRUE => print type with value */
113 static Bool useDots = RISCOS; /* TRUE => use dots in progress */
114 static Bool quiet = FALSE; /* TRUE => don't show progress */
115 static Bool lastWasObject = FALSE;
116 Bool preludeLoaded = FALSE;
117 Bool debugSC = FALSE;
118 Bool combined = TRUE; //FALSE;
122 String modName; /* Module name */
123 Bool details; /* FALSE => remaining fields are invalid */
124 String path; /* Path to module */
125 String srcExt; /* ".hs" or ".lhs" if fromSource */
126 Time lastChange; /* Time of last change to script */
127 Bool fromSource; /* FALSE => load object code */
128 Bool postponed; /* Indicates postponed load */
135 static Void local makeStackEntry Args((ScriptInfo*,String));
136 static Void local addStackEntry Args((String));
138 static ScriptInfo scriptInfo[NUM_SCRIPTS];
140 static Int numScripts; /* Number of scripts loaded */
141 static Int nextNumScripts;
142 static Int namesUpto; /* Number of script names set */
143 static Bool needsImports; /* set to TRUE if imports required */
144 String scriptFile; /* Name of current script (if any) */
148 static Text evalModule = 0; /* Name of module we eval exprs in */
149 static String currProject = 0; /* Name of current project file */
150 static Bool projectLoaded = FALSE; /* TRUE => project file loaded */
152 static Bool autoMain = FALSE;
153 static String lastEdit = 0; /* Name of script to edit (if any) */
154 static Int lastEdLine = 0; /* Editor line number (if possible)*/
155 static String prompt = 0; /* Prompt string */
156 static Int hpSize = DEFAULTHEAP; /* Desired heap size */
157 String hugsEdit = 0; /* String for editor command */
158 String hugsPath = 0; /* String for file search path */
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;
307 addStackEntry("Prelude");
309 for (i=1; i<argc; ++i) { /* process command line arguments */
310 if (strcmp(argv[i], "--")==0) break;
311 if (strcmp(argv[i],"+")==0 && i+1<argc) {
313 ERRMSG(0) "Multiple project filenames on command line"
318 } else if (argv[i] && argv[i][0]/* workaround for /bin/sh silliness*/
319 && !processOption(argv[i])) {
320 addStackEntry(argv[i]);
326 char exe_name[N_INSTALLDIR + 6];
327 strcpy(exe_name, installDir);
328 strcat(exe_name, "hugs");
329 DEBUG_LoadSymbols(exe_name);
335 if (!scriptName[0]) {
336 Printf("Prelude not found on current path: \"%s\"\n",
337 hugsPath ? hugsPath : "");
338 fatal("Unable to load prelude");
343 Printf("Haskell 98 mode: Restart with command line option -98 to enable extensions\n");
345 Printf("Hugs mode: Restart with command line option +98 for Haskell 98 mode\n");
349 Printf("Combined mode: Restart with command line -c for standalone mode\n\n" );
351 Printf("Standalone mode: Restart with command line +c for combined mode\n\n" );
355 evalModule = findText(""); /* evaluate wrt last module by default */
359 "\nUsing project file, ignoring additional filenames\n");
361 loadProject(strCopy(proj));
366 /* --------------------------------------------------------------------------
367 * Command line options:
368 * ------------------------------------------------------------------------*/
370 struct options { /* command line option toggles */
371 char c; /* table defined in main app. */
376 extern struct options toggle[];
378 static Void local toggleSet(c,state) /* Set command line toggle */
382 for (i=0; toggle[i].c; ++i)
383 if (toggle[i].c == c) {
384 *toggle[i].flag = state;
387 ERRMSG(0) "Unknown toggle `%c'", c
391 static Void local togglesIn(state) /* Print current list of toggles in*/
392 Bool state; { /* given state */
395 for (i=0; toggle[i].c; ++i)
396 if (*toggle[i].flag == state && (!haskell98 || toggle[i].h98)) {
398 Putchar((char)(state ? '+' : '-'));
399 Putchar(toggle[i].c);
406 static Void local optionInfo() { /* Print information about command */
407 static String fmts = "%-5s%s\n"; /* line settings */
408 static String fmtc = "%-5c%s\n";
411 Printf("TOGGLES: groups begin with +/- to turn options on/off resp.\n");
412 for (i=0; toggle[i].c; ++i) {
413 if (!haskell98 || toggle[i].h98) {
414 Printf(fmtc,toggle[i].c,toggle[i].description);
418 Printf("\nOTHER OPTIONS: (leading + or - makes no difference)\n");
419 Printf(fmts,"hnum","Set heap size (cannot be changed within Hugs)");
420 Printf(fmts,"pstr","Set prompt string to str");
421 Printf(fmts,"rstr","Set repeat last expression string to str");
422 Printf(fmts,"Pstr","Set search path for modules to str");
423 Printf(fmts,"Estr","Use editor setting given by str");
424 Printf(fmts,"cnum","Set constraint cutoff limit");
425 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
426 Printf(fmts,"Fstr","Set preprocessor filter to str");
429 Printf("\nCurrent settings: ");
432 Printf("-h%d",heapSize);
436 printString(repeatStr);
437 Printf(" -c%d",cutoff);
438 Printf("\nSearch path : -P");
439 printString(hugsPath);
442 if (projectPath!=NULL) {
443 Printf("\nProject Path : %s",projectPath);
446 Printf("\nEditor setting : -E");
447 printString(hugsEdit);
448 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
449 Printf("\nPreprocessor : -F");
450 printString(preprocessor);
452 Printf("\nCompatibility : %s", haskell98 ? "Haskell 98 (+98)"
453 : "Hugs Extensions (-98)");
457 #if USE_REGISTRY || HUGS_FOR_WINDOWS
465 #define PUTInt(optc,i) \
466 sprintf(next,"-%c%d",optc,i); \
469 #define PUTStr(c,s) \
470 next=PUTStr_aux(next,c,s)
472 static String local PUTStr_aux Args((String,Char, String));
474 static String local PUTStr_aux(next,c,s)
480 sprintf(next,"-%c\"",c);
483 PUTS(unlexChar(*t,'"'));
491 static String local optionsToStr() { /* convert options to string */
492 static char buffer[2000];
493 String next = buffer;
496 for (i=0; toggle[i].c; ++i) {
497 PUTC(*toggle[i].flag ? '+' : '-');
501 PUTS(haskell98 ? "+98 " : "-98 ");
502 PUTInt('h',hpSize); PUTC(' ');
504 PUTStr('r',repeatStr);
505 PUTStr('P',hugsPath);
506 PUTStr('E',hugsEdit);
507 PUTInt('c',cutoff); PUTC(' ');
508 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
509 PUTStr('F',preprocessor);
514 #endif /* USE_REGISTRY */
521 static Void local readOptions(options) /* read options from string */
525 stringInput(options);
526 while ((s=readFilename())!=0) {
527 if (*s && !processOption(s)) {
528 ERRMSG(0) "Option string must begin with `+' or `-'"
535 static Bool local processOption(s) /* process string s for options, */
536 String s; { /* return FALSE if none found. */
548 case 'Q' : break; /* already handled */
550 case 'p' : if (s[1]) {
551 if (prompt) free(prompt);
552 prompt = strCopy(s+1);
556 case 'r' : if (s[1]) {
557 if (repeatStr) free(repeatStr);
558 repeatStr = strCopy(s+1);
563 String p = substPath(s+1,hugsPath ? hugsPath : "");
564 if (hugsPath) free(hugsPath);
569 case 'E' : if (hugsEdit) free(hugsEdit);
570 hugsEdit = strCopy(s+1);
573 #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
574 case 'F' : if (preprocessor) free(preprocessor);
575 preprocessor = strCopy(s+1);
579 case 'h' : setHeapSize(s+1);
582 case 'c' : if (heapBuilt()) {
584 "You can't enable/disable combined"
585 " operation inside Hugs\n" );
591 case 'D' : /* hack */
593 extern void setRtsFlags( int x );
594 setRtsFlags(argToInt(s+1));
598 default : if (strcmp("98",s)==0) {
599 if (heapBuilt() && ((state && !haskell98) ||
600 (!state && haskell98))) {
602 "Haskell 98 compatibility cannot be changed"
603 " while the interpreter is running\n");
616 static Void local setHeapSize(s)
619 hpSize = argToInt(s);
620 if (hpSize < MINIMUMHEAP)
621 hpSize = MINIMUMHEAP;
622 else if (MAXIMUMHEAP && hpSize > MAXIMUMHEAP)
623 hpSize = MAXIMUMHEAP;
624 if (heapBuilt() && hpSize != heapSize) {
625 /* ToDo: should this use a message box in winhugs? */
627 FPrintf(stderr,"Change to heap size will not take effect until you rerun Hugs\n");
629 FPrintf(stderr,"You cannot change heap size from inside Hugs\n");
637 static Int local argToInt(s) /* read integer from argument str */
642 if (*s=='\0' || !isascii((int)(*s)) || !isdigit((int)(*s))) {
643 ERRMSG(0) "Missing integer in option setting \"%s\"", t
648 Int d = (*s++) - '0';
649 if (n > ((MAXPOSINT - d)/10)) {
650 ERRMSG(0) "Option setting \"%s\" is too large", t
654 } while (isascii((int)(*s)) && isdigit((int)(*s)));
656 if (*s=='K' || *s=='k') {
657 if (n > (MAXPOSINT/1000)) {
658 ERRMSG(0) "Option setting \"%s\" is too large", t
665 #if MAXPOSINT > 1000000 /* waste of time on 16 bit systems */
666 if (*s=='M' || *s=='m') {
667 if (n > (MAXPOSINT/1000000)) {
668 ERRMSG(0) "Option setting \"%s\" is too large", t
676 #if MAXPOSINT > 1000000000
677 if (*s=='G' || *s=='g') {
678 if (n > (MAXPOSINT/1000000000)) {
679 ERRMSG(0) "Option setting \"%s\" is too large", t
688 ERRMSG(0) "Unwanted characters after option setting \"%s\"", t
695 /* --------------------------------------------------------------------------
696 * Print Menu of list of commands:
697 * ------------------------------------------------------------------------*/
699 static struct cmd cmds[] = {
700 {":?", HELP}, {":cd", CHGDIR}, {":also", ALSO},
701 {":type", TYPEOF}, {":!", SYSTEM}, {":load", LOAD},
702 {":reload", RELOAD}, {":gc", COLLECT}, {":edit", EDIT},
703 {":quit", QUIT}, {":set", SET}, {":find", FIND},
704 {":names", NAMES}, {":info", INFO}, {":project", PROJECT},
705 {":dump", DUMP}, {":ztats", STATS},
706 {":module",SETMODULE},
708 #if EXPLAIN_INSTANCE_RESOLUTION
711 {":version", PNTVER},
716 static Void local menu() {
717 Printf("LIST OF COMMANDS: Any command may be abbreviated to :c where\n");
718 Printf("c is the first character in the full name.\n\n");
719 Printf(":load <filenames> load modules from specified files\n");
720 Printf(":load clear all files except prelude\n");
721 Printf(":also <filenames> read additional modules\n");
722 Printf(":reload repeat last load command\n");
723 Printf(":project <filename> use project file\n");
724 Printf(":edit <filename> edit file\n");
725 Printf(":edit edit last module\n");
726 Printf(":module <module> set module for evaluating expressions\n");
727 Printf("<expr> evaluate expression\n");
728 Printf(":type <expr> print type of expression\n");
729 Printf(":? display this list of commands\n");
730 Printf(":set <options> set command line options\n");
731 Printf(":set help on command line options\n");
732 Printf(":names [pat] list names currently in scope\n");
733 Printf(":info <names> describe named objects\n");
734 Printf(":browse <modules> browse names defined in <modules>\n");
735 #if EXPLAIN_INSTANCE_RESOLUTION
736 Printf(":xplain <context> explain instance resolution for <context>\n");
738 Printf(":find <name> edit module containing definition of name\n");
739 Printf(":!command shell escape\n");
740 Printf(":cd dir change directory\n");
741 Printf(":gc force garbage collection\n");
742 Printf(":version print Hugs version\n");
743 Printf(":dump <name> print STG code for named fn\n");
744 #ifdef CRUDE_PROFILING
745 Printf(":ztats <name> print reduction stats\n");
747 Printf(":quit exit Hugs interpreter\n");
750 static Void local guidance() {
751 Printf("Command not recognised. ");
755 static Void local forHelp() {
756 Printf("Type :? for help\n");
759 /* --------------------------------------------------------------------------
760 * Setting of command line options:
761 * ------------------------------------------------------------------------*/
763 struct options toggle[] = { /* List of command line toggles */
764 {'s', 1, "Print no. reductions/cells after eval", &showStats},
765 {'t', 1, "Print type after evaluation", &addType},
766 {'g', 1, "Print no. cells recovered after gc", &gcMessages},
767 {'l', 1, "Literate modules as default", &literateScripts},
768 {'e', 1, "Warn about errors in literate modules", &literateErrors},
769 {'.', 1, "Print dots to show progress", &useDots},
770 {'q', 1, "Print nothing to show progress", &quiet},
771 {'w', 1, "Always show which modules are loaded", &listScripts},
772 {'k', 1, "Show kind errors in full", &kindExpert},
773 {'o', 0, "Allow overlapping instances", &allowOverlap},
777 {'D', 1, "Debug: show generated code", &debugCode},
779 #if EXPLAIN_INSTANCE_RESOLUTION
780 {'x', 1, "Explain instance resolution", &showInstRes},
783 {'m', 0, "Use multi instance resolution", &multiInstRes},
786 {'D', 1, "Debug: show generated G code", &debugCode},
788 {'S', 1, "Debug: show generated SC code", &debugSC},
792 static Void local set() { /* change command line options from*/
793 String s; /* Hugs command line */
795 if ((s=readFilename())!=0) {
797 if (!processOption(s)) {
798 ERRMSG(0) "Option string must begin with `+' or `-'"
801 } while ((s=readFilename())!=0);
803 writeRegString("Options", optionsToStr());
810 /* --------------------------------------------------------------------------
811 * Change directory command:
812 * ------------------------------------------------------------------------*/
814 static Void local changeDir() { /* change directory */
815 String s = readFilename();
817 ERRMSG(0) "Unable to change to directory \"%s\"", s
822 /* --------------------------------------------------------------------------
823 * Loading project and script files:
824 * ------------------------------------------------------------------------*/
826 static Void local loadProject(s) /* Load project file */
830 projInput(currProject);
831 scriptFile = currProject;
832 forgetScriptsFrom(1);
833 while ((s=readFilename())!=0)
836 ERRMSG(0) "Empty project file"
840 projectLoaded = TRUE;
843 static Void local clearProject() { /* clear name for current project */
847 projectLoaded = FALSE;
849 setLastEdit((String)0,0);
855 static Void local makeStackEntry ( ScriptInfo* ent, String iname )
858 Bool sAvail, iAvail, oAvail;
859 Time sTime, iTime, oTime;
860 Long sSize, iSize, oSize;
863 ok = findFilesForModule (
867 &sAvail, &sTime, &sSize,
868 &iAvail, &iTime, &iSize,
869 &oAvail, &oTime, &oSize
873 "Can't find source or object+interface for module \"%s\"",
874 /* "Can't find source for module \"%s\"", */
878 /* findFilesForModule should enforce this */
879 if (!(sAvail || (oAvail && iAvail)))
881 /* Load objects in preference to sources if both are available */
882 /* 11 Oct 99: disable object loading in the interim.
883 Will probably only reinstate when HEP becomes available.
887 ? (oAvail && iAvail && timeEarlier(sTime,oTime))
893 /* ToDo: namesUpto overflow */
894 ent->modName = strCopy(iname);
897 ent->fromSource = !fromObj;
899 ent->postponed = FALSE;
900 ent->lastChange = sTime; /* ToDo: is this right? */
901 ent->size = fromObj ? iSize : sSize;
902 ent->oSize = fromObj ? oSize : 0;
903 ent->objLoaded = FALSE;
908 static Void nukeEnding( String s )
911 if (l > 4 && strncmp(s+l-4,".u_o" ,4)==0) s[l-4] = 0; else
912 if (l > 5 && strncmp(s+l-5,".u_hi",5)==0) s[l-5] = 0; else
913 if (l > 3 && strncmp(s+l-3,".hs" ,3)==0) s[l-3] = 0; else
914 if (l > 4 && strncmp(s+l-4,".lhs" ,4)==0) s[l-4] = 0; else
915 if (l > 4 && strncmp(s+l-4,".dll" ,4)==0) s[l-4] = 0; else
916 if (l > 4 && strncmp(s+l-4,".DLL" ,4)==0) s[l-4] = 0;
919 static Void local addStackEntry(s) /* Add script to list of scripts */
920 String s; { /* to be read in ... */
925 if (namesUpto>=NUM_SCRIPTS) {
926 ERRMSG(0) "Too many module files (maximum of %d allowed)",
933 for (s2 = s; *s2; s2++)
934 if (*s2 == SLASH && *(s2+1)) s = s2+1;
937 for (i = 0; i < namesUpto; i++)
938 if (strcmp(scriptInfo[i].modName,s)==0)
942 makeStackEntry ( &scriptInfo[namesUpto], strCopy(s) );
948 /* Return TRUE if no imports were needed; FALSE otherwise. */
949 static Bool local addScript(stacknum) /* read single file */
951 static char name[FILENAME_MAX+1];
952 Int len = scriptInfo[stacknum].size;
954 #if HUGS_FOR_WINDOWS /* Set clock cursor while loading */
956 SetCursor(LoadCursor(NULL, IDC_WAIT));
959 // setLastEdit(name,0);
962 strcpy(name, scriptInfo[stacknum].path);
963 strcat(name, scriptInfo[stacknum].modName);
964 if (scriptInfo[stacknum].fromSource)
965 strcat(name, scriptInfo[stacknum].srcExt); else
966 strcat(name, ".u_hi");
970 if (scriptInfo[stacknum].fromSource) {
971 if (lastWasObject) finishInterfaces();
972 lastWasObject = FALSE;
973 Printf("Reading script \"%s\":\n",name);
974 needsImports = FALSE;
975 parseScript(name,len);
976 if (needsImports) return FALSE;
981 Printf("Reading iface \"%s\":\n", name);
983 needsImports = FALSE;
985 // set nameObj for the benefit of openGHCIface
986 strcpy(nameObj, scriptInfo[stacknum].path);
987 strcat(nameObj, scriptInfo[stacknum].modName);
988 strcat(nameObj, DLL_ENDING);
989 sizeObj = scriptInfo[stacknum].oSize;
991 loadInterface(name,len);
993 lastWasObject = TRUE;
994 if (needsImports) return FALSE;
998 preludeLoaded = TRUE;
1003 Bool chase(imps) /* Process list of import requests */
1007 Int origPos = numScripts; /* keep track of original position */
1008 String origName = scriptInfo[origPos].modName;
1009 for (; nonNull(imps); imps=tl(imps)) {
1010 String iname = textToStr(textOf(hd(imps)));
1012 for (; i<namesUpto; i++)
1013 if (strcmp(scriptInfo[i].modName,iname)==0)
1015 //fprintf(stderr, "import name = %s num = %d\n", iname, i );
1018 /* We should have filled in the details of each module
1019 the first time we hear about it.
1021 assert(scriptInfo[i].details);
1024 if (i>=origPos) { /* Neither loaded or queued */
1030 needsImports = TRUE;
1031 if (scriptInfo[origPos].fromSource)
1032 scriptInfo[origPos].postponed = TRUE;
1034 if (i==namesUpto) { /* Name not found (i==namesUpto) */
1035 /* Find out where it lives, whether source or object, etc */
1036 makeStackEntry ( &scriptInfo[i], iname );
1040 if (scriptInfo[i].postponed && scriptInfo[i].fromSource) {
1041 /* Check for recursive dependency */
1043 "Recursive import dependency between \"%s\" and \"%s\"",
1044 scriptInfo[origPos].modName, iname
1047 /* Move stack entry i to somewhere below origPos. If i denotes
1048 * an object, destination is immediately below origPos.
1049 * Otherwise, it's underneath the queue of objects below origPos.
1051 dstPosn = origPos-1;
1052 if (scriptInfo[i].fromSource)
1053 while (!scriptInfo[dstPosn].fromSource && dstPosn > 0)
1057 tmp = scriptInfo[i];
1058 for (; i > dstPosn; i--) scriptInfo[i] = scriptInfo[i-1];
1059 scriptInfo[dstPosn] = tmp;
1060 if (dstPosn < nextNumScripts) nextNumScripts = dstPosn;
1064 return needsImports;
1067 static Void local forgetScriptsFrom(scno)/* remove scripts from system */
1071 for (i=scno; i<namesUpto; ++i)
1073 free(scriptName[i]);
1075 dropScriptsFrom(scno-1);
1077 if (numScripts>namesUpto)
1081 /* --------------------------------------------------------------------------
1082 * Commands for loading and removing script files:
1083 * ------------------------------------------------------------------------*/
1085 static Void local load() { /* read filenames from command line */
1086 String s; /* and add to list of scripts waiting */
1088 while ((s=readFilename())!=0)
1093 static Void local project() { /* read list of script names from */
1094 String s; /* project file */
1096 if ((s=readFilename()) || currProject) {
1098 s = strCopy(currProject);
1099 else if (readFilename()) {
1100 ERRMSG(0) "Too many project files"
1107 ERRMSG(0) "No project filename specified"
1114 static Void local readScripts(n) /* Reread current list of scripts, */
1115 Int n; { /* loading everything after and */
1116 Time timeStamp; /* including the first script which*/
1117 Long fileSize; /* has been either changed or added*/
1118 static char name[FILENAME_MAX+1];
1120 lastWasObject = FALSE;
1121 ppSmStack("readscripts-begin");
1122 #if HUGS_FOR_WINDOWS
1123 SetCursor(LoadCursor(NULL, IDC_WAIT));
1127 for (; n<numScripts; n++) { /* Scan previously loaded scripts */
1128 ppSmStack("readscripts-loop1");
1129 getFileInfo(scriptName[n], &timeStamp, &fileSize);
1130 if (timeChanged(timeStamp,lastChange[n])) {
1131 dropScriptsFrom(n-1);
1136 for (; n<NUM_SCRIPTS; n++) /* No scripts have been postponed */
1137 postponed[n] = FALSE; /* at this stage */
1140 while (numScripts<namesUpto) { /* Process any remaining scripts */
1141 ppSmStack("readscripts-loop2");
1142 getFileInfo(scriptName[numScripts], &timeStamp, &fileSize);
1143 timeSet(lastChange[numScripts],timeStamp);
1144 if (numScripts>0) /* no new script for prelude */
1145 startNewScript(scriptName[numScripts]);
1146 if (addScript(scriptName[numScripts],fileSize))
1149 dropScriptsFrom(numScripts-1);
1155 for (; n<numScripts; n++) {
1156 ppSmStack("readscripts-loop2");
1157 strcpy(name, scriptInfo[n].path);
1158 strcat(name, scriptInfo[n].modName);
1159 if (scriptInfo[n].fromSource)
1160 strcat(name, scriptInfo[n].srcExt); else
1161 strcat(name, ".u_hi"); //ToDo: should be .o
1162 getFileInfo(name,&timeStamp, &fileSize);
1163 if (timeChanged(timeStamp,scriptInfo[n].lastChange)) {
1164 dropScriptsFrom(n-1);
1169 for (; n<NUM_SCRIPTS; n++)
1170 scriptInfo[n].postponed = FALSE;
1174 while (numScripts < namesUpto) {
1175 ppSmStack ( "readscripts-loop2" );
1177 if (scriptInfo[numScripts].fromSource) {
1180 startNewScript(scriptInfo[numScripts].modName);
1181 nextNumScripts = NUM_SCRIPTS; //bogus initialisation
1182 if (addScript(numScripts)) {
1184 assert(nextNumScripts==NUM_SCRIPTS);
1187 dropScriptsFrom(numScripts-1);
1191 if (scriptInfo[numScripts].objLoaded) {
1194 scriptInfo[numScripts].objLoaded = TRUE;
1197 startNewScript(scriptInfo[numScripts].modName);
1199 nextNumScripts = NUM_SCRIPTS;
1200 if (addScript(numScripts)) {
1202 assert(nextNumScripts==NUM_SCRIPTS);
1204 //while (!scriptInfo[numScripts].fromSource && numScripts > 0)
1206 //if (scriptInfo[numScripts].fromSource)
1208 numScripts = nextNumScripts;
1209 assert(nextNumScripts<NUM_SCRIPTS);
1213 if (numScripts==namesUpto) ppSmStack( "readscripts-final") ;
1218 { Int m = namesUpto-1;
1219 Text mtext = findText(scriptInfo[m].modName);
1220 /* Commented out till we understand what
1221 * this is trying to do.
1222 * Problem, you cant find a module till later.
1225 setCurrModule(findModule(mtext));
1235 setLastEdit((String)0, 0);
1236 ppSmStack("readscripts-end ");
1239 static Void local whatScripts() { /* list scripts in current session */
1241 Printf("\nHugs session for:");
1243 Printf(" (project: %s)",currProject);
1244 for (i=0; i<numScripts; ++i)
1245 Printf("\n%s%s",scriptInfo[i].path, scriptInfo[i].modName);
1249 /* --------------------------------------------------------------------------
1250 * Access to external editor:
1251 * ------------------------------------------------------------------------*/
1253 static Void local editor() { /* interpreter-editor interface */
1254 String newFile = readFilename();
1256 setLastEdit(newFile,0);
1257 if (readFilename()) {
1258 ERRMSG(0) "Multiple filenames not permitted"
1265 static Void local find() { /* edit file containing definition */
1267 This just plain wont work no more.
1269 String nm = readFilename(); /* of specified name */
1271 ERRMSG(0) "No name specified"
1274 else if (readFilename()) {
1275 ERRMSG(0) "Multiple names not permitted"
1281 setCurrModule(findEvalModule());
1283 if (nonNull(c=findTycon(t=findText(nm)))) {
1284 if (startEdit(tycon(c).line,scriptName[scriptThisTycon(c)])) {
1287 } else if (nonNull(c=findName(t))) {
1288 if (startEdit(name(c).line,scriptName[scriptThisName(c)])) {
1292 ERRMSG(0) "No current definition for name \"%s\"", nm
1299 static Void local runEditor() { /* run editor on script lastEdit */
1300 if (startEdit(lastEdLine,lastEdit)) /* at line lastEdLine */
1304 static Void local setLastEdit(fname,line)/* keep name of last file to edit */
1309 lastEdit = strCopy(fname);
1311 #if HUGS_FOR_WINDOWS
1312 DrawStatusLine(hWndMain); /* Redo status line */
1316 /* --------------------------------------------------------------------------
1317 * Read and evaluate an expression:
1318 * ------------------------------------------------------------------------*/
1320 static Void local setModule(){/*set module in which to evaluate expressions*/
1321 String s = readFilename();
1322 if (!s) s = ""; /* :m clears the current module selection */
1323 evalModule = findText(s);
1324 setLastEdit(fileOfModule(findEvalModule()),0);
1327 static Module local findEvalModule() { /*Module in which to eval expressions*/
1328 Module m = findModule(evalModule);
1334 static Void local evaluator() { /* evaluate expr and print value */
1338 setCurrModule(findEvalModule());
1340 startNewScript(0); /* Enables recovery of storage */
1341 /* allocated during evaluation */
1344 defaultDefns = evalDefaults;
1345 type = typeCheckExp(TRUE);
1346 if (isPolyType(type)) {
1347 ks = polySigOf(type);
1348 bd = monotypeOf(type);
1353 if (whatIs(bd)==QUAL) {
1354 ERRMSG(0) "Unresolved overloading" ETHEN
1355 ERRTEXT "\n*** Type : " ETHEN ERRTYPE(type);
1356 ERRTEXT "\n*** Expression : " ETHEN ERREXPR(inputExpr);
1366 if (isProgType(ks,bd)) {
1367 inputExpr = ap(nameRunIO,inputExpr);
1371 Cell d = provePred(ks,NIL,ap(classShow,bd));
1373 ERRMSG(0) "Cannot find \"show\" function for:" ETHEN
1374 ERRTEXT "\n*** expression : " ETHEN ERREXPR(inputExpr);
1375 ERRTEXT "\n*** of type : " ETHEN ERRTYPE(type);
1379 inputExpr = ap2(findName(findText("show")),d,inputExpr);
1380 inputExpr = ap(findName(findText("putStr")), inputExpr);
1381 inputExpr = ap(nameRunIO, inputExpr);
1383 evalExp(); printf("\n");
1386 printType(stdout,type);
1393 printf ( "result type is " );
1394 printType ( stdout, type );
1403 static Void local stopAnyPrinting() { /* terminate printing of expression,*/
1404 if (printing) { /* after successful termination or */
1405 printing = FALSE; /* runtime error (e.g. interrupt) */
1408 #define plural(v) v, (v==1?"":"s")
1409 Printf("%lu cell%s",plural(numCells));
1411 Printf(", %u garbage collection%s",plural(numGcs));
1420 /* --------------------------------------------------------------------------
1421 * Print type of input expression:
1422 * ------------------------------------------------------------------------*/
1424 static Void local showtype() { /* print type of expression (if any)*/
1427 setCurrModule(findEvalModule());
1428 startNewScript(0); /* Enables recovery of storage */
1429 /* allocated during evaluation */
1432 defaultDefns = evalDefaults;
1433 type = typeCheckExp(FALSE);
1434 printExp(stdout,inputExpr);
1436 printType(stdout,type);
1441 static Void local browseit(mod,t,all)
1448 Printf("module %s where\n",textToStr(module(mod).text));
1449 for (cs = module(mod).names; nonNull(cs); cs=tl(cs)) {
1451 /* only look at things defined in this module,
1452 unless `all' flag is set */
1453 if (all || name(nm).mod == mod) {
1454 /* unwanted artifacts, like lambda lifted values,
1455 are in the list of names, but have no types */
1456 if (nonNull(name(nm).type)) {
1457 printExp(stdout,nm);
1459 printType(stdout,name(nm).type);
1461 Printf(" -- data constructor");
1462 } else if (isMfun(nm)) {
1463 Printf(" -- class member");
1464 } else if (isSfun(nm)) {
1465 Printf(" -- selector function");
1473 Printf("Unknown module %s\n",t);
1478 static Void local browse() { /* browse modules */
1479 Int count = 0; /* or give menu of commands */
1483 setCurrModule(findEvalModule());
1484 startNewScript(0); /* for recovery of storage */
1485 for (; (s=readFilename())!=0; count++)
1486 if (strcmp(s,"all") == 0) {
1490 browseit(findModule(findText(s)),s,all);
1492 browseit(findEvalModule(),NULL,all);
1496 #if EXPLAIN_INSTANCE_RESOLUTION
1497 static Void local xplain() { /* print type of expression (if any)*/
1499 Bool sir = showInstRes;
1501 setCurrModule(findEvalModule());
1502 startNewScript(0); /* Enables recovery of storage */
1503 /* allocated during evaluation */
1507 d = provePred(NIL,NIL,hd(inputContext));
1509 fprintf(stdout, "not Sat\n");
1511 fprintf(stdout, "Sat\n");
1517 /* --------------------------------------------------------------------------
1518 * Enhanced help system: print current list of scripts or give information
1520 * ------------------------------------------------------------------------*/
1522 static String local objToStr(m,c)
1525 #if 1 || DISPLAY_QUANTIFIERS
1526 static char newVar[60];
1527 switch (whatIs(c)) {
1528 case NAME : if (m == name(c).mod) {
1529 sprintf(newVar,"%s", textToStr(name(c).text));
1531 sprintf(newVar,"%s.%s",
1532 textToStr(module(name(c).mod).text),
1533 textToStr(name(c).text));
1537 case TYCON : if (m == tycon(c).mod) {
1538 sprintf(newVar,"%s", textToStr(tycon(c).text));
1540 sprintf(newVar,"%s.%s",
1541 textToStr(module(tycon(c).mod).text),
1542 textToStr(tycon(c).text));
1546 case CLASS : if (m == cclass(c).mod) {
1547 sprintf(newVar,"%s", textToStr(cclass(c).text));
1549 sprintf(newVar,"%s.%s",
1550 textToStr(module(cclass(c).mod).text),
1551 textToStr(cclass(c).text));
1555 default : internal("objToStr");
1559 static char newVar[33];
1560 switch (whatIs(c)) {
1561 case NAME : sprintf(newVar,"%s", textToStr(name(c).text));
1564 case TYCON : sprintf(newVar,"%s", textToStr(tycon(c).text));
1567 case CLASS : sprintf(newVar,"%s", textToStr(cclass(c).text));
1570 default : internal("objToStr");
1578 static Void local dumpStg( void ) { /* print STG stuff */
1583 Cell v; /* really StgVar */
1584 setCurrModule(findEvalModule());
1586 for (; (s=readFilename())!=0;) {
1589 /* find the name while ignoring module scopes */
1590 for (i=NAMEMIN; i<nameHw; i++)
1591 if (name(i).text == t) n = i;
1593 /* perhaps it's an "idNNNNNN" thing? */
1596 s[0]=='i' && s[1]=='d' && isdigit(s[2])) {
1599 while (isdigit(s[i])) {
1600 v = v * 10 + (s[i]-'0');
1604 n = nameFromStgVar(v);
1607 if (isNull(n) && whatIs(v)==STGVAR) {
1608 Printf ( "\n{- `%s' has no nametable entry -}\n", s );
1609 printStg(stderr, v );
1612 Printf ( "Unknown reference `%s'\n", s );
1615 Printf ( "Not a Name: `%s'\n", s );
1617 if (isNull(name(n).stgVar)) {
1618 Printf ( "Doesn't have a STG tree: %s\n", s );
1620 Printf ( "\n{- stgVar of `%s' is id%d -}\n", s, -name(n).stgVar);
1621 printStg(stderr, name(n).stgVar);
1626 static Void local info() { /* describe objects */
1627 Int count = 0; /* or give menu of commands */
1630 setCurrModule(findEvalModule());
1631 startNewScript(0); /* for recovery of storage */
1632 for (; (s=readFilename())!=0; count++) {
1633 describe(findText(s));
1641 static Void local describe(t) /* describe an object */
1643 Tycon tc = findTycon(t);
1644 Class cl = findClass(t);
1645 Name nm = findName(t);
1647 if (nonNull(tc)) { /* as a type constructor */
1651 for (i=0; i<tycon(tc).arity; ++i) {
1652 t = ap(t,mkOffset(i));
1654 Printf("-- type constructor");
1656 Printf(" with kind ");
1657 printKind(stdout,tycon(tc).kind);
1660 switch (tycon(tc).what) {
1661 case SYNONYM : Printf("type ");
1662 printType(stdout,t);
1664 printType(stdout,tycon(tc).defn);
1668 case DATATYPE : { List cs = tycon(tc).defn;
1669 if (tycon(tc).what==DATATYPE) {
1674 printType(stdout,t);
1676 mapProc(printSyntax,cs);
1678 Printf("\n-- constructors:");
1680 for (; hasCfun(cs); cs=tl(cs)) {
1682 printExp(stdout,hd(cs));
1684 printType(stdout,name(hd(cs)).type);
1687 Printf("\n-- selectors:");
1689 for (; nonNull(cs); cs=tl(cs)) {
1691 printExp(stdout,hd(cs));
1693 printType(stdout,name(hd(cs)).type);
1698 case RESTRICTSYN : Printf("type ");
1699 printType(stdout,t);
1700 Printf(" = <restricted>");
1704 if (nonNull(in=findFirstInst(tc))) {
1705 Printf("\n-- instances:\n");
1708 in = findNextInst(tc,in);
1709 } while (nonNull(in));
1714 if (nonNull(cl)) { /* as a class */
1715 List ins = cclass(cl).instances;
1716 Kinds ks = cclass(cl).kinds;
1717 if (nonNull(ks) && isNull(tl(ks)) && hd(ks)==STAR) {
1718 Printf("-- type class");
1720 Printf("-- constructor class");
1722 Printf(" with arity ");
1723 printKinds(stdout,ks);
1727 mapProc(printSyntax,cclass(cl).members);
1729 if (nonNull(cclass(cl).supers)) {
1730 printContext(stdout,cclass(cl).supers);
1733 printPred(stdout,cclass(cl).head);
1735 if (nonNull(cclass(cl).fds)) {
1736 List fds = cclass(cl).fds;
1738 for (; nonNull(fds); fds=tl(fds)) {
1740 printFD(stdout,hd(fds));
1745 if (nonNull(cclass(cl).members)) {
1746 List ms = cclass(cl).members;
1749 Type t = name(hd(ms)).type;
1750 if (isPolyType(t)) {
1754 printExp(stdout,hd(ms));
1756 if (isNull(tl(fst(snd(t))))) {
1759 t = ap(QUAL,pair(tl(fst(snd(t))),snd(snd(t))));
1761 printType(stdout,t);
1763 } while (nonNull(ms));
1767 Printf("\n-- instances:\n");
1771 } while (nonNull(ins));
1776 if (nonNull(nm)) { /* as a function/name */
1778 printExp(stdout,nm);
1780 if (nonNull(name(nm).type)) {
1781 printType(stdout,name(nm).type);
1783 Printf("<unknown type>");
1787 Printf(" -- data constructor");
1788 } else if (isMfun(nm)) {
1789 Printf(" -- class member");
1790 } else if (isSfun(nm)) {
1791 Printf(" -- selector function");
1797 if (isNull(tc) && isNull(cl) && isNull(nm)) {
1798 Printf("Unknown reference `%s'\n",textToStr(t));
1802 static Void local printSyntax(nm)
1804 Syntax sy = syntaxOf(nm);
1805 Text t = name(nm).text;
1806 String s = textToStr(t);
1807 if (sy != defaultSyntax(t)) {
1809 switch (assocOf(sy)) {
1810 case LEFT_ASS : Putchar('l'); break;
1811 case RIGHT_ASS : Putchar('r'); break;
1812 case NON_ASS : break;
1814 Printf(" %i ",precOf(sy));
1815 if (isascii((int)(*s)) && isalpha((int)(*s))) {
1824 static Void local showInst(in) /* Display instance decl header */
1826 Printf("instance ");
1827 if (nonNull(inst(in).specifics)) {
1828 printContext(stdout,inst(in).specifics);
1831 printPred(stdout,inst(in).head);
1835 /* --------------------------------------------------------------------------
1836 * List all names currently in scope:
1837 * ------------------------------------------------------------------------*/
1839 static Void local listNames() { /* list names matching optional pat*/
1840 String pat = readFilename();
1842 Int width = getTerminalWidth() - 1;
1845 Module mod = findEvalModule();
1847 if (pat) { /* First gather names to list */
1849 names = addNamesMatching(pat,names);
1850 } while ((pat=readFilename())!=0);
1852 names = addNamesMatching((String)0,names);
1854 if (isNull(names)) { /* Then print them out */
1855 ERRMSG(0) "No names selected"
1858 for (termPos=0; nonNull(names); names=tl(names)) {
1859 String s = objToStr(mod,hd(names));
1861 if (termPos+1+l>width) {
1864 } else if (termPos>0) {
1872 Printf("\n(%d names listed)\n", count);
1875 /* --------------------------------------------------------------------------
1876 * print a prompt and read a line of input:
1877 * ------------------------------------------------------------------------*/
1879 static Void local promptForInput(moduleName)
1880 String moduleName; {
1881 char promptBuffer[1000];
1883 /* This is portable but could overflow buffer */
1884 sprintf(promptBuffer,prompt,moduleName);
1886 /* Works on ANSI C - but pre-ANSI compilers return a pointer to
1887 * promptBuffer instead.
1889 if (sprintf(promptBuffer,prompt,moduleName) >= 1000) {
1890 /* Reset prompt to a safe default to avoid an infinite loop */
1892 prompt = strCopy("? ");
1893 internal("Combined prompt and evaluation module name too long");
1897 stringInput("main\0"); else
1898 consoleInput(promptBuffer);
1901 /* --------------------------------------------------------------------------
1902 * main read-eval-print loop, with error trapping:
1903 * ------------------------------------------------------------------------*/
1905 static jmp_buf catch_error; /* jump buffer for error trapping */
1907 static Void local interpreter(argc,argv)/* main interpreter loop */
1910 Int errorNumber = setjmp(catch_error);
1912 if (errorNumber && autoMain) {
1913 fprintf(stderr, "hugs +Q: compilation failed -- can't run `main'\n" );
1917 breakOn(TRUE); /* enable break trapping */
1918 if (numScripts==0) { /* only succeeds on first time, */
1919 if (errorNumber) /* before prelude has been loaded */
1920 fatal("Unable to load prelude");
1921 initialize(argc,argv);
1925 /* initialize calls startupHaskell, which trashes our signal handlers */
1930 everybody(RESET); /* reset to sensible initial state */
1931 dropScriptsFrom(numScripts-1); /* remove partially loaded scripts */
1932 /* not counting prelude as a script*/
1934 promptForInput(textToStr(module(findEvalModule()).text));
1936 cmd = readCommand(cmds, (Char)':', (Char)'!');
1941 case EDIT : editor();
1945 case LOAD : clearProject();
1946 forgetScriptsFrom(1);
1949 case ALSO : clearProject();
1950 forgetScriptsFrom(numScripts);
1953 case RELOAD : readScripts(1);
1955 case PROJECT: project();
1960 case EVAL : evaluator();
1962 case TYPEOF : showtype();
1964 case BROWSE : browse();
1966 #if EXPLAIN_INSTANCE_RESOLUTION
1967 case XPLAIN : xplain();
1970 case NAMES : listNames();
1974 case BADCMD : guidance();
1979 #ifdef CRUDE_PROFILING
1983 case SYSTEM : if (shellEsc(readLine()))
1984 Printf("Warning: Shell escape terminated abnormally\n");
1986 case CHGDIR : changeDir();
1990 case PNTVER: Printf("-- Hugs Version %s\n",
1993 case DUMP : dumpStg();
1996 case COLLECT: consGC = FALSE;
1999 Printf("Garbage collection recovered %d cells\n",
2006 Printf("Elapsed time (ms): %ld (user), %ld (system)\n",
2007 millisecs(userElapsed), millisecs(systElapsed));
2009 if (autoMain) break;
2014 /* --------------------------------------------------------------------------
2015 * Display progress towards goal:
2016 * ------------------------------------------------------------------------*/
2018 static Target currTarget;
2019 static Bool aiming = FALSE;
2022 static Int charCount;
2024 Void setGoal(what, t) /* Set goal for what to be t */
2029 #if EXPLAIN_INSTANCE_RESOLUTION
2033 currTarget = (t?t:1);
2036 currPos = strlen(what);
2037 maxPos = getTerminalWidth() - 1;
2041 for (charCount=0; *what; charCount++)
2046 Void soFar(t) /* Indicate progress towards goal */
2047 Target t; { /* has now reached t */
2050 #if EXPLAIN_INSTANCE_RESOLUTION
2055 Int newPos = (Int)((maxPos * ((long)t))/currTarget);
2060 if (newPos>currPos) {
2063 while (newPos>++currPos);
2070 Void done() { /* Goal has now been achieved */
2073 #if EXPLAIN_INSTANCE_RESOLUTION
2078 while (maxPos>currPos++)
2083 for (; charCount>0; charCount--) {
2092 static Void local failed() { /* Goal cannot be reached due to */
2093 if (aiming) { /* errors */
2100 /* --------------------------------------------------------------------------
2102 * ------------------------------------------------------------------------*/
2104 Void errHead(l) /* print start of error message */
2106 failed(); /* failed to reach target ... */
2108 FPrintf(errorStream,"ERROR");
2111 FPrintf(errorStream," \"%s\"", scriptFile);
2112 setLastEdit(scriptFile,l);
2113 if (l) FPrintf(errorStream," (line %d)",l);
2116 FPrintf(errorStream,": ");
2117 FFlush(errorStream);
2120 Void errFail() { /* terminate error message and */
2121 Putc('\n',errorStream); /* produce exception to return to */
2122 FFlush(errorStream); /* main command loop */
2123 longjmp(catch_error,1);
2126 Void errAbort() { /* altern. form of error handling */
2127 failed(); /* used when suitable error message*/
2128 stopAnyPrinting(); /* has already been printed */
2132 Void internal(msg) /* handle internal error */
2134 #if HUGS_FOR_WINDOWS
2136 wsprintf(buf,"INTERNAL ERROR: %s",msg);
2137 MessageBox(hWndMain, buf, appName, MB_ICONHAND | MB_OK);
2141 Printf("INTERNAL ERROR: %s\n",msg);
2143 longjmp(catch_error,1);
2146 Void fatal(msg) /* handle fatal error */
2148 #if HUGS_FOR_WINDOWS
2150 wsprintf(buf,"FATAL ERROR: %s",msg);
2151 MessageBox(hWndMain, buf, appName, MB_ICONHAND | MB_OK);
2154 Printf("\nFATAL ERROR: %s\n",msg);
2159 sigHandler(breakHandler) { /* respond to break interrupt */
2160 #if HUGS_FOR_WINDOWS
2161 MessageBox(GetFocus(), "Interrupted!", appName, MB_ICONSTOP | MB_OK);
2164 Printf("{Interrupted!}\n");
2166 breakOn(TRUE); /* reinstall signal handler - redundant on BSD systems */
2167 /* but essential on POSIX (and other?) systems */
2173 longjmp(catch_error,1);
2174 sigResume;/*NOTREACHED*/
2177 /* --------------------------------------------------------------------------
2178 * Read value from environment variable or registry:
2179 * ------------------------------------------------------------------------*/
2181 String fromEnv(var,def) /* return value of: */
2182 String var; /* environment variable named by var */
2183 String def; { /* or: default value given by def */
2184 String s = getenv(var);
2185 return (s ? s : def);
2188 /* --------------------------------------------------------------------------
2189 * String manipulation routines:
2190 * ------------------------------------------------------------------------*/
2192 static String local strCopy(s) /* make malloced copy of a string */
2196 if ((t=(char *)malloc(strlen(s)+1))==0) {
2197 ERRMSG(0) "String storage space exhausted"
2200 for (r=t; (*r++ = *s++)!=0; ) {
2207 /* --------------------------------------------------------------------------
2209 * We can redirect compiler output (prompts, error messages, etc) by
2210 * tweaking these functions.
2211 * ------------------------------------------------------------------------*/
2213 #if REDIRECT_OUTPUT && !HUGS_FOR_WINDOWS
2215 #ifdef HAVE_STDARG_H
2218 #include <varargs.h>
2221 /* ----------------------------------------------------------------------- */
2223 #define BufferSize 10000 /* size of redirected output buffer */
2225 typedef struct _HugsStream {
2226 char buffer[BufferSize]; /* buffer for redirected output */
2227 Int next; /* next space in buffer */
2230 static Void local vBufferedPrintf Args((HugsStream*, const char*, va_list));
2231 static Void local bufferedPutchar Args((HugsStream*, Char));
2232 static String local bufferClear Args((HugsStream *stream));
2234 static Void local vBufferedPrintf(stream, fmt, ap)
2238 Int spaceLeft = BufferSize - stream->next;
2239 char* p = &stream->buffer[stream->next];
2240 Int charsAdded = vsnprintf(p, spaceLeft, fmt, ap);
2241 if (0 <= charsAdded && charsAdded < spaceLeft)
2242 stream->next += charsAdded;
2243 #if 1 /* we can either buffer the first n chars or buffer the last n chars */
2249 static Void local bufferedPutchar(stream, c)
2252 if (BufferSize - stream->next >= 2) {
2253 stream->buffer[stream->next++] = c;
2254 stream->buffer[stream->next] = '\0';
2258 static String local bufferClear(stream)
2259 HugsStream *stream; {
2260 if (stream->next == 0) {
2264 return stream->buffer;
2268 /* ----------------------------------------------------------------------- */
2270 static HugsStream outputStreamH;
2272 * We rely on standard C semantics to initialise outputStreamH.next to 0.
2275 Void hugsEnableOutput(f)
2280 String hugsClearOutputBuffer() {
2281 return bufferClear(&outputStreamH);
2284 #ifdef HAVE_STDARG_H
2285 Void hugsPrintf(const char *fmt, ...) {
2286 va_list ap; /* pointer into argument list */
2287 va_start(ap, fmt); /* make ap point to first arg after fmt */
2288 if (!disableOutput) {
2291 vBufferedPrintf(&outputStreamH, fmt, ap);
2293 va_end(ap); /* clean up */
2296 Void hugsPrintf(fmt, va_alist)
2299 va_list ap; /* pointer into argument list */
2300 va_start(ap); /* make ap point to first arg after fmt */
2301 if (!disableOutput) {
2304 vBufferedPrintf(&outputStreamH, fmt, ap);
2306 va_end(ap); /* clean up */
2312 if (!disableOutput) {
2315 bufferedPutchar(&outputStreamH, c);
2319 Void hugsFlushStdout() {
2320 if (!disableOutput) {
2327 if (!disableOutput) {
2332 #ifdef HAVE_STDARG_H
2333 Void hugsFPrintf(FILE *fp, const char* fmt, ...) {
2336 if (!disableOutput) {
2337 vfprintf(fp, fmt, ap);
2339 vBufferedPrintf(&outputStreamH, fmt, ap);
2344 Void hugsFPrintf(FILE *fp, const char* fmt, va_list)
2350 if (!disableOutput) {
2351 vfprintf(fp, fmt, ap);
2353 vBufferedPrintf(&outputStreamH, fmt, ap);
2359 Void hugsPutc(c, fp)
2362 if (!disableOutput) {
2365 bufferedPutchar(&outputStreamH, c);
2369 #endif /* REDIRECT_OUTPUT && !HUGS_FOR_WINDOWS */
2370 /* --------------------------------------------------------------------------
2371 * Send message to each component of system:
2372 * ------------------------------------------------------------------------*/
2374 Void everybody(what) /* send command `what' to each component of*/
2375 Int what; { /* system to respond as appropriate ... */
2376 machdep(what); /* The order of calling each component is */
2377 storage(what); /* important for the INSTALL command */
2380 translateControl(what);
2382 staticAnalysis(what);
2383 deriveControl(what);
2389 /* --------------------------------------------------------------------------
2390 * Hugs for Windows code (WinMain and related functions)
2391 * ------------------------------------------------------------------------*/
2393 #if HUGS_FOR_WINDOWS
2394 #include "winhugs.c"