--		Copyright 1994-2000 by Daniel R. Grayson

newStartupMethod := true;				    -- for testing purposes
use evaluate;
use parser;
use texmacs;
use actors5;

import dirname(s:string):string;

dummyError := Error(dummyPosition,"dummy error message",nullE,false,dummyFrame);

export setupargv():void := (
     setupconst("commandLine",toExpr(argv));
     setupconst("environment",toExpr(envp));
     );

fileExitHooks := setupvar("fileExitHooks", Expr(emptyList));
currentFileName := setupvar("currentFileName", nullE);
currentPosFile  := dummyPosFile;
currentFileDirectory := setupvar("currentFileDirectory", toExpr("./"));
update(err:Error,prefix:string,f:Code):Error := (
     if !err.printed
     then printErrorMessage0(f,prefix + ": " + err.message)
     else printErrorMessage0(f,prefix + ": --backtrace update-- ")
     );
previousLineNumber := -1;

BeforeEval := makeProtectedSymbolClosure("BeforeEval");
AfterEval := makeProtectedSymbolClosure("AfterEval");
BeforePrint := makeProtectedSymbolClosure("BeforePrint");
Print := makeProtectedSymbolClosure("Print");
NoPrint := makeProtectedSymbolClosure("NoPrint");
AfterPrint := makeProtectedSymbolClosure("AfterPrint");
AfterNoPrint := makeProtectedSymbolClosure("AfterNoPrint");
runmethod(methodname:SymbolClosure,g:Expr):Expr := (
     method := lookup(Class(g),methodname);
     if method == nullE then g else applyEE(method,g)
     );
runmethod(methodname:Expr,g:Expr):Expr := (
     method := lookup(Class(g),methodname);
     if method == nullE then g else applyEE(method,g)
     );

endInput := makeProtectedSymbolClosure("end");

-- PrintOut(g:Expr,semi:bool,f:Code):Expr := (
--      methodname := if semi then NoPrint else Print;
--      method := lookup(Class(g),methodname);
--      if method == nullE 
--      then printErrorMessageE(f,"no method for '" + methodname.symbol.word.name + "'")
--      else applyEE(method,g)
--      );

readeval4(file:TokenFile,printout:bool,dictionary:Dictionary,returnLastvalue:bool,stopIfBreakReturnContinue:bool,returnIfError:bool):Expr := (
     lastvalue := nullE;
     mode := topLevelMode;
     modeBeforePrint := list(mode,Expr(BeforePrint));
     modeNoPrint := list(mode,Expr(NoPrint));
     modePrint := list(mode,Expr(Print));
     modeAfterNoPrint := list(mode,Expr(AfterNoPrint));
     modeAfterPrint := list(mode,Expr(AfterPrint));
     bumpLineNumber := true;
     promptWanted := false;
     issuePrompt := false;
     lasterrmsg := dummyError;
     while true do (
	  if debugLevel == 123 then stderr <<  "------------ top of loop" << endl;
	  if bumpLineNumber then (
	       if debugLevel == 123 then stderr <<  "-- bumpLineNumber" << endl;
     	       if printout then setLineNumber(lineNumber + 1);
	       bumpLineNumber = false;
	       );
	  if promptWanted then (
	       if debugLevel == 123 then stderr <<  "-- promptWanted" << endl;
     	       previousLineNumber = -1;	-- to force a prompt at the beginning of the next input line
	       promptWanted = false;
	       );
	  if issuePrompt then (
	       if debugLevel == 123 then stderr <<  "-- issuePrompt" << endl;
	       previousLineNumber = -1;
	       stdIO << file.posFile.file.prompt();
	       issuePrompt = false;
	       );
	  clearAllFlags();
	  if debugLevel == 123 then (
	       stderr << "-- file: " << file.posFile.filename << ":" << file.posFile.line << ":" << file.posFile.column << newline;
	       c := peek(file.posFile.file);
	       stderr << "-- next character: ";
	       if c == int('\n') then stderr << "NEWLINE" else if c >= 0 then stderr << char(c) else stderr << c;
	       stderr << endl;
	       );
	  u := peektoken(file,true);
	  interruptPending = false; determineExceptionFlag();
	  if u == errorToken || test(interruptedFlag) then (
	       gettoken(file,true);
	       if test(interruptedFlag) then (
		    if debugLevel == 123 then stderr <<  "-- token read interrupted" << endl;
		    clearFileError(file);
	       	    store(interruptedFlag, false);
		    determineExceptionFlag();
		    promptWanted = true;
		    if !file.posFile.file.readline then issuePrompt = true; -- I'm not sure why this works, but it does!  Assigning always leads to an extra prompt when readline is being used in a terminal window.
		    )
	       else (
		    if debugLevel == 123 then stderr <<  "-- token read error" << endl;
		    promptWanted = true;
	       	    if fileError(file) then return buildErrorPacket(fileErrorMessage(file));
	       	    if stopIfError || returnIfError then return buildErrorPacket("--backtrace: token read error--");
		    if isatty(file) || file.posFile.file.fulllines then flush(file);
		    )
	       )
	  else (
	       t := u.word;
	       if t == wordEOF then (
		    if debugLevel == 123 then stderr <<  "-- EOF token, returning: " << position(u) << endl;
		    return if returnLastvalue then lastvalue else nullE;
		    )
	       else if t == NewlineW then (
		    if debugLevel == 123 then stderr <<  "-- newline token, discarding: " << position(u) << endl;
		    gettoken(file,true);
		    )
	       else if t == wordEOC then (
		    if debugLevel == 123 then stderr <<  "-- end-of-cell token, discarding: " << position(u) << endl;
		    gettoken(file,true);
		    )
	       else (
	  	    previousLineNumber = lineNumber;
		    promptWanted = true;
		    if debugLevel == 123 then stderr <<  "-- ordinary token, ready to parse: " << position(u) << endl;
		    parsed := parse(file,SemicolonW.parse.precedence,true);
		    if parsed == errorTree then (
			 if test(interruptedFlag) then (
		    	      if debugLevel == 123 then stderr <<  "-- parsing interrupted" << endl;
		    	      clearFileError(file);
	       	    	      store(interruptedFlag, false);
			      determineExceptionFlag();
			      promptWanted = true;
			      -- issuePrompt = true;
			      )
			 else (
		    	      if debugLevel == 123 then stderr <<  "-- error during parsing" << endl;
			      if fileError(file) then return buildErrorPacket(fileErrorMessage(file));
			      if stopIfError || returnIfError then return buildErrorPacket("--backtrace: parse error--");
			      );
			 )
		    else (
			 if debugLevel == 123 then (
			      stderr
			      << "-- parsing successful" << newline
			      << "-- parse tree size: " << size(parsed) << endl;
			      );
     	       	    	 bumpLineNumber = true;
			 -- { [ (
			 -- get the token that terminated the parsing of the expression
			 -- it has parsing precedence at most that of the semicolon
			 -- so it is end of file, end of cell, newline, semicolon, or one of the right parentheses : ) ] } 
			 -- that explains the next error message
			 s := gettoken(file,true);
			 if !(s.word == SemicolonW || s.word == NewlineW || s.word == wordEOC || s.word == wordEOF)
			 then (
			      msg := "syntax error: unmatched " + s.word.name;
			      printErrorMessage(s,msg);
			      if stopIfError || returnIfError then return Expr(Error(position(s),msg,nullE,false,dummyFrame));
			      )
			 else (
			      if localBind(parsed,dictionary) -- assign scopes to tokens, look up symbols; returns false iff an error occurred
			      then (
				   -- result of BeforeEval is ignored unless error:
				   -- BeforeEval method is independent of mode
				   f := convert(parsed); -- convert to runnable code
				   be := runmethod(BeforeEval,nullE);
				   when be is err:Error do (
					err = update(err,"before eval",f);
					if stopIfError || returnIfError then return Expr(err);
					lasterrmsg = err;
					)
				   else nothing;
				   lastvalue = evalexcept(f);	  -- run it
				   if lastvalue == endInput then return nullE;
				   when lastvalue is err:Error do (
					if err.message == returnMessage
					|| err.message == continueMessage || err.message == continueMessageWithArg 
					|| err.message == stepMessage || err.message == stepMessageWithArg 
					|| err.message == breakMessage || err.message == throwMessage then (
					     if stopIfBreakReturnContinue then return lastvalue;
					     );
					if err.message == unwindMessage then (
					     lastvalue = nullE;
					     )
					else (
					     if !err.printed then printErrorMessage(err);
					     if stopIfError || returnIfError then return lastvalue;
					     );
					lasterrmsg = err;
					)
				   else (
					if printout then (
					     if mode != topLevelMode then (
						  mode = topLevelMode;
						  modeBeforePrint = list(mode,Expr(BeforePrint));
						  modeNoPrint = list(mode,Expr(NoPrint));
						  modePrint = list(mode,Expr(Print));
						  modeAfterNoPrint = list(mode,Expr(AfterNoPrint));
						  modeAfterPrint = list(mode,Expr(AfterPrint));
						  );
					     -- result of AfterEval replaces lastvalue unless error, in which case 'null' replaces it:
					     g := runmethod(AfterEval,lastvalue);
					     when g is err:Error
					     do (
						  err = update(err,"after eval",f); 
						  if stopIfError || returnIfError then return err;
						  lastvalue = nullE;
						  lasterrmsg = err;
						  ) 
					     else lastvalue = g;
					     -- result of BeforePrint is printed instead unless error:
					     printvalue := nullE;
					     g = runmethod(modeBeforePrint,lastvalue);
					     when g is err:Error
					     do (
						  err = update(err,"before print",f);
						  if stopIfError || returnIfError then return err;
						  lasterrmsg = err;
						  )
					     else printvalue = g;
					     -- result of Print is ignored:
					     g = runmethod(if s.word == SemicolonW then modeNoPrint else modePrint,printvalue);
					     when g is err:Error do (
						  err = update(err,"at print",f);
						  if stopIfError || returnIfError then return err;
						  lasterrmsg = err;
						  )
					     else nothing;
					     -- result of AfterPrint is ignored:
					     g = runmethod(if s.word == SemicolonW then modeAfterNoPrint else modeAfterPrint,lastvalue);
					     when g is err:Error do (
						  err = update(err,"after print",f);
						  if stopIfError || returnIfError then return err;
						  lasterrmsg = err;
						  )
					     else nothing;
					     )
					)
				   )
			      else (
				   -- an error occurred in localBind
				   if isatty(file) 
				   then flush(file)
				   else return (
					if lasterrmsg != dummyError
					then Expr(lasterrmsg)
					else buildErrorPacket("error occurred in parsing")))))))));

interpreterDepthS := setupvar("interpreterDepth",zeroE);
setInterpreterDepth(n:int):void := (
     interpreterDepth = n;
     setGlobalVariable(interpreterDepthS, toExpr(interpreterDepth)));
incrementInterpreterDepth():void := setInterpreterDepth(interpreterDepth + 1);
decrementInterpreterDepth():void := setInterpreterDepth(interpreterDepth - 1);

readeval3(file:TokenFile,printout:bool,dc:DictionaryClosure,returnLastvalue:bool,stopIfBreakReturnContinue:bool,returnIfError:bool):Expr := (
     saveLocalFrame := localFrame;
     localFrame = dc.frame;
      savecf := getGlobalVariable(currentFileName);
      savecd := getGlobalVariable(currentFileDirectory);
      savepf := currentPosFile;
	setGlobalVariable(currentFileName,toExpr(file.posFile.file.filename));
	setGlobalVariable(currentFileDirectory,toExpr(dirname(file.posFile.file.filename)));
        currentPosFile = file.posFile;
	ret := readeval4(file,printout,dc.dictionary,returnLastvalue,stopIfBreakReturnContinue,returnIfError);
      setGlobalVariable(currentFileDirectory,savecd);
      setGlobalVariable(currentFileName,savecf);
      currentPosFile = savepf;
     localFrame = saveLocalFrame;
     ret);

-- parse a file
readeval(file:TokenFile,returnLastvalue:bool,returnIfError:bool):Expr := (
     savefe := getGlobalVariable(fileExitHooks);
     setGlobalVariable(fileExitHooks,emptyList);
     printout := false; mode := nullE;
     ret := readeval3(file,printout,newStaticLocalDictionaryClosure(file.posFile.file.filename),returnLastvalue,false,returnIfError);
     haderror := when ret is Error do True else False;
     lastexiterror := dummyError;
     hook := getGlobalVariable(fileExitHooks);
     when hook is x:List do foreach f in x.v do (
	  r := applyEE(f,haderror);
	  when r is err:Error do (
	       if lastexiterror != dummyError && !lastexiterror.printed then printErrorMessage(lastexiterror); -- or else it gets bumped
	       lastexiterror = err;
	       ) else nothing
	  )
     else nothing;
     setGlobalVariable(fileExitHooks,savefe);
     if lastexiterror != dummyError then Expr(lastexiterror) else ret);

InputPrompt := makeProtectedSymbolClosure("InputPrompt");
InputContinuationPrompt := makeProtectedSymbolClosure("InputContinuationPrompt");

promptcount := 0;
topLevelPrompt():string := (
     if debugLevel == 123 then (
	  stderr <<  "-- topLevelPrompt:" 
	  << " previousLineNumber = " << previousLineNumber 
	  << "; lineNumber = " << lineNumber 
	  << endl;
	  );
     method := lookup(
	  ZZClass,
	  list(topLevelMode, Expr(if lineNumber == previousLineNumber then InputContinuationPrompt else (previousLineNumber = lineNumber; InputPrompt))));
     p := (
	  if method == nullE then ""
     	  else when applyEE(method,toExpr(lineNumber)) is s:stringCell do s.v
     	  is n:ZZcell do if isInt(n) then blanks(toInt(n)) else ""
     	  else "\n<--bad prompt--> : " -- unfortunately, we are not printing the error message!
	  );
     if debugLevel == 123 then (
	  p = "[" + tostring(promptcount) + "]  " + p;
	  stderr <<  "-- topLevelPrompt:" 
	  << " prompt = \"" << presentn(p) << "\""
	  << endl;
	  );
     promptcount = promptcount + 1;
     p);

loadprintstdin(dc:DictionaryClosure,stopIfBreakReturnContinue:bool,returnIfError:bool):Expr := (
     when openTokenFile("-")
     is e:errmsg do buildErrorPacket(e.message)
     is file:TokenFile do (
	  if !file.posFile.file.fulllines		    --texmacs !
	  then setprompt(file,topLevelPrompt);
	  r := readeval3(file,true,dc,false,stopIfBreakReturnContinue,returnIfError);
	  file.posFile.file.eof = false; -- erase eof indication so we can try again (e.g., recursive calls to topLevel)
	  r));

loadprint(filename:string,dc:DictionaryClosure,returnIfError:bool):Expr := (
     when openTokenFile(filename)
     is errmsg do False
     is file:TokenFile do (
	  if file.posFile.file != stdIO then file.posFile.file.echo = true;
	  if !file.posFile.file.fulllines		    --texmacs !
	  then setprompt(file,topLevelPrompt);
	  r := readeval3(file,true,dc,false,false,returnIfError);
	  t := (
	       if filename === "-"			 -- whether it's stdIO
	       then (
		    file.posFile.file.eof = false; -- erase eof indication so we can try again (e.g., recursive calls to topLevel)
		    0
		    )
	       else close(file));
	  when r is err:Error do (
	       if err.message == returnMessage
	       || err.message == continueMessage || err.message == continueMessageWithArg
	       || err.message == stepMessage || err.message == stepMessageWithArg
	       || err.message == breakMessage then if err.value == dummyExpr then nullE else err.value else r
	       )
	  else (
	       if t == ERROR
	       then buildErrorPacket("error closing file") 
	       else nullE)));
load(filename:string):Expr := (
     when openTokenFile(filename)
     is e:errmsg do buildErrorPacket(e.message)
     is file:TokenFile do (
	  r := readeval(file,true,true);
	  t := if !(filename==="-") then close(file) else 0;
	  when r is err:Error do (
	       if err.message == returnMessage
	       || err.message == continueMessage || err.message == continueMessageWithArg
	       || err.message == stepMessage || err.message == stepMessageWithArg
	       || err.message == breakMessage then if err.value == dummyExpr then nullE else err.value else r
	       )
	  else (
	       if t == ERROR
	       then buildErrorPacket("error closing file") 
 	       else r)));

load(e:Expr):Expr := (
     when e
     is s:stringCell do load(s.v)
     else buildErrorPacket("expected string as file name"));
setupfun("simpleLoad",load);

currentRowNumber(e:Expr):Expr := (
     when e is s:Sequence do
     if length(s) == 0 then toExpr(int(currentPosFile.line))
     else WrongNumArgs(0)
     else WrongNumArgs(0));
setupfun("currentRowNumber",currentRowNumber);

currentColumnNumber(e:Expr):Expr := (
     when e is s:Sequence do
     if length(s) == 0 then toExpr(int(currentPosFile.column))
     else WrongNumArgs(0)
     else WrongNumArgs(0));
setupfun("currentColumnNumber",currentColumnNumber);

input(e:Expr):Expr := (
     when e
     is f:stringCell do (
	  filename := f.v;
	  -- we should have a way of setting normal prompts while inputting
     	  incrementInterpreterDepth();
	  ret := loadprint(filename,newStaticLocalDictionaryClosure(filename),true);
     	  decrementInterpreterDepth();
	  previousLineNumber = -1;
	  ret)
     else buildErrorPacket("expected string as file name"));
setupfun("simpleInput",input);

stringTokenFile(name:string,contents:string):TokenFile := (
     TokenFile(
	  makePosFile(
	  newFile(name,	 		  -- filename
	       0,			  -- pid
	       false,	       	    	  -- error
	       "",     	    	      	  -- message
	       false,	       	    	  -- listener
	       NOFD,   	    	          -- listenerfd
	       NOFD,	      	   	  -- connection
	       0,     	   	     	  -- numconns
	       true,			  -- input
	       NOFD,			  -- infd
	       false,			  -- inisatty
	       contents,		  -- inbuffer
	       0,			  -- inindex
	       length(contents),	  -- insize
	       false,			  -- eof
	       false,	  		  -- promptq
	       noprompt,		  -- prompt
	       noprompt,		  -- reward
	       false,			  -- fulllines
     	       true,	       	    	  -- bol
	       false,			  -- echo
	       0,			  -- echoindex
	       false,			  -- output
	       NOFD,			  -- outfd
	       false,			  -- outisatty
	       "",			  -- outbuffer
	       0,			  -- outindex
	       0,     	   	     	  -- outbol
	       false,	       	    	  -- hadNet
	       dummyNetList,   	      	  -- nets
	       0,		          -- bytesWritten
	       -1,		          -- lastCharOut
	       false,                     -- readline
	       0                          -- threadState
	       )),
	  NULL));

export topLevel():bool := (
     when loadprint("-",newStaticLocalDictionaryClosure(),false)
     is err:Error do (
	  -- printErrorMessage(err);		    -- this message may not have been printed before (?)
	  false)
     else true
     );

commandInterpreter(dc:DictionaryClosure):Expr := loadprint("-",dc,false);
commandInterpreter(f:Frame):Expr := commandInterpreter(newStaticLocalDictionaryClosure(localDictionaryClosure(f)));
commandInterpreter(e:Expr):Expr := (
     incrementInterpreterDepth();
       ret := 
       when e is s:Sequence do (
	    if length(s) == 0 then loadprint("-",newStaticLocalDictionaryClosure(),false)
	    else WrongNumArgs(0,1)
	    )
       is Nothing do loadprint("-",newStaticLocalDictionaryClosure(),false)
       is x:DictionaryClosure do commandInterpreter(x)
       is x:SymbolClosure do commandInterpreter(x.frame)
       is x:CodeClosure do commandInterpreter(x.frame)
       is x:FunctionClosure do commandInterpreter(x.frame)
       is cfc:CompiledFunctionClosure do commandInterpreter(emptyFrame)	    -- some values are there, but no symbols
       is CompiledFunction do commandInterpreter(emptyFrame)		    -- no values or symbols are there
       is s:SpecialExpr do commandInterpreter(s.e)
       else WrongArg("a function, symbol, dictionary, pseudocode, or ()");
     decrementInterpreterDepth();
     ret);
setupfun("commandInterpreter",commandInterpreter);

currentS := setupvar("current",nullE);
debugger(f:Frame,c:Code):Expr := (
     -- stdIO << "-- recursionDepth = " << recursionDepth << endl;
     oldrecursionDepth := recursionDepth;
     recursionDepth = 0;
     setDebuggingMode(false);
       oldDebuggerCode := getGlobalVariable(currentS);
       setGlobalVariable(currentS,Expr(CodeClosure(f,c)));
	 incrementInterpreterDepth();
	   if debuggerHook != nullE then (
		r := applyEE(debuggerHook,True);
		when r is Error do return r else nothing;
		);
	   ret := loadprintstdin(newStaticLocalDictionaryClosure(localDictionaryClosure(f)),true,false);
	   if debuggerHook != nullE then (
		r := applyEE(debuggerHook,False);
		when r is Error do return r else nothing;
		);
	 decrementInterpreterDepth();
       setGlobalVariable(currentS,oldDebuggerCode);
     setDebuggingMode(true);
     recursionDepth = oldrecursionDepth;
     ret);
debuggerFun = debugger;

currentString := setupvar("currentString", nullE);
value(e:Expr):Expr := (
     when e
     is q:SymbolClosure do (
	  vals := q.frame.values;
	  i := q.symbol.frameindex;
	  if i < length(vals) then vals.i 
	  else nullE					    -- localFrame is the only one that might be short
	  )
     is c:CodeClosure do eval(c.frame,c.code)
     is s:stringCell do (
      	  savecs := getGlobalVariable(currentString);
	  setGlobalVariable(currentString,e);
	  r := readeval(stringTokenFile("currentString", s.v+newline),true,true);
	  setGlobalVariable(currentString,savecs);
	  when r 
	  is err:Error do (
	       if err.message == returnMessage
	       || err.message == continueMessage || err.message == continueMessageWithArg 
	       || err.message == stepMessage || err.message == stepMessageWithArg 
	       || err.message == breakMessage then if err.value == dummyExpr then nullE else err.value 
	       else r)
	  else r)
     else WrongArg(1,"a string, a symbol, or pseudocode"));
setupfun("value'",value);

--May need thread work?
capture(e:Expr):Expr := (
     when e
     is s:stringCell do (
	  flush(stdIO);
	  flush(stdError);
	  oldStdError := stdError;
	  setStdError(stdIO);
	  oldStopIfError := stopIfError;
	  setstopIfError(true);
	  oldDebuggingMode := debuggingMode;
	  setDebuggingMode(false);
	  oldInterpreterDepth := interpreterDepth;
	  setInterpreterDepth(1);
	  oldLineNumber := lineNumber;
	  setLineNumber(0);
	  previousLineNumber = -1;
	  --
	  foss := getFileFOSS(stdIO);
	  foss.capturing = true;
	  oldbuf := foss.outbuffer;
	  oldbol := foss.outbol;
	  oldindex := foss.outindex;
	  stringFile := stringTokenFile("currentString", s.v+newline);
	  stringFile.posFile.file.echo = true;
	  setprompt(stringFile,topLevelPrompt);
	  --
	  r := readeval3(stringFile,true,newStaticLocalDictionaryClosure(),false,false,true);
	  --
	  out := substrAlwaysCopy(foss.outbuffer,0,foss.outindex);
	  foss.capturing = false;
	  foss.outbuffer = oldbuf;
	  foss.outbol = oldbol;
	  foss.outindex = oldindex;
	  releaseFileFOSS(stdIO);
	  --
	  setStdError(oldStdError);
	  setstopIfError(oldStopIfError);
	  setDebuggingMode(oldDebuggingMode);
	  setInterpreterDepth(oldInterpreterDepth);
	  setLineNumber(oldLineNumber);
	  previousLineNumber = -1;
	  --
	  Expr(Sequence( when r is err:Error do True else False, toExpr(out) )))
     else WrongArg(1,"a string"));
setupfun("capture", capture).Protected = false; -- will be overloaded in m2/examples.m2

normalExit := 0;
errorExit := 1;
interruptExit := 2;					    -- see also M2lib.c
failedExitExit := 3;

Exit(err:Error):void := exit(
     if err.message === interruptMessage then interruptExit
     else errorExit
     );

header "/* Declarations for startup.c, which is generated in Macaulay2/bin */
typedef struct { const char *filename, *contents; } cached_file;
extern cached_file startupFile;
extern cached_file testStrings[];
extern int num_testStrings;
/* End of declarations for startup.c */";

export cachedFile := { filename:string, contents:string };
export startupFile := cachedFile(
     tostring(Ccode(constcharstar,"startupFile.filename")),
     tostring(Ccode(constcharstar,"startupFile.contents")));
export process():void := (
     localFrame = globalFrame;
     previousLineNumber = -1;
     stdIO.inisatty  =    0 != isatty(0) ;
     stdIO.echo      =  !(0 != isatty(0));
     stdIO.outisatty =    0 != isatty(1) ;
     stdError.outisatty = 0 != isatty(2) ;
     setstopIfError(false);				    -- this is usually true after loaddata(), we want to reset it
     sethandleInterrupts(true);				    -- could be overridden in startup.m2
     setMaxAllowableThreads();
     -- setLoadDepth(loadDepth);				    -- loaddata() in M2lib.c increments it, so we have to reflect that at top level
     everytimeRun();
     -- we don't know the right directory; calls commandInterpreter and eventually returns:
     ret := readeval(stringTokenFile(startupFile.filename,startupFile.contents),false,false);
     when ret is err:Error do (
	  if !err.printed then printError(err);		    -- just in case
	  if stopIfError
	  then Exit(err)	 -- probably can't happen, because layout.m2 doesn't set stopIfError
	  else if !topLevel()				    -- give a prompt for debugging
	  then Exit(err))
     else nothing;
     when ret is n:ZZcell do (
	  if isInt(n) then (
     	       value(toExpr("exit " + tostring(toInt(n))));   -- try to exit the user's way
     	       ))
     else nothing;
     value(toExpr("exit 0"));				    -- try to exit the user's way
     exit(failedExitExit);		   -- if that doesn't work, try harder and indicate an error
     );

export testStrings := (
     new array(cachedFile) len Ccode(int,"num_testStrings") at i 
     do provide cachedFile(
     	  tostring(Ccode(constcharstar,"testStrings[",i,"].filename")),
     	  tostring(Ccode(constcharstar,"testStrings[",i,"].contents"))));
setupconst("startupString", toExpr(startupFile.contents));
runBasicTests(e:Expr):Expr := (
     when e is s:Sequence do
     if length(s) == 0 then (
	  foreach cf in testStrings do (
	       stderr << "-- testing " << cf.filename << endl;
	       save := globalDictionary;
	       globalDictionary = newGlobalDictionary();
	       globalDictionary.outerDictionary = Macaulay2Dictionary;
	       ret := readeval(stringTokenFile(cf.filename,cf.contents),false,false);
     	       globalDictionary = save;
	       when ret is err:Error do (
		    if !err.printed then printError(err);		    -- just in case
		    if stopIfError
		    then Exit(err)
		    else if !topLevel()				    -- give a prompt for debugging
		    then Exit(err))
	       else nothing);
	  nullE)
     else WrongNumArgs(0)
     else WrongNumArgs(0));
setupfun("runBasicTests",runBasicTests);

-- Local Variables:
-- compile-command: "echo \"make: Entering directory \\`$M2BUILDDIR/Macaulay2/d'\" && make -C $M2BUILDDIR/Macaulay2/d interp.o "
-- End:
