[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Proposed patch for external debugger access
From: |
John Swensen |
Subject: |
Re: Proposed patch for external debugger access |
Date: |
Tue, 30 Oct 2007 08:15:44 -0400 |
User-agent: |
Thunderbird 2.0.0.6 (Macintosh/20070728) |
John W. Eaton wrote:
On 29-Oct-2007, John Swensen wrote:
| I fixed up these suggestions also. The patches are attached.
| Index: debug.cc
| ===================================================================
| RCS file: /cvs/octave/src/debug.cc,v
| retrieving revision 1.26
| diff -r1.26 debug.cc
| 22d21
| <
| 29a29,30
| > #include <set>
| >
Thanks, can you please send a context diff?
jwe
Sorry, I forgot the -uN option to cvs diff this last time. Attached are
the context sensitive patches.
John
Index: debug.cc
===================================================================
RCS file: /cvs/octave/src/debug.cc,v
retrieving revision 1.26
diff -u -r1.26 debug.cc
--- debug.cc 12 Oct 2007 21:27:29 -0000 1.26
+++ debug.cc 30 Oct 2007 12:14:16 -0000
@@ -19,7 +19,6 @@
<http://www.gnu.org/licenses/>.
*/
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -27,9 +26,12 @@
#include <iostream>
#include <fstream>
#include <string>
+#include <set>
+
#include "defun.h"
#include "error.h"
+#include "help.h"
#include "input.h"
#include "pager.h"
#include "oct-obj.h"
@@ -40,6 +42,8 @@
#include "ov.h"
#include "ov-usr-fcn.h"
#include "ov-fcn.h"
+#include "ov-list.h"
+#include "ov-struct.h"
#include "pt-pr-code.h"
#include "pt.h"
#include "pt-bp.h"
@@ -48,12 +52,16 @@
#include "unwind-prot.h"
#include "variables.h"
+#include "debug.h"
+
+// Initialize the singleton object
+bp_table *bp_table::instance = NULL;
+
// Return a pointer to the user-defined function FNAME. If FNAME is
// empty, search backward for the first user-defined function in the
// current call stack.
-
static octave_user_function *
-get_user_function (std::string fname = "")
+get_user_function (const std::string& fname = "")
{
octave_user_function *dbg_fcn = 0;
@@ -71,7 +79,6 @@
else
{
ptr = lookup_by_name (fname, false);
-
if (ptr && ptr->is_user_function ())
{
octave_value tmp = ptr->def ();
@@ -83,102 +90,277 @@
return dbg_fcn;
}
-
-DEFCMD (dbstop, args, ,
- "-*- texinfo -*-\n\
address@hidden {Loadable Function} {rline =} dbstop (func, line, @dots{})\n\
-Set a breakpoint in a function\n\
address@hidden @code\n\
address@hidden func\n\
-String representing the function name. When already in debug\n\
-mode this should be left out and only the line should be given.\n\
address@hidden line\n\
-Line you would like the breakpoint to be set on. Multiple\n\
-lines might be given as separate arguments or as a vector.\n\
address@hidden table\n\
-\n\
-The rline returned is the real line that the breakpoint was set at.\n\
address@hidden, dbstatus, dbnext}\n\
address@hidden deftypefn")
+static void
+parse_dbfunction_params (const octave_value_list& args,
+ std::string& symbol_name,
+ intmap& lines)
{
- octave_value retval;
+ octave_idx_type len = 0;
int nargin = args.length ();
int idx = 0;
- std::string symbol_name = "";
+ int list_idx = 0;
+ symbol_name = std::string ();
- if (nargin != 1 && args(0).is_string())
+ // If we are already in a debugging function
+ if (octave_call_stack::caller_user_function () != NULL)
{
- symbol_name = args(0).string_value ();
+ idx = 0;
+ }
+ else
+ {
+ symbol_name = args (0).string_value ();
+ if (error_state)
+ return;
idx = 1;
}
- octave_user_function *dbg_fcn = get_user_function (symbol_name);
-
- if (dbg_fcn)
+ for (int i = idx; i < nargin; i++ )
{
- octave_idx_type nsize = 10;
- RowVector results (nsize);
- octave_idx_type nr = 0;
-
- tree_statement_list *cmds = dbg_fcn->body ();
+ if (args (i).is_string ())
+ len += 1;
+ else
+ len += args (i).numel ();
+ }
- for (int i = idx; i < nargin; i++)
+ lines = intmap();
+ for (int i = idx; i < nargin; i++ )
+ {
+ if (args (i).is_string ())
+ {
+ int line = atoi (args (i).string_value ().c_str ());
+ if (error_state)
+ break;
+ lines[list_idx++] = line;
+ }
+ else
{
- if (args(i).is_string ())
+ const NDArray arg = args (i).array_value ();
+
+ if (error_state)
+ break;
+
+ for (octave_idx_type j = 0; j < arg.nelem(); j++)
{
- int line = atoi (args(i).string_value ().c_str ());
-
+ int line = static_cast<int> (arg.elem (j));
if (error_state)
break;
+ lines[list_idx++] = line;
+ }
+
+ if (error_state)
+ break;
+ }
+ }
+}
- if (nr == nsize)
- {
- nsize *= 2;
- results.resize (nsize);
- }
+intmap
+bp_table::add_breakpoint (const std::string& fname,
+ const intmap& line)
+{
+ if (!instance_ok ())
+ return intmap();
- results(nr++) = cmds->set_breakpoint (line);
- }
- else
+ octave_idx_type len = line.size ();
+ intmap retval;
+ octave_user_function *dbg_fcn = get_user_function (fname);
+
+ if (dbg_fcn)
+ {
+ tree_statement_list *cmds = dbg_fcn->body ();
+ for (int i = 0; i < len; i++)
+ {
+ intmap::const_iterator p = line.find (i);
+ if (p != line.end ())
{
- const NDArray arg = args(i).array_value ();
+ int lineno = p->second;
+ retval[i] = cmds->set_breakpoint (lineno);
+ if (retval[i] != 0)
+ instance->bp_map[fname] = dbg_fcn;
+ }
+ }
+ }
+ else
+ error ("add_breakpoint: unable to find the function requested\n");
- if (error_state)
- break;
+ return retval;
+}
- for (octave_idx_type j = 0; j < arg.nelem(); j++)
- {
- int line = static_cast<int> (arg.elem (j));
- if (error_state)
- break;
+int
+bp_table::remove_breakpoint (const std::string& fname,
+ const intmap& line)
+{
+ if (!instance_ok ())
+ return 0;
- if (nr == nsize)
- {
- nsize *= 2;
- results.resize (nsize);
- }
+ octave_idx_type len = line.size ();
+ int retval = 0;
- results(nr++) = cmds->set_breakpoint (line);
+ if (len == 0)
+ {
+ intmap results = remove_all_breakpoints_in_file (fname);
+ retval = results.size ();
+ }
+ else
+ {
+ octave_user_function *dbg_fcn = get_user_function (fname);
+ if (dbg_fcn)
+ {
+ tree_statement_list *cmds = dbg_fcn->body ();
+ for (int i = 0; i < len; i++)
+ {
+ intmap::const_iterator p = line.find (i);
+ if (p != line.end ())
+ {
+ int lineno = p->second;
+ cmds->delete_breakpoint (lineno);
}
-
- if (error_state)
- break;
}
+ octave_value_list results = cmds->list_breakpoints ();
+ if (results.length () == 0)
+ instance->bp_map.erase (instance->bp_map.find (fname));
+ retval = results.length ();
}
+ else
+ error ("remove_breakpoint: unable to find the function requested\n");
+ }
+ return retval;
+}
+
+
+intmap
+bp_table::remove_all_breakpoints_in_file (const std::string& fname)
+{
+ if (!instance_ok ())
+ return intmap();
- if (! error_state)
+ octave_value_list bkpts;
+ intmap retval;
+ octave_user_function *dbg_fcn = get_user_function (fname);
+
+ if (dbg_fcn)
+ {
+ tree_statement_list *cmds = dbg_fcn->body ();
+ bkpts = cmds->list_breakpoints ();
+ for (int i = 0; i < bkpts.length (); i++)
{
- results.resize (nr);
- retval = results;
+ int lineno = static_cast<int> (bkpts (i).int_value ());
+ cmds->delete_breakpoint (lineno);
+ retval[i] = lineno;
}
+ instance->bp_map.erase (instance->bp_map.find (fname));
}
else
- error ("dbstop: unable to find the function requested\n");
+ error ("remove_all_breakpoint_in_file: "
+ "unable to find the function requested\n");
+
+ return retval;
+}
+
+
+void
+bp_table::remove_all_breakpoints (void)
+{
+ if (!instance_ok ())
+ return;
+
+ std::map< std::string, octave_user_function* >::iterator it;
+ for (it = instance->bp_map.begin (); it != instance->bp_map.end (); it++)
+ {
+ remove_all_breakpoints_in_file (it->first);
+ }
+}
+
+std::string
+do_find_bkpt_list (octave_value_list slist,
+ std::string match)
+{
+ std::string retval;
+ for (int i = 0; i < slist.length (); i++)
+ {
+ if (slist (i).string_value () == match)
+ {
+ retval = slist (i).string_value ();
+ break;
+ }
+ }
+ return retval;
+}
+
+
+std::map< std::string, intmap>
+bp_table::get_breakpoint_list (const octave_value_list& fname_list)
+{
+ std::map<std::string, intmap> retval;
+
+ if (!instance_ok ())
+ return retval;
+
+ // Iterate through each of the files in the map and get the
+ // name and list of breakpoints
+ std::map< std::string, octave_user_function* >::iterator it;
+ for (it = instance->bp_map.begin (); it != instance->bp_map.end (); it++)
+ {
+ if (fname_list.length () == 0 ||
+ do_find_bkpt_list (fname_list, it->first) != "")
+ {
+ octave_value_list bkpts = it->second->body ()->list_breakpoints ();
+ octave_idx_type len = bkpts.length ();
+ intmap bkpts_vec;
+ for (int i = 0; i < len; i++)
+ bkpts_vec[i] = bkpts (i).double_value ();
+ retval[ it->first ] = bkpts_vec;
+ }
+ }
+ return retval;
+}
+static octave_value
+intmap_to_ov (const intmap& line)
+{
+ int idx = 0;
+ NDArray retval (dim_vector (1, line.size()));
+ for (int i = 0; i < line.size(); i++ )
+ {
+ intmap::const_iterator p = line.find (i);
+ if (p != line.end ())
+ {
+ int lineno = p->second;
+ retval (idx++) = lineno;
+ }
+ }
+ retval.resize (dim_vector (1, idx));
return retval;
}
+DEFCMD (dbstop, args, ,
+ "-*- texinfo -*-\n\
address@hidden {Loadable Function} {rline =} dbstop (func, line, @dots{})\n\
+Set a breakpoint in a function\n\
address@hidden @code\n\
address@hidden func\n\
+String representing the function name. When already in debug\n\
+mode this should be left out and only the line should be given.\n\
address@hidden line\n\
+Line you would like the breakpoint to be set on. Multiple\n\
+lines might be given as separate arguments or as a vector.\n\
address@hidden table\n\
+\n\
+The rline returned is the real line that the breakpoint was set at.\n\
address@hidden, dbstatus, dbnext}\n\
address@hidden deftypefn")
+{
+ intmap retval;
+ std::string symbol_name = "";
+ intmap lines;
+ parse_dbfunction_params (args, symbol_name, lines);
+
+ if (!error_state)
+ retval = bp_table::add_breakpoint (symbol_name, lines);
+
+ return intmap_to_ov(retval);
+}
+
DEFCMD (dbclear, args, ,
"-*- texinfo -*-\n\
@deftypefn {Loadable Function} {} dbclear (func, line, @dots{})\n\
@@ -197,62 +379,17 @@
@end deftypefn")
{
octave_value retval;
- int nargin = args.length ();
- int idx = 0;
std::string symbol_name = "";
-
- if (nargin != 1 && args(0).is_string())
- {
- symbol_name = args(0).string_value ();
- idx = 1;
- }
-
- octave_user_function *dbg_fcn = get_user_function (symbol_name);
-
- if (dbg_fcn)
- {
- tree_statement_list *cmds = dbg_fcn->body ();
-
- for (int i = idx; i < nargin; i++)
- {
- if (args(i).is_string ())
- {
- int line = atoi (args(i).string_value ().c_str ());
-
- if (error_state)
- break;
-
- cmds->delete_breakpoint (line);
- }
- else
- {
- const NDArray arg = args(i).array_value ();
-
- if (error_state)
- break;
-
- for (octave_idx_type j = 0; j < arg.nelem (); j++)
- {
- int line = static_cast<int> (arg.elem (j));
-
- if (error_state)
- break;
-
- cmds->delete_breakpoint (line);
- }
-
- if (error_state)
- break;
- }
- }
- }
- else
- error ("dbclear: unable to find the function requested\n");
+ intmap lines;
+ parse_dbfunction_params (args, symbol_name, lines);
+
+ if (!error_state)
+ bp_table::remove_breakpoint (symbol_name, lines);
return retval;
}
-DEFCMD (dbstatus, args, ,
+DEFCMD (dbstatus, args, nargout,
"-*- texinfo -*-\n\
@deftypefn {Loadable Function} {lst =} dbstatus ([func])\n\
Return a vector containing the lines on which a function has \n\
@@ -265,50 +402,74 @@
@seealso{dbclear, dbwhere}\n\
@end deftypefn")
{
- octave_value retval;
-
+ Octave_map retval;
int nargin = args.length ();
+ octave_value_list fcn_list;
+ std::map< std::string, intmap> bp_list;
+ std::string symbol_name = "";
if (nargin != 0 && nargin != 1)
{
error ("dbstatus: only zero or one arguements accepted\n");
- return retval;
+ return octave_value ();
}
- std::string symbol_name = "";
-
if (nargin == 1)
{
if (args(0).is_string ())
- symbol_name = args(0).string_value ();
+ {
+ symbol_name = args (0).string_value ();
+ fcn_list (0) = symbol_name;
+ bp_list = bp_table::get_breakpoint_list (fcn_list);
+ }
else
- gripe_wrong_type_arg ("dbstatus", args(0));
+ gripe_wrong_type_arg ("dbstatus", args (0));
}
-
- octave_user_function *dbg_fcn = get_user_function (symbol_name);
-
- if (dbg_fcn)
+ else
{
- tree_statement_list *cmds = dbg_fcn->body ();
-
- octave_value_list lst = cmds->list_breakpoints ();
-
- RowVector vec (lst.length (), 0.0);
-
- for (int i = 0; i < lst.length (); i++)
+ octave_user_function *dbg_fcn = get_user_function ();
+ if (dbg_fcn)
+ {
+ symbol_name = dbg_fcn->name ();
+ fcn_list (0) = symbol_name;
+ }
+ bp_list = bp_table::get_breakpoint_list (fcn_list);
+ }
+
+ std::map< std::string, intmap>::iterator it;
+ if (nargout == 1)
+ {
+ // Fill in an array for return
+ int i = 0;
+ Cell names (dim_vector (bp_list.size (), 1));
+ Cell file (dim_vector (bp_list.size (), 1));
+ Cell line (dim_vector (bp_list.size (), 1));
+ for (it = bp_list.begin (); it != bp_list.end (); it++)
{
- vec(i) = lst(i).double_value ();
-
- if (error_state)
- panic_impossible ();
+ names (i) = it->first;
+ line (i) = intmap_to_ov(it->second);
+ file (i) = do_which (it->first);
+ i++;
}
-
- retval = octave_value (vec);
+ retval.assign ("name", names);
+ retval.assign ("file", file);
+ retval.assign ("line", line);
+ return octave_value (retval);
}
else
- error ("dbstatus: unable to find the function you requested\n");
-
- return retval;
+ {
+ // Print out the breakpoint information
+ for (it = bp_list.begin(); it != bp_list.end(); it++)
+ {
+ octave_stdout << "Breakpoint in " << it->first << " at line(s) ";
+ for (int j = 0; j < it->second.size (); j++)
+ if (j < it->second.size()-1)
+ octave_stdout << it->second [j] << ", ";
+ else
+ octave_stdout << it->second [j] << "." << std::endl;
+ }
+ return octave_value ();
+ }
}
DEFCMD (dbwhere, , ,
Index: help.h
===================================================================
RCS file: /cvs/octave/src/help.h,v
retrieving revision 1.27
diff -u -r1.27 help.h
--- help.h 12 Oct 2007 21:27:30 -0000 1.27
+++ help.h 30 Oct 2007 12:14:16 -0000
@@ -49,6 +49,8 @@
// (--info-program program)
extern std::string Vinfo_program;
+extern std::string do_which (const std::string& name);
+
#endif
/*
Index: help.cc
===================================================================
RCS file: /cvs/octave/src/help.cc,v
retrieving revision 1.175
diff -u -r1.175 help.cc
--- help.cc 12 Oct 2007 21:27:30 -0000 1.175
+++ help.cc 30 Oct 2007 12:14:16 -0000
@@ -1295,7 +1295,7 @@
return retval;
}
-static std::string
+std::string
do_which (const std::string& name)
{
std::string retval;
--- /dev/null 2007-10-29 22:54:34.000000000 -0400
+++ debug.h 2007-10-29 22:57:32.000000000 -0400
@@ -0,0 +1,101 @@
+/*
+
+Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Ben Sapp
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING. If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_debug_h)
+#define octave_debug_h 1
+
+#include <map>
+#include "ov.h"
+#include "dRowVector.h"
+
+//class RowVector;
+class octave_value_list;
+class octave_user_function;
+
+typedef std::map<int, int> intmap;
+
+// A singleton class to provide a standard interface to breakpoints,
+// even if the associated backend changes, we can make sure this
+// higher level interface stays the same.
+class bp_table
+{
+private:
+
+ bp_table (void) {};
+
+ ~bp_table (void) {};
+
+public:
+
+ static bool instance_ok (void)
+ {
+ bool retval = true;
+
+ if (! instance)
+ instance = new bp_table ();
+
+ if (! instance)
+ {
+ ::error ("unable to create breakpoint table!");
+ retval = false;
+ }
+
+ return retval;
+ }
+
+ // Add a breakpoint at the nearest executable line.
+ static intmap add_breakpoint (const std::string& fname = "",
+ const intmap& lines = intmap());
+
+ // Remove a breakpoint from a line in file.
+ static int remove_breakpoint (const std::string& fname = "",
+ const intmap& lines = intmap());
+
+ // Remove all the breakpoints in a specified file.
+ static intmap remove_all_breakpoints_in_file (const std::string& fname);
+
+ // Remove all the breakpoints registered with octave.
+ static void remove_all_breakpoints (void);
+
+ // Return all breakpoints. Each element of the map is a vector
+ // containing the breakpoints corresponding to a given function name.
+ static std::map <std::string, intmap>
+ get_breakpoint_list (const octave_value_list& fname_list);
+
+private:
+
+ // Map from function names to function objects for functions
+ // containing at least one breakpoint.
+ std::map<std::string, octave_user_function*> bp_map;
+
+ // Singleton instance
+ static bp_table *instance;
+};
+
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
- Proposed patch for external debugger access, John Swensen, 2007/10/23
- Proposed patch for external debugger access, John W. Eaton, 2007/10/24
- Re: Proposed patch for external debugger access, John Swensen, 2007/10/24
- Re: Proposed patch for external debugger access, John Swensen, 2007/10/24
- Re: Proposed patch for external debugger access, John W. Eaton, 2007/10/24
- Re: Proposed patch for external debugger access, John Swensen, 2007/10/29
- Re: Proposed patch for external debugger access, John W. Eaton, 2007/10/29
- Re: Proposed patch for external debugger access, John Swensen, 2007/10/29
- Re: Proposed patch for external debugger access, John W. Eaton, 2007/10/30
- Re: Proposed patch for external debugger access,
John Swensen <=
- Re: Proposed patch for external debugger access, John W. Eaton, 2007/10/30
- Re: Proposed patch for external debugger access, John Swensen, 2007/10/31
- Re: Proposed patch for external debugger access, John W. Eaton, 2007/10/31
- Re: Proposed patch for external debugger access, John Swensen, 2007/10/31
- Re: Proposed patch for external debugger access, John W. Eaton, 2007/10/31