Index: Shell.java
===================================================================
RCS file: /cvsroot/tcljava/src/jacl/tcl/lang/Shell.java,v
retrieving revision 1.5
diff -b -c -r1.5 Shell.java
*** Shell.java	2000/04/03 14:09:11	1.5
--- Shell.java	2000/04/05 21:33:56
***************
*** 183,191 ****
  
  // Used to for interactive input/output
  
! private Channel in;
! private Channel out;
! private Channel err;
  
  // set to true to get extra debug output
  private static final boolean debug = false;
--- 183,190 ----
  
  // Used to for interactive input/output
  
! private PrintStream out;
! private PrintStream err;
  
  // set to true to get extra debug output
  private static final boolean debug = false;
***************
*** 247,254 ****
      sbuf = new StringBuffer(100);
      historyObjs = new Vector();
  
!     out = new StdChannel("stdout");
!     err = new StdChannel("stderr");
  }
  
  /*
--- 246,253 ----
      sbuf = new StringBuffer(100);
      historyObjs = new Vector();
  
!     out = System.out;
!     err = System.err;
  }
  
  /*
***************
*** 298,316 ****
              System.out.println("\"" + sbuf + "\"");
          }
  
! 	// We have a complete command now. Execute it.
  
! 	if (Interp.commandComplete(sbuf.toString())) {
              if (debug) {
                  System.out.println("line was a complete command");
              }
  
! 	    ConsoleEvent evt = new ConsoleEvent(interp, sbuf.toString());
! 	    interp.getNotifier().queueEvent(evt, TCL.QUEUE_TAIL);
! 	    evt.sync();
  
! 	    if (evt.evalException == null) { // No error was generated
! 		String s = evt.evalResult.toString();
  
                  if (debug) {
                      System.out.println("eval result was \"" + s + "\"");
--- 297,349 ----
              System.out.println("\"" + sbuf + "\"");
          }
  
! 	// We have a complete or partial command now. Execute it.
! 	// We use a ConsoleEvent to queue all execution logic to
! 	// be executed by the Interp's thread.
  	
! 	ConsoleEvent evt = new ConsoleEvent(this);
! 	interp.getNotifier().queueEvent(evt, TCL.QUEUE_TAIL);
! 	evt.sync();	// wait for the Interp to finish handling the command
!     }
! }
! 
! /*
!  *----------------------------------------------------------------------
!  *
!  * safeEvalCommand --
!  *
!  *	Called by the ConsoleEvent.processEvent.  This method should
!  *	only be called from the processEvent() method of the ConsoleEvent
!  *	The ConsoleEvent.processEvent() method is guaranteed to be called
!  *	by the TCL interpreter thread.  As a result, it is safe to access
!  *	Interp class data and method inside this method.
!  *
!  * Results:
!  *	None.
!  *
!  * Side effects:
!  *	The user input is eval'ed. It may may have arbitrary side
!  *	effects.
!  *
!  *----------------------------------------------------------------------
!  */
! void
! safeEvalCommand()
! {
!     TclObject		 prompt;
!     String		 command = sbuf.toString();
!     
!     if (Interp.commandComplete(command)) {
  	if (debug) {
  	    System.out.println("line was a complete command");
  	}
  
! 	try {
! 	    interp.recordAndEval(TclString.newInstance(command), 0);
! 	    TclObject evalResult = interp.getResult();
! 	    evalResult.preserve();
  	    
! 	    String s = evalResult.toString();
  
  	    if (debug) {
  		System.out.println("eval result was \"" + s + "\"");
***************
*** 318,338 ****
  
  		if (s.length() > 0) {
  		    putLine(out, s);
  		}
! 	    } else { // Tcl error was generated !
                  if (debug) {
                      System.out.println("eval returned exceptional condition");
                  }
  
! 		int code = evt.evalException.getCompletionCode();
  
- 		// This really sucks, but the getMessage() call on the exception
- 		// does not always return the msg! See TclException for super()!
- 		String msg = evt.evalResult.toString();
- 
  		check_code: {
  		    if (code == TCL.RETURN) {
- 			// FIXME : not thread safe!
  			code = interp.updateReturnInfo();
  			if (code == TCL.OK) {
  			    break check_code;
--- 351,402 ----
  
  	    if (s.length() > 0) {
  		putLine(out, s);
+ 	    }
+ 
+ 	    // The "history limit" controls how many TclObject's
+ 	    // we record from the results of the Console inputs.
+ 
+ 	    int limit = 0;
+ 	    //		    int limit = 10;
+ 
+ 	    try {
+ 		TclObject histLimit = interp.getVar("historyLimit",
+ 						    TCL.GLOBAL_ONLY);
+ 		if (histLimit != null) {
+ 		    histLimit.preserve();
+ 		    limit = TclInteger.get(interp, histLimit);
+ 		    histLimit.release();
+ 		}
+ 	    } catch (TclException e) {
+ 		// histLimit doesn't exist or contains an invalid integer.
+ 		// Ignore it.
+ 	    }
+ 
+ 	    // This cleans up all intermediate objects that
+ 	    // are no longer referenced in Tcl. This check is
+ 	    // needed to clean up object references in the
+ 	    // string->object translation table.
+ 
+ 	    if (limit > 0) {
+ 		historyObjs.addElement(evalResult);
+ 	    } else {
+ 		evalResult.release();
  	    }
! 
! 	    if (historyObjs.size() > limit && historyObjs.size() > 0) {
! 		TclObject cobj =(TclObject)historyObjs.elementAt(0);
! 		historyObjs.removeElementAt(0);
! 		cobj.release();
! 	    }
! 	} catch (TclException e) {
  	    if (debug) {
  		System.out.println("eval returned exceptional condition");
  	    }
  
! 	    int code = e.getCompletionCode();
  	    
  	    check_code: {
  		if (code == TCL.RETURN) {
  		    code = interp.updateReturnInfo();
  		    if (code == TCL.OK) {
  			break check_code;
***************
*** 341,347 ****
  
  		    switch (code) {
  		    case TCL.ERROR:
! 			putLine(err, msg);
  			break;
  		    case TCL.BREAK:
  			putLine(err, "invoked \"break\" outside of a loop");
--- 405,411 ----
  
  		switch (code) {
  		case TCL.ERROR:
! 		    putLine(err, interp.getResult().toString());
  		    break;
  		case TCL.BREAK:
  		    putLine(err, "invoked \"break\" outside of a loop");
***************
*** 355,364 ****
  		}
  	    }
  
- 	    evt.evalResult.release(); // we are done with the interp result
  	    sbuf.setLength(0); // empty out sbuf
  
- 	    // FIXME : not thread safe!
  	    try {
  		prompt = interp.getVar("tcl_prompt1", TCL.GLOBAL_ONLY);
  	    } catch (TclException e) {
--- 419,426 ----
***************
*** 366,375 ****
  	    }
  	    if (prompt != null) {
  		try {
! 		    // FIXME : not thread safe
  		    interp.eval(prompt.toString(), TCL.GLOBAL_ONLY);
  		} catch (TclException e) {
  		    put(out, "% ");
  		}
  	    } else {
  		put(out, "% ");
--- 428,439 ----
  	}
  	if (prompt != null) {
  	    try {
! 		prompt.preserve();
  		interp.eval(prompt.toString(), TCL.GLOBAL_ONLY);
  	    } catch (TclException e) {
  		put(out, "% ");
+ 	    } finally {
+ 		prompt.release();
  	    }
  	} else {
  	    put(out, "% ");
***************
*** 383,405 ****
  	    // prompt message and wait for further inputs.
  
  	    try {
- 		// FIXME : not thread safe!
  		prompt = interp.getVar("tcl_prompt2", TCL.GLOBAL_ONLY);
  	    } catch (TclException e) {
  		prompt = null;
  	    }
  	    if (prompt != null) {
  		try {
! 		    // FIXME : not thread safe
  		    interp.eval(prompt.toString(), TCL.GLOBAL_ONLY);
  		} catch (TclException e) {
  		    put(out, "> ");
  		}
  	    } else {
  		put(out, "> ");
  	    }
  	}
-     }
  }
  
  /*
--- 447,469 ----
  	// prompt message and wait for further inputs.
  
  	try {
  	    prompt = interp.getVar("tcl_prompt2", TCL.GLOBAL_ONLY);
  	} catch (TclException e) {
  	    prompt = null;
  	}
  	if (prompt != null) {
  	    try {
! 		prompt.preserve();
  		interp.eval(prompt.toString(), TCL.GLOBAL_ONLY);
  	    } catch (TclException e) {
  		put(out, "> ");
+ 	    } finally {
+ 		prompt.release();
  	    }
  	} else {
  	    put(out, "> ");
  	}
      }
  }
  
  /*
***************
*** 547,557 ****
  
  private void
  putLine(
!     Channel chan, 		// The channel to print to.
      String s)			// The string to print.
  {
!     put(chan, s);
!     put(chan, "\n");
  }
  
  /*
--- 611,621 ----
  
  private void
  putLine(
!     PrintStream chan, 		// The channel to print to.
      String s)			// The string to print.
  {
!     chan.println(s);
!     chan.flush();
  }
  
  /*
***************
*** 573,586 ****
  
  private
  void put(
!     Channel chan,  		// The channel to print to.
      String s)			// The string to print.
  {
!     try {
! 	out.write(interp, s);
!         out.flush(interp);
!     } catch (Exception  e) {
! 	throw new TclRuntimeError("unexpected Exception " + e);
!     }
  }
  } // end of class ConsoleThread
--- 637,646 ----
  
  private
  void put(
!     PrintStream chan,  		// The channel to print to.
      String s)			// The string to print.
  {
!     chan.print(s);
!     chan.flush();
  }
  } // end of class ConsoleThread
Index: ConsoleEvent.java
===================================================================
RCS file: /cvsroot/tcljava/src/jacl/tcl/lang/ConsoleEvent.java,v
retrieving revision 1.5
diff -b -c -r1.5 ConsoleEvent.java
*** ConsoleEvent.java	2000/04/03 14:09:11	1.5
--- ConsoleEvent.java	2000/04/05 21:33:56
***************
*** 22,46 ****
  
  class ConsoleEvent extends TclEvent {
  
! // Interpreter to evaluate the user input.
  
- Interp interp;
  
- // The result of evaluating the user input string. If an exception
- // occurred it will be the interp result.
- 
- TclObject evalResult;
- 
- // If an exception occurred during the script evaluation, contains the
- // exception. Otherwise is null.
- 
- TclException evalException;
- 
- // The user input string.
- 
- String script;
- 
- 
  /*
   *----------------------------------------------------------------------
   *
--- 22,31 ----
  
  class ConsoleEvent extends TclEvent {
  
! // The ConsoleThread that issued this event
! ConsoleThread console;
  
  
  /*
   *----------------------------------------------------------------------
   *
***************
*** 55,67 ****
   */
  
  ConsoleEvent(
!     Interp i,		// Interpreter to evaluate the user input string.
!     String s)		// User input string.
  {
!     interp = i;
!     script = s;
!     evalResult = null;
!     evalException = null;
  }
  
  /*
--- 40,48 ----
   */
  
  ConsoleEvent(
!     ConsoleThread consoleThread)	// The thread that issued this event
  {
!     console = consoleThread;
  }
  
  /*
***************
*** 86,99 ****
  processEvent(
      int flags)		// Same as flags passed to Notifier.doOneEvent.
  {
!     try {
! 	interp.recordAndEval(TclString.newInstance(script), 0);
!     } catch (TclException e) {
! 	evalException = e;
!     } finally {
! 	evalResult = interp.getResult();
! 	evalResult.preserve();
!     }
  
      return 1;
  }
--- 67,74 ----
  processEvent(
      int flags)		// Same as flags passed to Notifier.doOneEvent.
  {
!     console.safeEvalCommand();	// calls the console thread's method to
! 				//  do the actual work
  
      return 1;
  }
