changeset 7787:6b521b1e3631

Add dbquit and make dbstep compatible. Use parser in debug mode to handle multi-line input
author David Bateman <dbateman@free.fr>
date Tue, 13 May 2008 21:12:12 +0200
parents 37ff0c21c17d
children 45f5faba05a2
files PROJECTS doc/ChangeLog doc/interpreter/debug.txi doc/interpreter/octave.texi src/ChangeLog src/debug.cc src/input.cc src/input.h src/parse.y src/pt-bp.h src/pt.cc src/pt.h src/toplev.cc src/toplev.h
diffstat 14 files changed, 377 insertions(+), 183 deletions(-) [+]
line wrap: on
line diff
--- a/PROJECTS	Tue May 20 16:49:02 2008 -0400
+++ b/PROJECTS	Tue May 13 21:12:12 2008 +0200
@@ -174,15 +174,6 @@
 
   * Allow customization of the debug prompt.
 
-  * For the keyboard function, parse return (or quit) more
-    intelligently so that something like
-
-      debug> x = 1; return
-
-    will work as expected.
-
-  * Handle multi-line input at the keyboard/debug prompt correctly.
-
   * Fix the parser so that
 
       if (expr) 'this is a string' end
--- a/doc/ChangeLog	Tue May 20 16:49:02 2008 -0400
+++ b/doc/ChangeLog	Tue May 13 21:12:12 2008 +0200
@@ -1,3 +1,10 @@
+2008-05-20  David Bateman  <dbateman@free.fr>
+
+	* interpreter/debug.txi: Uodate documentation for multiline
+	input. Add documentation for dbcont, dbquit, dbstep, dbstqck, dbup
+	and dbdown functions.
+	* interpreter/octave.texi: Upodate index for debugging functions.
+
 2008-05-03  Rafael Laboissiere <rafael@debian.org>
 
 	* interpreter/expr.txi, interpreter/tips.txi: Use ischar instead of
--- a/doc/interpreter/debug.txi	Tue May 20 16:49:02 2008 -0400
+++ b/doc/interpreter/debug.txi	Tue May 13 21:12:12 2008 +0200
@@ -27,25 +27,14 @@
 errors.
 
 The normal commandline editing and history functions are available in
-debug mode. However, one limitation on the debug mode is that
-commands entered at the debug prompt are evaluated as strings, rather
-than being handled by the Octave parser. This means that all commands in
-debug mode must be contained on a single line. That is, it is alright to
-write
-
-@example
-debug> for i = 1:n, foo(i); endfor
-@end example
-
-@noindent
-in debug mode. However, writing the above in three lines will not be
-correctly evaluated. To leave the debug mode, you should simply type
-either @code{quit}, @code{exit}, @code{return} or @code{dbcont}.
+debug mode.
 
 @menu
 * Entering Debug Mode::
+* Leaving Debug Mode::
 * Breakpoints::
 * Debug Mode::
+* Call Stack::
 @end menu
 
 @node Entering Debug Mode
@@ -65,6 +54,22 @@
 
 @DOCSTRING(debug_on_error)
 
+@node Leaving Debug Mode
+@section Leavinging Debug Mode
+
+To leave the debug mode, you should simply type either @code{dbcont} 
+or @code{return}.
+
+@DOCSTRING(dbcont}
+
+To quit debug mode and return directly to the prompt @code{dbquit}
+should be used instead
+
+@DOCSTRING(dbquit)
+
+Finally, typing @code{exit} or @code{quit} at the debug prompt will
+result in Octave terminating normally.
+
 @node Breakpoints
 @section Breakpoints
 
@@ -132,8 +137,17 @@
 @DOCSTRING(dbtype)
 
 Debug mode equally allows single line stepping through a function using
-the commands @code{dbstep} and @code{dbnext}.  These differ slightly in
-the way they treat the next executable line if the next line itself is a
-function defined in an m-file.  The @code{dbnext} command will execute
-the next line, while staying in the existing function being debugged.
-The @code{dbstep} command will step in to the new function.
+the commands @code{dbstep}.
+
+@c leave dbnext undocumented
+
+@DOCSTRING(dbstep)
+
+@node Call Stack
+@section Call Stack
+
+@DOCSTRING(dbstack)
+
+@DOCSTRING(dbup)
+
+@DOCSTRING(dbdown)
--- a/doc/interpreter/octave.texi	Tue May 20 16:49:02 2008 -0400
+++ b/doc/interpreter/octave.texi	Tue May 13 21:12:12 2008 +0200
@@ -353,8 +353,10 @@
 Debugging
 
 * Entering Debug Mode::
+* Leaving Debug Mode::
 * Breakpoints::
 * Debug Mode::
+* Call Stack::
 
 Input and Output
 
--- a/src/ChangeLog	Tue May 20 16:49:02 2008 -0400
+++ b/src/ChangeLog	Tue May 13 21:12:12 2008 +0200
@@ -1,3 +1,46 @@
+2008-05-20  David Bateman  <dbateman@free.fr>
+
+	* debug.cc (Fdbstop): If no line specified assume line 1.
+	(Fdbstep, Fdbcont, Fdbnext): Move debugging functions 
+	to normal commands.
+	(Fdbquit): New command to quit debugging mode and return to the 
+	prompt.
+	(Fdbstep): Modify the dbstep command for compatibility.
+	* input.cc (Vdebugging_current_line): Store current line being
+	debugged for use in DEFCMD versions of debug commands.
+	(match_sans_spaces_semi): Delete.
+	(static void get_debug_input (const std;string&)): New function to
+	parse input in debug mode using standard Octave parser.
+	(static octave_value_list get_user_input (const
+	octave_value_list&, int)): Remove debugging specialization.
+	* input.h (Vdebugging_current_line): Store current line being
+	debugged for use in DEFCMD versions of debug commands.
+	* parse.y (make_return_command): Special handling in debug mode.
+	* pt-bp.h (MAYBE_DO_BREAKPOINT): Support break in n lines needed
+	to support "dbstep N". 
+	* pt.cc (tree::break_next): Convert to a down counter to support
+	break in N lines. Breakpoint occure when tree::break_next is zero.
+	* toplev.cc (octave_user_script *
+	octave_call_stack::do_caller_user_script (difference_type) const):
+	Support skipping the first N functions to support "dbstep out".
+	(octave_user_function * octave_call_stack::do_caller_user_function
+	(difference_type) const): Ditto.
+	(octave_user_code * octave_call_stack::do_caller_user_code
+	(difference_type) const): Ditto.
+	* toplev.h (octave_user_script *
+	octave_call_stack::do_caller_user_script (difference_type) const):
+	Add difference_type argument.
+	(octave_user_function * octave_call_stack::do_caller_user_function
+	(difference_type) const): Ditto.
+	(octave_user_code * octave_call_stack::do_caller_user_code
+	(difference_type) const): Ditto.
+	(static octave_user_script *caller_script (difference_type)):
+	Ditto.
+	(static octave_user_function *caller_user_function
+	(difference_type q)): Ditto.
+	(static octave_user_code *caller_user_code (difference_type q)):
+	Ditto.
+
 2008-05-20  Kim Hansen  <kimhanse@gmail.com>
 
 	* load-path.cc (load_path::do_initialize):
--- a/src/debug.cc	Tue May 20 16:49:02 2008 -0400
+++ b/src/debug.cc	Tue May 13 21:12:12 2008 +0200
@@ -380,6 +380,9 @@
 
   parse_dbfunction_params ("dbstop", args, symbol_name, lines);
 
+  if (lines.size () == 0)
+    lines[0] = 1;
+
   if (! error_state)
     retval = bp_table::add_breakpoint (symbol_name, lines);
 
@@ -833,6 +836,155 @@
   return retval;
 }
 
+DEFCMD (dbstep, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Command} {} dbstep @var{n}\n\
+@deftypefnx {Command} {} dbstep in\n\
+@deftypefnx {Command} {} dbstep out\n\
+In debugging mode, execute the next @var{n} lines of code. If @var{n} is\n\
+omitted execute the next line of code. If the next line of code is itself\n\
+defined in terms of an m-file remain in the existing function.\n\
+\n\
+Using @code{dbstep in} will cause execution of the next line to step into\n\
+any m-files defined on the next line. Using @code{dbstep out} with cause\n\
+execution to continue until the current function returns.\n\
+@seealso{dbcont, dbquit}\n\
+@end deftypefn")
+{
+  if (Vdebugging)
+    {
+      int nargin = args.length ();
+      
+      if (nargin > 1)
+	print_usage ();
+      else if (nargin == 1 && args(0).is_string ())
+	{
+	  std::string arg = args(0).string_value ();
+
+	  if (! error_state)
+	    {
+	      if (arg == "in")
+		{
+		  Vdebugging = false;
+
+		  tree::break_next = 0;
+
+		  tree::last_line = 0;
+
+		  tree::break_function = octave_call_stack::caller_user_code ();
+		}
+	      else if (arg == "out")
+		{
+		  Vdebugging = false;
+
+		  tree::break_next = 0;
+
+		  tree::last_line = -1;
+
+		  // Next to skip 2 here. One for the oct-file dbstep and 
+		  // another for the function we actually want to step out of.
+		  tree::break_function = octave_call_stack::caller_user_code (2);
+		}
+	      else
+		{
+		  int n = atoi (arg.c_str ());
+
+		  Vdebugging = false;
+
+		  if (n < 0)
+		    tree::break_next = 0;
+		  else
+		    tree::break_next = n;
+
+		  tree::last_line = Vdebugging_current_line;
+		  
+		  tree::break_function = octave_call_stack::caller_user_code ();
+		}
+	    }
+	}
+      else
+	{
+	  Vdebugging = false;
+
+	  tree::break_next = 0;
+
+	  tree::last_line = Vdebugging_current_line;
+		  
+	  tree::break_function = octave_call_stack::caller_user_code ();
+	}
+    }
+  else
+    error ("dbstep: can only be called in debug mode");
+
+  return octave_value_list ();
+}
+
+DEFCMD (dbcont, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Command} {} dbcont ()\n\
+In debugging mode, quit debugging mode and continue execution.\n\
+@seealso{dbstep, dbstep}\n\
+@end deftypefn")
+{
+  if (Vdebugging)
+    if (args.length() == 0)
+      Vdebugging = false;
+    else
+      print_usage ();
+  else
+    error ("dbcont: can only be called in debug mode");
+
+  return octave_value_list ();
+}
+
+DEFCMD (dbquit, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Command} {} dbquit ()\n\
+In debugging mode, quit debugging mode and return to the top level.\n\
+@seealso{dbstep, dbcont}\n\
+@end deftypefn")
+{
+  if (Vdebugging)
+    if (args.length() == 0)
+      octave_throw_interrupt_exception ();
+    else
+      print_usage ();
+  else
+    error ("dbquit: can only be called in debug mode");
+
+  return octave_value_list ();
+}
+
+DEFCMD (dbnext, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Command} {} dbquit ()\n\
+In debugging mode, execute the next line of code without stepping in to\n\
+functions. This is synonymous with @code{dbstep}.\n\
+@seealso{dbstep, dbcont, dbquit}\n\
+@end deftypefn")
+{
+  if (Vdebugging)
+    {
+    if (args.length() == 0)
+      {
+	Vdebugging = false;
+
+	tree::break_next = 0;
+
+	tree::last_line = Vdebugging_current_line;
+		  
+	tree::break_function = octave_call_stack::caller_user_code ();
+      }
+    else
+      print_usage ();
+    }
+  else
+    error ("dbnext: can only be called in debug mode");
+
+  return octave_value_list ();
+}
+
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/input.cc	Tue May 20 16:49:02 2008 -0400
+++ b/src/input.cc	Tue May 13 21:12:12 2008 +0200
@@ -147,6 +147,9 @@
 // TRUE if we are in debugging mode.
 bool Vdebugging = false;
 
+// The current line that we are debugging
+int Vdebugging_current_line = -1;
+
 // TRUE if we are running in the Emacs GUD mode.
 static bool Vgud_mode = false;
 
@@ -566,21 +569,78 @@
   command_editor::set_quoting_function (quoting_filename);
 }
 
-static bool
-match_sans_spaces_semi (const std::string& standard, const std::string& test)
+static void
+get_debug_input (const std::string& prompt)
 {
-  size_t beg = test.find_first_not_of (" \t");
+  octave_user_code *caller = octave_call_stack::caller_user_code ();
+  std::string nm;
+
+  if (caller)
+    {
+      nm = caller->fcn_file_name ();
+
+      if (nm.empty ())
+	nm = caller->name ();
+
+      Vdebugging_current_line = octave_call_stack::current_line ();
+    }
+  else
+    Vdebugging_current_line = -1;
 
-  if (beg != NPOS)
+  std::ostringstream buf;
+
+  if (! nm.empty ())
     {
-      size_t end = test.find_last_not_of ("; \t");
+      if (Vgud_mode)
+	{
+	  static char ctrl_z = 'Z' & 0x1f;
 
-      size_t len = end == NPOS ? NPOS : end - beg + 1;
+	  buf << ctrl_z << ctrl_z << nm << ":" << Vdebugging_current_line;
+	}
+      else
+	{
+	  buf << "stopped in " << nm;
 
-      return (test.substr (beg, len) == standard);
+	  if (Vdebugging_current_line > 0)
+	    buf << " at line " << Vdebugging_current_line;
+	}
     }
 
-  return false;
+  std::string msg = buf.str ();
+
+  if (! msg.empty ())
+    message (Vgud_mode ? 0 : "keyboard", msg.c_str ());
+
+  unwind_protect::begin_frame ("get_debug_input");
+
+  unwind_protect_str (VPS1);
+  VPS1 = prompt;
+
+  while (Vdebugging)
+    {
+      reset_error_handler ();
+
+      reset_parser ();
+
+      // This is the same as yyparse in parse.y.
+      int retval = octave_parse ();
+
+      if (retval == 0 && global_command)
+	{
+	  global_command->eval ();
+
+	  delete global_command;
+
+	  global_command = 0;
+
+	  OCTAVE_QUIT;
+
+	  if (octave_completion_matches_called)
+	    octave_completion_matches_called = false;	    
+	}
+    }
+
+  unwind_protect::run_frame ("get_debug_input");
 }
 
 // If the user simply hits return, this will produce an empty matrix.
@@ -597,63 +657,14 @@
   if (nargin == 2)
     read_as_string++;
 
-  std::string nm;
-  int line = -1;
-
-  if (Vdebugging)
-    {
-      octave_user_code *caller = octave_call_stack::caller_user_code ();
-
-      if (caller)
-	{
-	  nm = caller->fcn_file_name ();
-
-	  if (nm.empty ())
-	    nm = caller->name ();
-
-	  line = octave_call_stack::current_line ();
-	}
-    }
-
-  std::ostringstream buf;
-
-  if (! nm.empty ())
-    {
-      if (Vgud_mode)
-	{
-	  static char ctrl_z = 'Z' & 0x1f;
+  std::string prompt = args(0).string_value ();
 
-	  buf << ctrl_z << ctrl_z << nm << ":" << line;
-	}
-      else
-	{
-	  buf << "stopped in " << nm;
-
-	  if (line > 0)
-	    buf << " at line " << line;
-	}
+  if (error_state)
+    {
+      error ("input: unrecognized argument");
+      return retval;
     }
 
-  std::string msg = buf.str ();
-
-  if (! msg.empty ())
-    message (Vgud_mode ? 0 : "keyboard", msg.c_str ());
-
-  std::string prompt = "debug> ";
-
-  if (nargin > 0)
-    {
-      prompt = args(0).string_value ();
-
-      if (error_state)
-	{
-	  error ("input: unrecognized argument");
-	  return retval;
-	}
-    }
-
- again:
-
   flush_octave_stdout ();
 
   octave_diary << prompt;
@@ -673,43 +684,7 @@
 	octave_diary << "\n";
 
       if (len < 1)
-	{
-	  if (Vdebugging)
-	    goto again;
-	  else
-	    return read_as_string ? octave_value ("") : octave_value (Matrix ());
-	}
-
-      if (Vdebugging)
-	{
-	  if (match_sans_spaces_semi ("exit", input_buf)
-	      || match_sans_spaces_semi ("quit", input_buf)
-	      || match_sans_spaces_semi ("return", input_buf)
-	      || match_sans_spaces_semi ("dbcont", input_buf))
-	    {
-	      return retval;
-	    }
-	  else if (match_sans_spaces_semi ("dbstep", input_buf))
-	    {
-	      tree::break_next = true;
-
-	      tree::last_line = 0;
-
-	      tree::break_function = octave_call_stack::current ();
-
-	      return retval;
-	    }
-	  else if (match_sans_spaces_semi ("dbnext", input_buf))
-	    {
-	      tree::break_next = true;
-
-	      tree::last_line = octave_call_stack::current_line ();
-
-	      tree::break_function = octave_call_stack::current ();
-
-	      return retval;
-	    }
-	}
+	return read_as_string ? octave_value ("") : octave_value (Matrix ());
 
       if (read_as_string)
 	{
@@ -723,9 +698,7 @@
 	{
 	  int parse_status = 0;
 
-	  bool silent = ! Vdebugging;
-
-	  retval = eval_string (input_buf, silent, parse_status, nargout);
+	  retval = eval_string (input_buf, true, parse_status, nargout);
 
 	  if (! Vdebugging && retval.length () == 0)
 	    retval(0) = Matrix ();
@@ -734,19 +707,6 @@
   else
     error ("input: reading user-input failed!");
 
-  if (Vdebugging)
-    {
-      // Clear error_state so that if errors were encountered while
-      // evaluating user input, extra error messages will not be
-      // printed after we return.
-
-      reset_error_handler ();
-
-      retval = octave_value_list ();
-
-      goto again;
-    }
-
   return retval;
 }
 
@@ -895,9 +855,12 @@
   Vsaving_history = true;
   Vdebugging = true;
 
-  octave_value_list tmp = get_user_input (args, 0);
+  std::string prompt = "debug> ";
+  if (nargin > 0)
+    prompt = args(0).string_value ();
 
-  retval = tmp(0);
+  if (! error_state)
+    get_debug_input (prompt);
 
   unwind_protect::run_frame ("do_keyboard");
 
--- a/src/input.h	Tue May 20 16:49:02 2008 -0400
+++ b/src/input.h	Tue May 13 21:12:12 2008 +0200
@@ -91,6 +91,9 @@
 // TRUE if we are in debugging mode.
 extern bool Vdebugging;
 
+// The current line that we are debugging
+extern int Vdebugging_current_line;
+
 extern std::string gnu_readline (const std::string& s, bool force_readline = false);
 
 extern void initialize_command_input (void);
--- a/src/parse.y	Tue May 20 16:49:02 2008 -0400
+++ b/src/parse.y	Tue May 13 21:12:12 2008 +0200
@@ -2216,11 +2216,20 @@
   int l = return_tok->line ();
   int c = return_tok->column ();
 
-  if (lexer_flags.defining_func || reading_script_file
-      || evaluating_function_body)
-    retval = new tree_return_command (l, c);
+  if (Vdebugging)
+    {
+      Vdebugging = false;
+
+      retval = new tree_no_op_command ("return", l, c);
+    }
   else
-    retval = new tree_no_op_command ("return", l, c);
+    {
+      if (lexer_flags.defining_func || reading_script_file
+          || evaluating_function_body)
+        retval = new tree_return_command (l, c);
+      else
+        retval = new tree_no_op_command ("return", l, c);
+    }
 
   return retval;
 }
--- a/src/pt-bp.h	Tue May 20 16:49:02 2008 -0400
+++ b/src/pt-bp.h	Tue May 13 21:12:12 2008 +0200
@@ -166,31 +166,40 @@
       octave_function *xfcn = octave_call_stack::current (); \
  \
       if (octave_debug_on_interrupt_state \
-	  || (tree::break_next && tree::last_line == 0) \
-	  || (tree::break_next \
+	  || (tree::break_next >= 0 && tree::last_line == 0) \
+	  || (tree::break_next >= 0 \
 	      && xfcn == tree::break_function \
 	      && tree::last_line != line ()) \
 	  || is_breakpoint ()) \
         { \
-          octave_debug_on_interrupt_state = false; \
+	  if (!octave_debug_on_interrupt_state && tree::break_next > 0) \
+	    { \
+	      tree::break_next--; \
+	      if (tree::last_line > 0) \
+		tree::last_line = line(); \
+	    } \
+	  else \
+	    { \
+              octave_debug_on_interrupt_state = false; \
  \
-          tree::break_next = false; \
- \
-          if (xfcn) \
-            octave_stdout << xfcn->name () << ": ";  \
+              tree::break_next = -1; \
  \
-          octave_stdout << "line " << line () << ", " \
-			<< "column " << column () \
-			<< std::endl; \
+              if (xfcn) \
+                octave_stdout << xfcn->name () << ": ";  \
+ \
+              octave_stdout << "line " << line () << ", " \
+			    << "column " << column () \
+			    << std::endl; \
  \
-          tree_print_code tpc (octave_stdout); \
-          this->accept (tpc); \
+              tree_print_code tpc (octave_stdout); \
+              this->accept (tpc); \
+ \
+              octave_stdout << std::endl; \
  \
-          octave_stdout << std::endl; \
+              tree::break_statement = this; \
  \
-          tree::break_statement = this; \
- \
-          do_keyboard (); \
+              do_keyboard (); \
+	    } \
         } \
     } \
   while (0)
--- a/src/pt.cc	Tue May 20 16:49:02 2008 -0400
+++ b/src/pt.cc	Tue May 13 21:12:12 2008 +0200
@@ -33,8 +33,8 @@
 #include "pt.h"
 #include "pt-pr-code.h"
 
-// If true, stop executing at the next possible point.
-bool tree::break_next = false;
+// If zero, stop executing at the next possible point.
+int tree::break_next = -1;
 
 // The line where dbnext was executed.
 int tree::last_line = 0;
--- a/src/pt.h	Tue May 20 16:49:02 2008 -0400
+++ b/src/pt.h	Tue May 13 21:12:12 2008 +0200
@@ -66,7 +66,7 @@
     { return break_point; }
 
   // If true, stop executing at the next possible point.
-  static bool break_next;
+  static int break_next;
   
   // The line where dbnext was executed.
   static int last_line; 
--- a/src/toplev.cc	Tue May 20 16:49:02 2008 -0400
+++ b/src/toplev.cc	Tue May 13 21:12:12 2008 +0200
@@ -112,11 +112,11 @@
 }
 
 octave_user_script *
-octave_call_stack::do_caller_user_script (void) const
+octave_call_stack::do_caller_user_script (difference_type q) const
 {
   octave_user_script *retval = 0;
 
-  for (const_iterator p = cs.begin (); p != cs.end (); p++)
+  for (const_iterator p = cs.begin () + q; p != cs.end (); p++)
     {
       const call_stack_elt& elt = *p;
 
@@ -133,11 +133,11 @@
 }
 
 octave_user_function *
-octave_call_stack::do_caller_user_function (void) const
+octave_call_stack::do_caller_user_function (difference_type q) const
 {
   octave_user_function *retval = 0;
 
-  for (const_iterator p = cs.begin (); p != cs.end (); p++)
+  for (const_iterator p = cs.begin () + q; p != cs.end (); p++)
     {
       const call_stack_elt& elt = *p;
 
@@ -154,11 +154,11 @@
 }
 
 octave_user_code *
-octave_call_stack::do_caller_user_code (void) const
+octave_call_stack::do_caller_user_code (difference_type q) const
 {
   octave_user_code *retval = 0;
 
-  for (const_iterator p = cs.begin (); p != cs.end (); p++)
+  for (const_iterator p = cs.begin () + q; p != cs.end (); p++)
     {
       const call_stack_elt& elt = *p;
 
--- a/src/toplev.h	Tue May 20 16:49:02 2008 -0400
+++ b/src/toplev.h	Tue May 13 21:12:12 2008 +0200
@@ -94,6 +94,7 @@
 
   typedef std::deque<call_stack_elt>::iterator iterator;
   typedef std::deque<call_stack_elt>::const_iterator const_iterator;
+  typedef std::deque<call_stack_elt>::difference_type difference_type;
 
   static bool instance_ok (void)
   {
@@ -149,21 +150,21 @@
   }
   
   // First script on the stack.
-  static octave_user_script *caller_script (void)
+  static octave_user_script *caller_script (difference_type q = 0)
   {
-    return instance_ok () ? instance->do_caller_user_script () : 0;
+    return instance_ok () ? instance->do_caller_user_script (q) : 0;
   }
 
   // First user-defined function on the stack.
-  static octave_user_function *caller_user_function (void)
+  static octave_user_function *caller_user_function (difference_type q = 0)
   {
-    return instance_ok () ? instance->do_caller_user_function () : 0;
+    return instance_ok () ? instance->do_caller_user_function (q) : 0;
   }
 
   // First user-defined function on the stack.
-  static octave_user_code *caller_user_code (void)
+  static octave_user_code *caller_user_code (difference_type q = 0)
   {
-    return instance_ok () ? instance->do_caller_user_code () : 0;
+    return instance_ok () ? instance->do_caller_user_code (q) : 0;
   }
 
   static void
@@ -251,11 +252,11 @@
     return retval;
   }
 
-  octave_user_script *do_caller_user_script (void) const;
+  octave_user_script *do_caller_user_script (difference_type q = 0) const;
 
-  octave_user_function *do_caller_user_function (void) const;
+  octave_user_function *do_caller_user_function (difference_type q = 0) const;
 
-  octave_user_code *do_caller_user_code (void) const;
+  octave_user_code *do_caller_user_code (difference_type q = 0) const; 
 
   void do_push (octave_function *f, symbol_table::scope_id scope,
 		symbol_table::context_id context)