From pkienzle Thu Jul 27 03:00:31 2000
To: jcardoso@inescporto.pt
Subject: Re: Could and error call 'keyboard' automatically?

Joao,

I've hacked "stop_on_error" into 2.0.16.  If stop_on_error = 1, then if
an error occurs, keyboard is automatically called.  From keyboard, you
can do whatever you normally would do in keyboard to fix the problem, the
type return (or just press Enter) to continue processing as if the error
didn't occur.  Better make sure that you produce the outputs that the
statement was supposed to, since the statement will not be re-evaluated.
Type quit or exit to return to the main prompt.

error.cc:
	The important bit of the code (the part that prints the location
	of the error and displays the offending code) is in error().  I am
	not handling the display of file and line information properly
	(should be going through verror). error.cc also contains the
	definition of the variable stop_on_error.

input.cc:
	I've modified get_user_input() to distinguish between "quit" and
	"return" in keyboard().  Not required for error trapping to work,
	but certainly useful.  get_user_input() should be rewritten so
	that it is not such a hack.  keyboard() should contain the loop
	since input() doesn't need it.  Restricting get_user_input() to
	doing just that, and letting keyboard() and input() evaluate or
	not as they wish is probably the best approach.


pt-misc.cc, toplev.cc, toplev.h:
	The tricky bit: how to know what statement caused the error.  I
	create a new global variable similar to the curr_function variable
	which defines the current statement.  Then during 
	tree_statement_list::eval(), I update it with each new statement.
	In 2.1.x series, tree_statement::eval() is probably the nicest
	place to put this, but tree_statement_list::eval() works, too
	[see file pt-stmt.cc].  I don't know if the unwind_protect_ptr()
	is necessary or useful here.

Please hack this code into something which can be submitted to
octave-sources (need to update the documentation, too!)  I haven't
tested it exhaustively by any stretch.  I can't work on 2.1.x series
since I can't compile it.  If you don't have the time or inclination,
submit this message to the list and let somebody else have a go.  Thanks!

Paul Kienzle
pkienzle@kienzle.powernet.co.uk

PS, It occurs to me that dbstep functionality would be easy to implement:
just define a "step_through_statements" flag like "stop_on_error", and
in tree_statement::eval(), if this flag is set, then do the same debug
call that you do for stop_on_error.

PPS, With curr_function and curr_command, warning() can print the function
and statement line/column which generated the warning.  That would be nice!

---------

[Update:  remove the unwind_protect_ptr(curr_command)
This patch should already have been applied to 2.1.32]

*** src/error.cc	Thu Jul 27 02:10:27 2000
--- src/error.cc-orig	Sat Mar 28 20:32:35 1998
***************
*** 39,58 ****
  #include "ov.h"
  #include "variables.h"
  
- #include "toplev.h"
- #include "pt-pr-code.h"
- #include "pt-fcn.h"
- #include "pt-misc.h"
- #include "input.h"
- 
  // TRUE means that Octave will try to beep obnoxiously before printing
  // error messages.
  static bool Vbeep_on_error;
  
- // TRUE means that Octave will try to run the keyboard prompt if any
- // errors occur.
- static bool Vstop_on_error;
- 
  // Current error state.
  int error_state = 0;
  
--- 39,48 ----
***************
*** 188,214 ****
  void
  error (const char *fmt, ...)
  {
-   int initstate = error_state;
- 
    va_list args;
    va_start (args, fmt);
    error_1 ("error", fmt, args);
    va_end (args);
- 
-   if (Vstop_on_error && initstate == 0 && curr_function != NULL) {
- 
-     if (curr_command != NULL) {
-       cout << curr_function->fcn_file_name() << ": "
- 	   << curr_command->line() << "(" 
- 	   << curr_command->column() << ")" << endl ;
-       tree_print_code tpc (octave_stdout, Vps4);
-       curr_command->accept (tpc);
-     }
- 
-     error_state = 0;
-     octave_value_list noargs;
-     feval("keyboard", noargs, 0);
-   }
  }
  
  void
--- 178,187 ----
***************
*** 329,349 ****
    return 0;
  }
  
- static int
- stop_on_error (void)
- {
-   Vstop_on_error = check_preference ("stop_on_error");
- 
-   return 0;
- }
- 
  void
  symbols_of_error (void)
  {
    DEFVAR (beep_on_error, 0.0, 0, beep_on_error,
      "if true, beep before printing error messages");
-   DEFVAR (stop_on_error, 0.0, 0, stop_on_error,
-     "if true, go into debug after printing error messages");
  }
  
  /*
--- 302,312 ----
*** src/input.cc	Thu Jul 27 02:04:26 2000
--- src/input.cc-orig	Thu Nov  4 17:21:14 1999
***************
*** 1111,1122 ****
  
        int len = strlen (input_buf);
  
!       if (len < 1 || (len == 1 && input_buf[0] == '\n'))
  	{
! 	  if (debug) 
! 	    {
! 	      return retval;
! 	    }
  	  else
  	    {
  	      if (read_as_string)
--- 1111,1120 ----
  
        int len = strlen (input_buf);
  
!       if (len < 1)
  	{
! 	  if (debug)
! 	    goto again;
  	  else
  	    {
  	      if (read_as_string)
***************
*** 1131,1144 ****
  	      || match_sans_spaces ("quit", input_buf)
  	      || match_sans_spaces ("return", input_buf)))
  	{
- 
- 	  if (! match_sans_spaces ("return", input_buf))
- 	    error_state = -1; // if exit or quit, return to main prompt
  	  return retval;
  	}
        else if (read_as_string)
  	{
! 	  retval = input_buf;
  	}
        else
  	{
--- 1129,1142 ----
  	      || match_sans_spaces ("quit", input_buf)
  	      || match_sans_spaces ("return", input_buf)))
  	{
  	  return retval;
  	}
        else if (read_as_string)
  	{
! 	  if (len == 1 && input_buf[0] == '\n')
! 	    retval = "";
! 	  else
! 	    retval = input_buf;
  	}
        else
  	{
***************
*** 1222,1228 ****
        retval = get_user_input (args, true);
  
        run_unwind_frame ("keyboard");
-       retval = octave_value();
      }
    else
      print_usage ("keyboard");
--- 1220,1225 ----
*** src/pt-misc.cc	Wed Jul 26 22:12:43 2000
--- src/pt-misc.cc-orig	Sat Mar 27 17:19:39 1999
***************
*** 51,57 ****
  #include "pt-mvr.h"
  #include "pt-walk.h"
  #include "pt-pr-code.h"
- #include "unwind-prot.h"
  #include "ov.h"
  #include "utils.h"
  #include "variables.h"
--- 51,56 ----
***************
*** 119,126 ****
    for (Pix p = first (); p != 0; next (p))
      {
        tree_statement *elt = this->operator () (p);
-       unwind_protect_ptr (curr_command);
-       curr_command = elt;
  
        if (! print)
  	pf = false;
--- 118,123 ----
***************
*** 169,176 ****
        for (Pix p = first (); p != 0; next (p))
  	{
  	  tree_statement *elt = this->operator () (p);
- 	  unwind_protect_ptr (curr_command);
- 	  curr_command = elt;
  
  	  if (! print)
  	    pf = false;
--- 166,171 ----
*** src/toplev.cc	Wed Jul 26 18:58:50 2000
--- src/toplev.cc-orig	Thu Oct 21 08:04:53 1999
***************
*** 129,137 ****
  // Pointer to function that is currently being evaluated.
  tree_function *curr_function = 0;
  
- // Pointer to command that is currently being evaluated.
- tree_statement *curr_command = 0;
- 
  // Nonzero means input is coming from startup file.
  int input_from_startup_file = 0;
  
--- 129,134 ----
*** src/toplev.h	Wed Jul 26 21:37:10 2000
--- src/toplev.h-orig	Sat Mar 28 21:55:19 1998
***************
*** 29,35 ****
  class octave_value_list;
  class tree_function;
  class tree_statement_list;
- class tree_statement;
  class charMatrix;
  
  #include <string>
--- 29,34 ----
***************
*** 92,100 ****
  
  // Pointer to function that is currently being evaluated.
  extern tree_function *curr_function;
- 
- // Pointer to function that is currently being evaluated.
- extern tree_statement *curr_command;
  
  // Nonzero means input is coming from startup file.
  extern int input_from_startup_file;
--- 91,96 ----

