octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Changeset]: filemarker and fix for 'dbstep in'


From: David Bateman
Subject: [Changeset]: filemarker and fix for 'dbstep in'
Date: Sun, 25 May 2008 15:44:35 +0200
User-agent: Thunderbird 2.0.0.12 (X11/20080306)

The attached changeset fixes a bug my previous debug patch introduced
and adds the filemarker function that is also useful for debugging. The
bug was that the "dbstep in" command executed parts of the line
individually rather than prevent the next breakpoint before the next
line of executed of the function, as occurs with "dbstep", etc.

The filemarker command itself is trivial, however it is then used to
identify subfunctions. Consider that you have a function

# string 1
function z = testfun (x)
# string 2
  y = 1;
  z = testfun2 (x, y);
end
# string 3
function z = testfun2 (x, y)
# string 4
  z = x + y;
end

then filemarker can be used like

help (["testfun", filemarker, "testfun2"])

or knowing that filemarker is by default ">", then

help testfun>testfun2

gives the same result. Other uses include in dbstop to set a breakpoint
in a subfunction, for example

dbstop testfun>testfun2

set the breakpoint at the first line of the testfun2 subfunction. I also
adapted the backtrace method so that dbstack gives the name of the
subfunctions including their parent functions..

Note that the symbol_table:;find_function method will have to be adapted
if we ever decide to implement nested functions as matlab stupidly uses
the filesep character to define the nesting rather than the filemarker
character. That is, if we have a function like

function f1
  function f2
  end
  function f3
  end
end
function f2
end

then to set breakpoints in each of these functions is done like

dbstop f1
dbstop f1>f1/f2
dbstop f1>f3
dbstop f1>f2

If matlab had used filemarker instead of filesep for the nesting, then
the current adaptation of symbol_table::find_function would already be
correct.

Note that I allowed the filemarker character to be set, but prevented it
from being set to a valid character for a function name. Matlab doesn't
allow filemarker to be set. Also note that on all platforms I tested
filemarker was ">" in Matlab (linux and windows), so I believe that the
default is always ">" though Matlab on a Mac might have a different value.

D.

# HG changeset patch
# User David Bateman <address@hidden>
# Date 1211720677 -7200
# Node ID ef5cfe89cc62152250d60e65f665500d662259e7
# Parent  0a4a6667a2cd85eecc6bba0ebef8c20583131f7c
Add Ffilemarker and fix for 'dbstep in'

diff --git a/src/ChangeLog b/src/ChangeLog
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,29 @@ 2008-05-21  David Bateman  <address@hidden
+2008-05-24  David Bateman  <address@hidden>
+
+       * pt.cc (tree:last_break_function): Next pointer to last function
+       with a breakpoint.
+       * pt.h (tree:last_break_function): ditto.
+       * debug.cc (Fdbstep): Use tree::break_function value of zero to
+       signal to step into the next function. Set tree::last_break_function
+       to indicate position of last breakpoint.
+       (Fdbnext):  Set tree::last_break_function to indicate position of
+       last breakpoint.
+       * pt-bp.h (MAYBE_DO_BREAKPOINT): Check tree::break_function value
+       of zero as well. Only check tree::last_line if we are in teh same
+       function as the last breakpoint.
+       * input.cc (char Vfilemarker): New global variable.
+       (Ffilemarker): New function to query and set Vfilemarker.
+       * input.h (extern char Vfilemarker): Make Vfilemarker available.
+       * util.cc (fcn_file_in_path): If the input argument contains
+       Vfilemarker, strip the trailing part of string from this point
+       when looking for function file.
+       * toplev.cc (octave_call_stack::fo_backtrace): Mark subfunctions
+       with the name of the parent function and Vfilemarker.
+       * symtab.cc (symbol_table::find_function (const std::string&,
+       tree_argument_list *, const string_vector&, octave_value_list*,
+       bool&): If function name contains Vfilemarker, check in scope of
+       specified parent function.
+
 2008-05-21  David Bateman  <address@hidden>
 
        * DLD-FUNCTIONS/quad.cc (quad_float_user_function): New function.
diff --git a/src/debug.cc b/src/debug.cc
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -869,9 +869,12 @@ execution to continue until the current 
 
                  tree::break_next = 0;
 
-                 tree::last_line = 0;
-
-                 tree::break_function = octave_call_stack::caller_user_code ();
+                 tree::last_line = Vdebugging_current_line;
+
+                 tree::break_function = 0;
+
+                 tree::last_break_function = 
+                   octave_call_stack::caller_user_code ();
                }
              else if (arg == "out")
                {
@@ -883,7 +886,11 @@ execution to continue until the current 
 
                  // 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);
+                 tree::break_function = 
+                   octave_call_stack::caller_user_code (2);
+
+                 tree::last_break_function = 
+                   octave_call_stack::caller_user_code ();
                }
              else
                {
@@ -899,6 +906,9 @@ execution to continue until the current 
                  tree::last_line = Vdebugging_current_line;
                  
                  tree::break_function = octave_call_stack::caller_user_code ();
+
+                 tree::last_break_function = 
+                   octave_call_stack::caller_user_code ();
                }
            }
        }
@@ -911,6 +921,9 @@ execution to continue until the current 
          tree::last_line = Vdebugging_current_line;
                  
          tree::break_function = octave_call_stack::caller_user_code ();
+
+         tree::last_break_function = 
+           octave_call_stack::caller_user_code ();
        }
     }
   else
@@ -974,6 +987,8 @@ functions. This is synonymous with @code
        tree::last_line = Vdebugging_current_line;
                  
        tree::break_function = octave_call_stack::caller_user_code ();
+
+       tree::last_break_function = octave_call_stack::caller_user_code ();
       }
     else
       print_usage ();
diff --git a/src/input.cc b/src/input.cc
--- a/src/input.cc
+++ b/src/input.cc
@@ -153,6 +153,9 @@ int Vdebugging_current_line = -1;
 // TRUE if we are running in the Emacs GUD mode.
 static bool Vgud_mode = false;
 
+// The filemarker used to separate filenames from subfunction names
+char Vfilemarker = '>';
+
 static void
 do_input_echo (const std::string& input_string)
 {
@@ -1333,6 +1336,44 @@ Undocumented internal function.\n\
   return retval;
 }
 
+DEFUN (filemarker, args, nargout,
+  "-*- texinfo -*-\n\
address@hidden {Built-in Function} {} filemarker ()\n\
+Returns or sets the character used to separate filename from the\n\
+the subfunction names contained within the file. This can be used in\n\
+a generic manner to interact with subfunctions. For example\n\
+\n\
address@hidden
+help ([\"myfunc\", filemarker, \"mysubfunc\"])\n\
address@hidden example\n\
+\n\
address@hidden
+returns the help string associated with the sub-function @code{mysubfunc}\n\
+of the function @code{myfunc}. Another use of @code{filemarker} is when\n\
+debugging it allows easier placement of breakpoints within sub-functions.\n\
+For example\n\
+\n\
address@hidden
+dbstop ([\"myfunc\", filemarker, \"mysubfunc\"])\n\
address@hidden example\n\
+\n\
address@hidden
+will set a breakpoint at the first line of the subfunction @code{mysubfunc}.\n\
address@hidden deftypefn")
+{
+  char tmp = Vfilemarker;
+  octave_value retval = SET_INTERNAL_VARIABLE (filemarker);
+
+  // The character passed must not be a legal character for a function name
+  if (! error_state && (::isalnum (Vfilemarker) || Vfilemarker == '_'))
+    {
+      Vfilemarker = tmp;
+      error ("filemarker: character can not be a valid character for a 
function name");
+    }
+
+  return retval;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
diff --git a/src/input.h b/src/input.h
--- a/src/input.h
+++ b/src/input.h
@@ -104,6 +104,8 @@ extern octave_value do_keyboard (const o
 
 extern std::string VPS4;
 
+extern char Vfilemarker;
+
 enum echo_state
 {
   ECHO_OFF = 0,
diff --git a/src/pt-bp.h b/src/pt-bp.h
--- a/src/pt-bp.h
+++ b/src/pt-bp.h
@@ -166,10 +166,9 @@ extern bool octave_debug_on_interrupt_st
       octave_function *xfcn = octave_call_stack::current (); \
  \
       if (octave_debug_on_interrupt_state \
-         || (tree::break_next >= 0 && tree::last_line == 0) \
          || (tree::break_next >= 0 \
-             && xfcn == tree::break_function \
-             && tree::last_line != line ()) \
+             && (tree::break_function == 0 || tree::break_function == xfcn) \
+             && (tree::last_break_function != xfcn || tree::last_line != line 
())) \
          || is_breakpoint ()) \
         { \
          if (!octave_debug_on_interrupt_state && tree::break_next > 0) \
diff --git a/src/pt.cc b/src/pt.cc
--- a/src/pt.cc
+++ b/src/pt.cc
@@ -40,6 +40,9 @@ int tree::last_line = 0;
 int tree::last_line = 0;
 
 // The function where the last breakpoint occurred.
+const octave_function *tree::last_break_function = 0;
+
+// The function where the next breakpoint is request.
 const octave_function *tree::break_function = 0;
 
 // The statement where the last breakpoint occurred.
diff --git a/src/pt.h b/src/pt.h
--- a/src/pt.h
+++ b/src/pt.h
@@ -72,6 +72,9 @@ public:
   static int last_line; 
 
   // The function where the last breakpoint occurred.
+  static const octave_function *last_break_function;
+
+  // The function where the next breakpoint is request.
   static const octave_function *break_function;
 
   // The statement where the last breakpoint occurred.
diff --git a/src/symtab.cc b/src/symtab.cc
--- a/src/symtab.cc
+++ b/src/symtab.cc
@@ -792,7 +792,32 @@ symbol_table::find_function (const std::
                             octave_value_list& evaluated_args,
                             bool& args_evaluated)
 {
-  return find (name, args, arg_names, evaluated_args, args_evaluated, true);
+  octave_value retval;
+  size_t pos = name.find_first_of (Vfilemarker);
+
+  if (pos == NPOS)
+    retval = find (name, args, arg_names, evaluated_args, args_evaluated, 
true);
+  else
+    {
+      std::string fcn_scope = name.substr(0, pos);
+      scope_id stored_scope = xcurrent_scope;
+      xcurrent_scope = xtop_scope;
+      octave_value parent = find_function (name.substr(0, pos));
+      if (parent.is_defined ())
+       {
+         octave_function *parent_fcn = parent.function_value ();
+         if (parent_fcn)
+           {
+             xcurrent_scope = parent_fcn->scope ();
+             if (xcurrent_scope > 1)
+               retval = find_function (name.substr (pos + 1), args, arg_names, 
+                                       evaluated_args, args_evaluated);
+           }
+       }
+      xcurrent_scope = stored_scope;
+    }
+
+  return retval;
 }
 
 void
diff --git a/src/toplev.cc b/src/toplev.cc
--- a/src/toplev.cc
+++ b/src/toplev.cc
@@ -213,7 +213,11 @@ octave_call_stack::do_backtrace (int n) 
          if (f)
            {
              file(k) = f->fcn_file_name ();
-             name(k) = f->name ();
+             std::string parent_fcn_name = f->parent_fcn_name ();
+             if (parent_fcn_name == std::string ())
+               name(k) = f->name ();
+             else
+               name(k) = f->parent_fcn_name () + Vfilemarker + f->name ();
 
              tree_statement *stmt = elt.stmt;
 
diff --git a/src/utils.cc b/src/utils.cc
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -435,7 +435,14 @@ fcn_file_in_path (const std::string& nam
       else if (len > 2 && name [len - 2] == '.' && name [len - 1] == 'm')
        retval = load_path::find_fcn_file (name.substr (0, len-2));
       else
-       retval = load_path::find_fcn_file (name);
+       {
+         std::string fname = name;
+         size_t pos = name.find_first_of (Vfilemarker);
+         if (pos != NPOS)
+           fname = name.substr (0, pos);
+
+         retval = load_path::find_fcn_file (fname);
+       }
     }
 
   return retval;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]