changeset 3707:58140935c812

[project @ 2000-07-28 09:40:52 by jwe]
author jwe
date Fri, 28 Jul 2000 09:40:54 +0000
parents 6581e686f83f
children 9b9efdcbdfd3
files liboctave/lo-cutils.c src/ChangeLog src/error.cc src/input.cc src/input.h src/pt-stmt.cc src/pt-stmt.h
diffstat 7 files changed, 200 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/lo-cutils.c	Tue Jul 25 05:30:02 2000 +0000
+++ b/liboctave/lo-cutils.c	Fri Jul 28 09:40:54 2000 +0000
@@ -42,6 +42,8 @@
   return strptime (buf, format, tm);
 }
 
+
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/ChangeLog	Tue Jul 25 05:30:02 2000 +0000
+++ b/src/ChangeLog	Fri Jul 28 09:40:54 2000 +0000
@@ -1,3 +1,23 @@
+2000-07-28  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	Debug-on-error stuff based on a patch submitted by Paul Kienzle
+	<pkienzle@kienzle.powernet.co.uk> for 2.0.x.
+
+	* error.cc (Vdebug_on_warning): New static flag variable.
+	(debug_on_warning): New function.
+	(symbols_of_warning): DEFVAR debug_on_warning.
+	(warning): Handle debug_on_warning here.
+
+	* input.cc (do_keyboard): New function.
+	(Fkeyboard): Use it to do the real work.
+	* pt-stmt.cc (curr_statement): New static variable.
+	(tree_statement::eval): Save and restore it here.
+	* error.cc (Vdebug_on_error): New static flag variable.
+	(debug_on_error): New function.
+	(symbols_of_error): DEFVAR debug_on_error.
+	(pr_where, pr_where_1): New functions.
+	(error): Handle debug_on_error here.
+
 2000-07-20  Joao Cardoso  <jcardoso@inescporto.pt>
 
 	* Makefile.in (octave): Link with $(LD_CXX) instead of $(CXX)
--- a/src/error.cc	Tue Jul 25 05:30:02 2000 +0000
+++ b/src/error.cc	Fri Jul 28 09:40:54 2000 +0000
@@ -32,16 +32,31 @@
 
 #include "defun.h"
 #include "error.h"
+#include "input.h"
 #include "pager.h"
 #include "oct-obj.h"
 #include "utils.h"
 #include "ov.h"
+#include "ov-usr-fcn.h"
+#include "pt-pr-code.h"
+#include "pt-stmt.h"
+#include "toplev.h"
+#include "unwind-prot.h"
 #include "variables.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 enter the debugger when an error
+// is encountered.  This will also inhibit printing of the normal
+// traceback message (you will only see the top-level error message).
+static bool Vdebug_on_error;
+
+// TRUE means that Octave will try to enter the debugger when a warning
+// is encountered.
+static bool Vdebug_on_warning;
+
 // Current error state.
 int error_state = 0;
 
@@ -195,6 +210,50 @@
   va_end (args);
 }
 
+static void
+pr_where_1 (const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  error_1 (0, fmt, args);
+  va_end (args);
+}
+
+static void
+pr_where (void)
+{
+  if (curr_statement)
+    {
+      std::string fcn_name = curr_function->function_name ();
+      std::string file_name = curr_function->fcn_file_name ();
+
+      const char *nm
+	= file_name.empty () ? fcn_name.c_str () : file_name.c_str ();
+
+      int l = curr_statement->line ();
+      int c = curr_statement->column ();
+
+      pr_where_1 ("error: in %s near line %d, column %d:", nm, l, c);
+
+      // Oops, note that the column number may not be correct
+      // since the code is being reproduced from the parse tree.
+
+      std::ostrstream output_buf;
+
+      tree_print_code tpc (output_buf, "    ");
+
+      curr_statement->accept (tpc);
+
+      output_buf << ends;
+
+      char *msg = output_buf.str ();
+
+      pr_where_1 (msg);
+
+      delete [] msg;
+    }
+}
+
 void
 warning (const char *fmt, ...)
 {
@@ -203,15 +262,45 @@
   warning_state = 1;
   vwarning ("warning", fmt, args);
   va_end (args);
+
+  if ((interactive || forced_interactive)
+      && Vdebug_on_warning && curr_function)
+    {
+      unwind_protect_bool (Vdebug_on_warning);
+      Vdebug_on_warning = false;
+
+      pr_where ();
+
+      do_keyboard (octave_value_list ());
+
+      unwind_protect::run ();
+    }
 }
 
 void
 error (const char *fmt, ...)
 {
+  int init_state = error_state;
+
   va_list args;
   va_start (args, fmt);
   error_1 ("error", fmt, args);
   va_end (args);
+
+  if ((interactive || forced_interactive)
+      && Vdebug_on_error && init_state == 0 && curr_function)
+    {
+      unwind_protect_bool (Vdebug_on_error);
+      Vdebug_on_error = false;
+
+      pr_where ();
+
+      error_state = 0;
+
+      do_keyboard (octave_value_list ());
+
+      unwind_protect::run ();
+    }
 }
 
 void
@@ -435,6 +524,22 @@
   return 0;
 }
 
+static int
+debug_on_error (void)
+{
+  Vdebug_on_error = check_preference ("debug_on_error");
+
+  return 0;
+}
+
+static int
+debug_on_warning (void)
+{
+  Vdebug_on_warning = check_preference ("debug_on_warning");
+
+  return 0;
+}
+
 void
 symbols_of_error (void)
 {
@@ -446,6 +551,23 @@
 default value is 0.\n\
 @end defvr");
 
+  DEFVAR (debug_on_error, 0.0, debug_on_error,
+    "-*- texinfo -*-\n\
+@defvr {Built-in Variable} debug_on_error\n\
+If the value of @code{debug_on_error} is nonzero, Octave will try\n\
+to enter the debugger when an error is encountered.  This will also\n\
+inhibit printing of the normal traceback message (you will only see\n\
+the top-level error message).  The default value is 0.\n\
+@end defvr");
+
+  DEFVAR (debug_on_warning, 0.0, debug_on_warning,
+    "-*- texinfo -*-\n\
+@defvr {Built-in Variable} debug_on_warning\n\
+If the value of @code{debug_on_warning} is nonzero, Octave will try\n\
+to enter the debugger when a warning is encountered.  The default\n\
+value is 0.\n\
+@end defvr");
+
   DEFCONST (error_text, "",
     "-*- texinfo -*-\n\
 @defvr {Built-in Variable} error_text\n\
--- a/src/input.cc	Tue Jul 25 05:30:02 2000 +0000
+++ b/src/input.cc	Fri Jul 28 09:40:54 2000 +0000
@@ -504,14 +504,14 @@
   std::string prompt ("debug> ");
 
   if (nargin > 0)
-   {
-     prompt = args(0).string_value ();
+    {
+      prompt = args(0).string_value ();
 
-     if (error_state)
-       {
-	 error ("input: unrecognized argument");
-	 return retval;
-       }
+      if (error_state)
+	{
+	  error ("input: unrecognized argument");
+	  return retval;
+	}
     }
 
  again:
@@ -640,6 +640,35 @@
   command_history::ignore_entries (! Vsaving_history);
 }
 
+octave_value
+do_keyboard (const octave_value_list& args)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  assert (nargin == 0 || nargin == 1);
+
+  unwind_protect::begin_frame ("do_keyboard");
+
+  // XXX FIXME XXX -- we shouldn't need both the
+  // command_history object and the
+  // Vsaving_history variable...
+  command_history::ignore_entries (false);
+
+  unwind_protect::add (restore_command_history, 0);
+
+  unwind_protect_bool (Vsaving_history);
+
+  Vsaving_history = true;
+
+  retval = get_user_input (args, true, 0);
+
+  unwind_protect::run_frame ("do_keyboard");
+
+  return retval;
+}
+
 DEFUN (keyboard, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} keyboard (@var{prompt})\n\
@@ -660,24 +689,7 @@
   int nargin = args.length ();
 
   if (nargin == 0 || nargin == 1)
-    {
-      unwind_protect::begin_frame ("keyboard");
-
-      // XXX FIXME XXX -- we shouldn't need both the
-      // command_history object and the
-      // Vsaving_history variable...
-      command_history::ignore_entries (false);
-
-      unwind_protect::add (restore_command_history, 0);
-
-      unwind_protect_bool (Vsaving_history);
-
-      Vsaving_history = true;
-
-      retval = get_user_input (args, true, 0);
-
-      unwind_protect::run_frame ("keyboard");
-    }
+    do_keyboard (args);
   else
     print_usage ("keyboard");
 
--- a/src/input.h	Tue Jul 25 05:30:02 2000 +0000
+++ b/src/input.h	Fri Jul 28 09:40:54 2000 +0000
@@ -31,6 +31,9 @@
 
 #include "oct-time.h"
 
+class octave_value;
+class octave_value_list;
+
 extern int octave_read (char *buf, unsigned max_size);
 extern FILE *get_input_from_file (const std::string& name, int warn = 1);
 extern FILE *get_input_from_stdin (void);
@@ -75,6 +78,8 @@
 
 extern void initialize_command_input (void);
 
+extern octave_value do_keyboard (const octave_value_list& args);
+
 extern std::string Vps4;
 
 enum echo_state
--- a/src/pt-stmt.cc	Tue Jul 25 05:30:02 2000 +0000
+++ b/src/pt-stmt.cc	Fri Jul 28 09:40:54 2000 +0000
@@ -43,6 +43,7 @@
 #include "pt-pr-code.h"
 #include "pt-stmt.h"
 #include "pt-walk.h"
+#include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
 
@@ -50,6 +51,9 @@
 // semicolon has been appended to each statement).
 static bool Vsilent_functions;
 
+// Pointer to the current statement being executed.
+tree_statement *curr_statement = 0;
+
 // A list of commands to be executed.
 
 tree_statement::~tree_statement (void)
@@ -154,8 +158,13 @@
 	  bool silent_flag =
 	    silent ? true : (function_body ? Vsilent_functions : false);
 
+	  unwind_protect_ptr (curr_statement);
+	  curr_statement = elt;
+
 	  retval = elt->eval (silent_flag, nargout, function_body);
 
+	  unwind_protect::run ();
+
 	  if (error_state)
 	    break;
 
@@ -168,6 +177,8 @@
 	}
       else
 	error ("invalid statement found in statement list!");
+
+
     }
 
   return retval;
--- a/src/pt-stmt.h	Tue Jul 25 05:30:02 2000 +0000
+++ b/src/pt-stmt.h	Fri Jul 28 09:40:54 2000 +0000
@@ -146,6 +146,9 @@
   tree_statement_list& operator = (const tree_statement_list&);
 };
 
+// Pointer to the current statement being executed.
+extern tree_statement *curr_statement;
+
 #endif
 
 /*