[nemiver/better-variable-format: 6/8] Support pretty printing instantly applied
- From: Dodji Seketeli <dodji src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver/better-variable-format: 6/8] Support pretty printing instantly applied
- Date: Wed, 2 Mar 2011 14:46:34 +0000 (UTC)
commit da171a3c04b5048e4dc6e77b4955ba006d09646e
Author: Dodji Seketeli <dodji seketeli org>
Date: Tue Mar 1 18:10:39 2011 +0100
Support pretty printing instantly applied
* src/dbgengine/nmv-dbg-common.h (Command::should_emit_signal):
New accessor. Returns TRUE by default.
* src/dbgengine/nmv-gdb-engine.h
(GDBEngine::variable_visualized_signal)
(GDBEngine::on_rv_eval_var, GDBEngine::on_rv_unfold_var)
(GDBEngine::on_rv_set_visualizer_on_member)
(GDBEngine::on_rv_set_visualizer_on_next_sibling)
(GDBEngine::on_rv_flag)
(GDBEngine::unfold_variable_with_visualizer)
(GDBEngine::revisualize_variable)
(GDBEngine::revisualize_variable_real): Declare new functions.
(GDBEngine::create_variable, GDBEngine::unfold_variable): Declare
new overloads.
(GDBEngine::enable_pretty_printing): Rename
GDBEngine::disable_pretty_printing into this.
(GDBEngine::set_variable_visualizer): Rename
GDBEngine::set_variable_vizualizer.
* src/dbgengine/nmv-gdb-engine.cc
(GDBEngine::Priv::variable_visualized_signal): New fn.
(GDBEngine::Priv::on_conf_key_changed_signal): If pretty printing
has been enabled, send the -enable-pretty-printing command down
the wire.
(OnCommandDoneHandler::do_handle): Handle new
set-variable-visualizer command.
(OnCreateVariableHandler::do_handle): Do not emit
IDebugger:variable_created_signal if it was been requested
otherwise at command creation time.
(OnUnfoldVariableHandler::do_handle): Likewise.
(GDBEngine::variable_visualized_signal, GDBEngine::on_rv_eval_var)
(GDBEngine::on_rv_unfold_var)
(GDBEngine::on_rv_set_visualizer_on_members)
(GDBEngine::on_rv_set_visualizer_on_next_sibling)
(GDBEngine::on_rv_flag)
(GDBEngine::unfold_variable_with_visualizer)
(GDBEngine::revisualize_variable)
(GDBEngine::revisualize_variable_real): New functions.
(GDBEngine::register_names_listed_signal)
(GDBEngine::register_values_listed_signal): Re-indent return type.
Add comments.
(GDBEngine::on_detached_from_target_signal): Add ';' after
NEMIVER_TRY/CATCH_NOX. Add comments.
(GDBEngine::create_variable, GDBEngine::unfold_variable): Add
comments. Add an overload that enables disabling broadcast signal
emitting.
(GDBEngine::enable_pretty_printing): Renamed
GDBEngine::disable_pretty_printing into this. Added comments.
(GDBEngine::set_variable_vizualizer): Update comments. Fix MI
commands sending.
* src/dbgengine/nmv-i-debugger.h (IDebugger::ConstVariableSlot)
(IDebugger::ConstVariableListSlot, IDebugger::ConstUStringSlot):
Move these defines right before declaring the IDebugger::Variable
type.
(IDebugger::visualizer, IDebugger::needs_revisualizing): New
accessors.
(IDebugger::members): Add a new accessor that returns non-const
members.
(IDebugger::variable_visualized_signal): New signal.
(IDebugger::revisualize_variable): New entry point.
(IDebugger::enable_pretty_printing): Renamed
IDebugger::disable_pretty_printing into this.
* src/persp/dbgperspective/nmv-dbg-perspective.cc
(DBGPerspective::on_conf_key_changed_signal): Add comments.
Re-indent somewhat. Re-visualize the local variables of the
current function whenever the pretty-printing enabling setting
changes.
* src/persp/dbgperspective/nmv-local-vars-inspector.h
(LocalVarsInspector::set_local_variables)
(LocalVarsInspector::show_local_variables_of_current_function):
Re-indent.
(LocalVarsInspector::visualize_local_variables_of_current_function):
New function.
* src/persp/dbgperspective/nmv-local-vars-inspector.cc
(LocalVarsInspector::Priv::append_a_function_argument): Add
logging.
(LocalVarsInspector::Priv::update_a_visualized_local_variable)
(LocalVarsInspector::Priv::update_a_visualized_function_arg)
(LocalVarsInspector::Priv::on_local_var_visualized_signal)
(LocalVarsInspector::Priv::on_function_arg_visualized_signal)
(LocalVarsInspector::visualize_local_variables_of_current_function):
New functions.
* src/persp/dbgperspective/nmv-variables-utils.h ():
* src/persp/dbgperspective/nmv-variables-utils.cc
(variables_match): Consider variables with the same internal name
being equal.
(set_a_variable): Factorize out of ...
(append_a_variable): ... here.
(unlink_member_variable_rows): New function.
(visualize_a_variable): Likewise. Use set_a_variable.
* tests/test-breakpoint.cc (test_main): Adjust for the renaming of
IDebugger::enable_pretty_printing.
* tests/test-types.cc (test_main): Likewise.
* tests/test-var-path-expr.cc (test_main): Likewise.
* tests/test-vars.cc (test_main): Likewise.
src/dbgengine/nmv-dbg-common.h | 40 +-
src/dbgengine/nmv-gdb-engine.cc | 585 ++++++++++++++++++--
src/dbgengine/nmv-gdb-engine.h | 55 ++-
src/dbgengine/nmv-i-debugger.h | 65 ++-
src/persp/dbgperspective/nmv-dbg-perspective.cc | 13 +-
.../dbgperspective/nmv-local-vars-inspector.cc | 109 ++++
.../dbgperspective/nmv-local-vars-inspector.h | 5 +-
src/persp/dbgperspective/nmv-variables-utils.cc | 110 ++++-
src/persp/dbgperspective/nmv-variables-utils.h | 14 +
tests/test-breakpoint.cc | 2 +-
tests/test-types.cc | 2 +-
tests/test-var-path-expr.cc | 2 +-
tests/test-vars.cc | 2 +-
13 files changed, 918 insertions(+), 86 deletions(-)
---
diff --git a/src/dbgengine/nmv-dbg-common.h b/src/dbgengine/nmv-dbg-common.h
index 7f48b25..d41f56b 100644
--- a/src/dbgengine/nmv-dbg-common.h
+++ b/src/dbgengine/nmv-dbg-common.h
@@ -40,40 +40,45 @@ class Command {
UString m_tag4;
IDebugger::VariableSafePtr m_var;
sigc::slot_base m_slot;
+ bool m_should_emit_signal;
public:
- Command () :
- m_tag2 (0),
- m_slot (0)
+ Command () :
+ m_tag2 (0),
+ m_slot (0),
+ m_should_emit_signal (true)
{
clear ();
}
/// \param a_value a textual command to send to the debugger.
Command (const UString &a_value) :
- m_value (a_value),
- m_tag2 (0),
- m_slot (0)
+ m_value (a_value),
+ m_tag2 (0),
+ m_slot (0),
+ m_should_emit_signal (true)
{
}
Command (const UString &a_name, const UString &a_value) :
- m_name (a_name),
- m_value (a_value),
- m_tag2 (0),
- m_slot (0)
+ m_name (a_name),
+ m_value (a_value),
+ m_tag2 (0),
+ m_slot (0),
+ m_should_emit_signal (true)
{
}
Command (const UString &a_name,
const UString &a_value,
const UString &a_cookie) :
- m_cookie (a_cookie),
- m_name (a_name),
- m_value (a_value),
- m_tag2 (0),
- m_slot (0)
+ m_cookie (a_cookie),
+ m_name (a_name),
+ m_value (a_value),
+ m_tag2 (0),
+ m_slot (0),
+ m_should_emit_signal (true)
{
}
@@ -125,6 +130,9 @@ public:
return reinterpret_cast<const T&> (m_slot);
}
+ bool should_emit_signal () const {return m_should_emit_signal;}
+ void should_emit_signal (bool a) {m_should_emit_signal = a;}
+
/// @}
void clear ()
@@ -136,6 +144,7 @@ public:
m_tag2 = 0;
m_tag3.clear ();
m_tag4.clear ();
+ m_should_emit_signal = true;
}
};//end class Command
@@ -923,7 +932,6 @@ public:
void submit_command_and_output (CommandAndOutput &a_cao);
};//end class OutputHandlerList
-
NEMIVER_END_NAMESPACE (nemiver)
#endif //__NMV_DBG_COMMON_H_H__
diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index 9b4876b..45bd43b 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -50,12 +50,19 @@ using namespace std;
using namespace nemiver::common;
using namespace nemiver::cpp;
-static const UString GDBMI_OUTPUT_DOMAIN = "gdbmi-output-domain";
-static const UString DEFAULT_GDB_BINARY = "default-gdb-binary";
+typedef nemiver::IDebugger::ConstVariableSlot ConstVariableSlot;
+typedef nemiver::IDebugger::ConstVariableListSlot ConstVariableListSlot;
+typedef nemiver::IDebugger::ConstUStringSlot ConstUStringSlot;
+typedef nemiver::IDebugger::VariableSafePtr VariableSafePtr;
using nemiver::debugger_utils::null_const_variable_slot;
using nemiver::debugger_utils::null_const_variable_list_slot;
+static const char* GDBMI_OUTPUT_DOMAIN = "gdbmi-output-domain";
+static const char* DEFAULT_GDB_BINARY = "default-gdb-binary";
+static const char* GDB_DEFAULT_PRETTY_PRINTING_VISUALIZER =
+ "gdb.default_visualizer";
+static const char* GDB_NULL_PRETTY_PRINTING_VISUALIZER = "None";
NEMIVER_BEGIN_NAMESPACE (nemiver)
@@ -79,7 +86,6 @@ quote_args (const vector<UString> &a_prog_args)
return args;
}
-
//*************************
//<GDBEngine::Priv struct>
//*************************
@@ -233,6 +239,11 @@ public:
mutable sigc::signal<void, const VariableSafePtr, const UString&>
variable_dereferenced_signal;
+ mutable sigc::signal<void,
+ const VariableSafePtr,
+ const UString&> variable_visualized_signal;
+
+
mutable sigc::signal<void, int, const UString&> got_target_info_signal;
mutable sigc::signal<void> running_signal;
@@ -1019,6 +1030,9 @@ public:
set_debugger_parameter ("follow-fork-mode", follow_fork_mode);
} else if (a_key == CONF_KEY_PRETTY_PRINTING) {
enable_pretty_printing = boost::get<bool> (a_value);
+ if (enable_pretty_printing) {
+ queue_command (Command ("-enable-pretty-printing"));
+ }
}
NEMIVER_CATCH_NOX
@@ -1569,6 +1583,21 @@ struct OnCommandDoneHandler : OutputHandler {
}
}
+ if (a_in.command ().name () == "set-variable-visualizer") {
+ VariableSafePtr var = a_in.command ().variable ();
+ THROW_IF_FAIL (var);
+ var->visualizer (a_in.command ().tag0 ());
+ if (a_in.command ().has_slot ()) {
+ LOG_DD ("set-variable-visualizer command has a slot");
+ ConstVariableSlot slot =
+ a_in.command ().get_slot<ConstVariableSlot> ();
+ slot (var);
+ } else {
+ LOG_DD ("set-variable-visualizer command "
+ "does not have a slot");
+ }
+ }
+
// So, if we are still attached to the target and we receive
// a "DONE" response from GDB, it means we are READY.
// But if we are not attached -- which can mean that the
@@ -2478,10 +2507,11 @@ struct OnCreateVariableHandler : public OutputHandler
void do_handle (CommandAndOutput &a_in)
{
+ VariableSafePtr var = a_in.output ().result_record ().variable ();
+
// Set the name of the variable to the name that got stored
// in the tag0 member of the command.
- a_in.output ().result_record ().variable ()->name
- (a_in.command ().tag0 ());
+ var->name (a_in.command ().tag0 ());
// Call the slot associated to IDebugger::create_variable (), if
// any.
@@ -2489,13 +2519,15 @@ struct OnCreateVariableHandler : public OutputHandler
LOG_DD ("calling IDebugger::create_variable slot");
typedef sigc::slot<void, IDebugger::VariableSafePtr> SlotType;
SlotType slot = a_in.command ().get_slot<SlotType> ();
- slot (a_in.output ().result_record ().variable ());
+ slot (var);
}
LOG_DD ("emit IDebugger::variable_create_signal");
- // Emit the general IDebugger::variable_create_signal () signal
- m_engine->variable_created_signal ().emit
- (a_in.output ().result_record ().variable (),
- a_in.command ().cookie ());
+ // Emit the general IDebugger::variable_create_signal ()
+ // signal
+ if (a_in.command ().should_emit_signal ())
+ m_engine->variable_created_signal ().emit
+ (var, a_in.command ().cookie ());
+
if (m_engine->get_state () != IDebugger::PROGRAM_EXITED
|| m_engine->get_state () != IDebugger::NOT_STARTED) {
m_engine->set_state (IDebugger::READY);
@@ -2589,8 +2621,9 @@ struct OnUnfoldVariableHandler : public OutputHandler {
}
// Now tell the world we have an unfolded variable.
- m_engine->variable_unfolded_signal ().emit
- (parent_var, a_in.command ().cookie ());
+ if (a_in.command ().should_emit_signal ())
+ m_engine->variable_unfolded_signal ().emit
+ (parent_var, a_in.command ().cookie ());
}
};// End struct OnUnfoldVariableHandler
@@ -3248,14 +3281,30 @@ GDBEngine::variable_dereferenced_signal () const
return m_priv->variable_dereferenced_signal;
}
-sigc::signal<void, const std::map<IDebugger::register_id_t, UString>&, const UString& >&
+/// A signal emitted upon completion of
+/// GDBEngine::revisualize_variable.
+///
+/// The first parameter of the slot is the variable that has been
+/// re-visualized and the second is the cookie passed to
+/// GDBEngine::revisualize_variable.
+sigc::signal<void, const VariableSafePtr, const UString&>&
+GDBEngine::variable_visualized_signal () const
+{
+ return m_priv->variable_visualized_signal;
+}
+
+sigc::signal<void,
+ const std::map<IDebugger::register_id_t, UString>&,
+ const UString& >&
GDBEngine::register_names_listed_signal () const
{
return m_priv->register_names_listed_signal;
}
-sigc::signal<void, const std::map<IDebugger::register_id_t, UString>&, const UString& >&
+sigc::signal<void,
+ const std::map<IDebugger::register_id_t, UString>&,
+ const UString& >&
GDBEngine::register_values_listed_signal () const
{
@@ -3425,26 +3474,246 @@ GDBEngine::on_stopped_signal (IDebugger::StopReason a_reason,
NEMIVER_CATCH_NOX
}
+/// Slot called from revisualize_variable_real.
+///
+/// Evaluates the expression of the given variable and schedules the
+/// unfolding of the variable upon completion of the expression
+/// evaluation. Upon unfolding of the variable, revisualization is
+/// scheduled for the member variables, if any. That revisualization
+/// uses the visualization given in parameter.
+///
+/// \param a_var the variable which expression to evaluate.
+///
+/// \param a_visualizer the pretty printer visualizer to use for the
+/// revisualization of the children member variables that will appear
+/// as the result of the scheduled unfolding.
+///
+/// \param a_slot the slot to call upon completion of the evaluation
+/// of the expression of this a_var.
void
-GDBEngine::on_detached_from_target_signal ()
+GDBEngine::on_rv_eval_var (const VariableSafePtr a_var,
+ const UString &a_visualizer,
+ const ConstVariableSlot &a_slot)
+{
+ NEMIVER_TRY;
+
+ evaluate_variable_expr
+ (a_var,
+ sigc::bind
+ (sigc::mem_fun
+ (*this, &GDBEngine::on_rv_unfold_var),
+ a_visualizer, a_slot),
+ "");
+
+ NEMIVER_CATCH_NOX;
+}
+
+/// Slot called from GDBEngine::on_rv_eval_var.
+///
+/// Unfolds the given variable and schedules lazy revisualization on
+/// its member variables if any. The unfolding is done using a given
+/// variable revisualizer.
+///
+/// \param a_var the variable to unfold.
+///
+/// \param a_visualizer to use for revisualization of the member
+/// variables, if any.
+///
+/// \param a_slot the slot to call upon completion of the unfolding.
+/// The slot takes a_var in argument.
+void
+GDBEngine::on_rv_unfold_var (const VariableSafePtr a_var,
+ const UString &a_visualizer,
+ const ConstVariableSlot &a_slot)
+{
+ NEMIVER_TRY;
+
+ unfold_variable_with_visualizer (a_var, a_visualizer, a_slot);
+
+ NEMIVER_CATCH_NOX;
+}
+
+/// Callback slot invoked from unfold_variable, set by
+/// GDBEngine::unfold_variable_with_visualizer.
+///
+/// It triggers the setting of the pretty-printing visualizer of each
+/// member variable of a given variable. Once each member variable
+/// has seen its visualizer set, the initial variable is unfolded.
+/// The resulting children variables will be unfolded and rendered
+/// using the visualize that got set on their children.
+///
+/// \param a_var the variable to act upon. The member variables of
+/// this one are the ones that are going to see their visualizer set.
+/// This variable will then be unfolded.
+///
+/// \param a_visualizer the vizualizer to set on the member variables
+/// of a_var.
+///
+/// \param a_slot the slot to call upon completion of the unfolding of
+/// a_var that happens after the visualizer setting on each member of
+/// a_var.
+void
+GDBEngine::on_rv_set_visualizer_on_members (const VariableSafePtr a_var,
+ const UString &a_visualizer,
+ const ConstVariableSlot &a_slot)
+{
+ NEMIVER_TRY;
+
+ IDebugger::VariableList::iterator it = a_var->members ().begin (),
+ end = a_var->members ().end ();
+
+ if (it != end)
+ set_variable_visualizer
+ (*it,
+ a_visualizer,
+ sigc::bind
+ (sigc::mem_fun
+ (*this,
+ &GDBEngine::on_rv_set_visualizer_on_next_sibling),
+ a_visualizer, it, end, a_slot));
+
+ NEMIVER_CATCH_NOX;
+}
+
+/// This is a callback slot called from
+/// GDBEngine::set_variable_visualizer, connected by
+/// GDBEngine::on_rv_set_visualizer_on_members.
+///
+/// It sets the pretty-printing visualizer for the next sibling
+/// variable. Once it reached the last sibling, it unfolds the parent
+/// variable, forcing the the re-printing of the siblings of the this
+/// function walked through, with a the new visualizer it did set.
+///
+/// \param a_var the variable which visualizer got set at the previous
+/// invocation of this function.
+///
+/// \param a_member_it an iterator pointing to the previous sibling
+/// variable which visualuzer got set. So this function is going to
+/// set the visualizer of ++a_member_it.
+///
+/// \param a_members_end an iterator pointing to right after the last
+/// slibling variable we need to walk.
+///
+/// \param a_slot the callback slot to invoke once the parent variable
+/// of a_var has been unfolded.
+void
+GDBEngine::on_rv_set_visualizer_on_next_sibling
+(const VariableSafePtr a_var,
+ const UString &a_visualizer,
+ IDebugger::VariableList::iterator &a_member_it,
+ IDebugger::VariableList::iterator &a_members_end,
+ const ConstVariableSlot &a_slot)
+{
+ NEMIVER_TRY;
+
+ THROW_IF_FAIL (a_member_it != a_members_end);
+
+ ++a_member_it;
+ if (a_member_it != a_members_end) {
+ set_variable_visualizer
+ (*a_member_it,
+ a_visualizer,
+ sigc::bind
+ (sigc::mem_fun
+ (*this,
+ &GDBEngine::on_rv_set_visualizer_on_next_sibling),
+ a_visualizer, a_member_it, a_members_end, a_slot));
+ } else {
+ IDebugger::VariableList::iterator it;
+ IDebugger::VariableSafePtr parent = a_var->parent ();
+ // This invalidates a_member_it and a_members_end iterators.
+ parent->members ().clear ();
+ unfold_variable (parent,
+ sigc::bind
+ (sigc::mem_fun (*this, &GDBEngine::on_rv_flag),
+ a_visualizer, a_slot),
+ "");
+ }
+
+ NEMIVER_CATCH_NOX;
+}
+
+/// Slot called by GDBEngine::on_rv_unfold_var.
+///
+/// Locally set the visualizer of each member variable of the given
+/// variable and flag them as needing revisualization. Later, when
+/// any of these member variables will be about to be unfolded
+/// GDBEngine::unfold_variable is going to actually unfold them using
+/// that visualizer. I.e, the member variables of that member
+/// variable are going to be rendered using that visualizer.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_visualizer the visualizer to set on the member variables
+/// of a_var if any.
+///
+/// \param a_slot the slot to call upon completion of this function.
+void
+GDBEngine::on_rv_flag (const VariableSafePtr a_var,
+ const UString &a_visualizer,
+ const ConstVariableSlot &a_slot)
{
- NEMIVER_TRY
+ NEMIVER_TRY;
+
+ THROW_IF_FAIL (a_var);
+
+ IDebugger::VariableList::iterator it;
+ for (it = a_var->members ().begin ();
+ it != a_var->members ().end ();
+ ++it) {
+ (*it)->visualizer (a_visualizer);
+ (*it)->needs_revisualizing (true);
+ }
+ if (a_slot)
+ a_slot (a_var);
+
+ NEMIVER_CATCH_NOX;
+}
+
+/// Unfold a variable, using a given visualizer to render the children
+/// variable objects resulting from the unfolding.
+///
+/// This has a lot of kludge as GDB doesn't
+void
+GDBEngine::unfold_variable_with_visualizer (const VariableSafePtr a_var,
+ const UString &a_visualizer,
+ const ConstVariableSlot &a_slot)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ unfold_variable
+ (a_var,
+ sigc::bind
+ (sigc::mem_fun
+ (*this, &GDBEngine::on_rv_set_visualizer_on_members),
+ a_visualizer, a_slot),
+ "",
+ /*a_should_emit_signal*/false);
+}
+
+/// Signal handler called when GDBEngine::detached_from_target_signal
+/// is emitted.
+void
+GDBEngine::on_detached_from_target_signal ()
+{
+ NEMIVER_TRY;
m_priv->is_attached = false;
- NEMIVER_CATCH_NOX
+ NEMIVER_CATCH_NOX;
}
+/// Signal handler called when GDBEngine::program_finished_signal is
+/// emitted.
void
GDBEngine::on_program_finished_signal ()
{
- NEMIVER_TRY
-
+ NEMIVER_TRY;
m_priv->is_attached = false;
- NEMIVER_CATCH_NOX
+ NEMIVER_CATCH_NOX;
}
//******************
@@ -4388,7 +4657,109 @@ GDBEngine::dereference_variable (const VariableSafePtr &a_var,
return true;
}
-/// Lists the source files htat make up the executable
+/// Re-build a given variable using the relevant visualizer if
+/// pretty-printing is in effect, or no visualizer if pretty printing
+/// is turned off. Bear in mind that for now, once pretty printing
+/// has been turned on, GDB doesn't support turning it back off. To
+/// turn it off in practise, one needs to set the 'None' visualizer for
+/// each variable we want to visualize.
+///
+/// This function clears the current member variables of the given
+/// variable, sets its relevant visualizer, re-evaluates its
+/// expression, unfolds it and schedules a similar set of actions for
+/// each of the member variables.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_slot the slot function to call once a_var has been
+/// unfolded as part part of the revisualization process.
+void
+GDBEngine::revisualize_variable (const VariableSafePtr a_var,
+ const ConstVariableSlot &a_slot)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ THROW_IF_FAIL (m_priv);
+
+
+ NEMIVER_TRY;
+
+ get_conf_mgr ().get_key_value (CONF_KEY_PRETTY_PRINTING,
+ m_priv->enable_pretty_printing);
+
+ NEMIVER_CATCH_NOX;
+
+ revisualize_variable (a_var, m_priv->enable_pretty_printing, a_slot);
+}
+
+/// A subroutine of GDBEngine::revisualize_variable above.
+///
+/// This function clears the current member variables of the given
+/// variable, sets its relevant visualizer, re-evaluates its
+/// expression, unfolds it and schedules a similar set of actions for
+/// each of the member variables.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_pretty_printing a flag saying whether to turn pretty
+/// printing on or off.
+///
+/// \param a_slot a slot to be called when the revisualization is
+/// done. It is called when a_var is effectively unfolded.
+void
+GDBEngine::revisualize_variable (IDebugger::VariableSafePtr a_var,
+ bool a_pretty_printing,
+ const ConstVariableSlot &a_slot)
+{
+ a_var->members ().clear ();
+ UString v;
+ if (a_pretty_printing)
+ v = GDB_DEFAULT_PRETTY_PRINTING_VISUALIZER;
+ else
+ v = GDB_NULL_PRETTY_PRINTING_VISUALIZER;
+ revisualize_variable_real (a_var, v, a_slot);
+}
+
+/// A subroutine of revisualize_variable.
+///
+/// Here is the actual sequence of action taken:
+///
+/// 1/ Set its visualizer. That is instruct the backend to use that
+/// visualizer to visualize this variable.
+/// 2/ Evaluate the expression of the variable
+/// 3/ Unfold variable with visualizer <-- TODO: need to write this.
+/// 3.1/ Unfold it w/o signaling
+/// 3.2/ Set visualizers of each children
+/// 3.3/ Unfold again, with normal signaling
+/// 3.4/ Mark each children variable as needing to go to 3 whenever
+/// they are going to be revisualized.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_visualizer the visualizer to use for revisualizing the
+/// variable.
+///
+/// \param a_slot the slot function to call upon completion of step 4.
+void
+GDBEngine::revisualize_variable_real (IDebugger::VariableSafePtr a_var,
+ const UString& a_visualizer,
+ const ConstVariableSlot &a_slot)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ THROW_IF_FAIL (a_var);
+
+ a_var->needs_revisualizing (false);
+
+ set_variable_visualizer
+ (a_var, a_visualizer,
+ sigc::bind
+ (sigc::mem_fun
+ (*this, &GDBEngine::on_rv_eval_var),
+ a_visualizer, a_slot));
+}
+
+/// Lists the source files that make up the executable
void
GDBEngine::list_files (const UString &a_cookie)
{
@@ -4870,6 +5241,24 @@ GDBEngine::create_variable (const UString &a_name,
a_cookie);
}
+/// Create a GDB-side variable object for a given variable. The name
+/// of the variable must be accessible from the current frame.
+///
+/// Emits IDebugger::variable_created_signal upon creation of the
+/// GDB-side variable object.
+///
+/// \param a_name the name of the variable to create.
+///
+/// \param a_s the slot callback function to invoke upon creation of
+/// the GDB-side variable object.
+///
+/// \param a_cookie a string value passed to the the
+/// IDebugger::variable_created_signal emitted upon creation of the
+/// server side variable object.
+///
+/// \param a_should_emit_signal if set to TRUE, emit the
+/// IDebugger::variable_created_signal signal. Otherwise that signal
+/// is not emitted.
void
GDBEngine::create_variable (const UString &a_name ,
const ConstVariableSlot &a_slot,
@@ -4877,6 +5266,33 @@ GDBEngine::create_variable (const UString &a_name ,
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
+ create_variable (a_name, a_slot, a_cookie,
+ /*a_should_emit_signal=*/true);
+}
+
+/// Create a GDB-side variable object for a given variable. The name
+/// of the variable must be accessible from the current frame.
+///
+/// \param a_name the name of the variable to create.
+///
+/// \param a_slot the slot callback function to invoke upon creation
+/// of the GDB-side variable object.
+///
+/// \param a_cookie a string value passed to the the
+/// IDebugger::variable_created_signal emitted upon creation of the
+/// server side variable object.
+///
+/// \param a_should_emit_signal if set to TRUE, emit the
+/// IDebugger::variable_created_signal signal. Otherwise that signal
+/// is not emitted.
+void
+GDBEngine::create_variable (const UString &a_name,
+ const ConstVariableSlot &a_slot,
+ const UString &a_cookie,
+ bool a_should_emit_signal)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
if (a_name.empty ()) {
LOG ("got empty name");
return;
@@ -4893,6 +5309,7 @@ GDBEngine::create_variable (const UString &a_name ,
a_cookie);
command.tag0 (a_name);
command.set_slot (a_slot);
+ command.should_emit_signal (a_should_emit_signal);
queue_command (command);
}
@@ -4924,6 +5341,20 @@ GDBEngine::delete_variable (const VariableSafePtr a_var,
queue_command (command);
}
+/// Unfold a given variable.
+///
+/// Query the backend for the member variables of the given variable.
+/// This is not recursive. Each member will in turn need to be
+/// unfolded to get its member variables.
+///
+/// Upon completion of the backend side of this command, signal
+/// IDebugger::variable_unfolded_signal is emitted, with a_var as an
+/// argument.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_cookie the cookie to pass to the
+/// IDebugger::variable_unfolded_signal signal.
void
GDBEngine::unfold_variable (const VariableSafePtr a_var,
const UString &a_cookie)
@@ -4934,6 +5365,23 @@ GDBEngine::unfold_variable (const VariableSafePtr a_var,
a_cookie);
}
+/// A subroutine of GDBEngine::unfold_variable above.
+///
+/// Query the backend for the member variables of the given variable.
+/// This is not recursive. Each member will in turn need to be
+/// unfolded to get its member variables.
+///
+/// Upon completion of the backend side of this command, signal
+/// IDebugger::variable_unfolded_signal is emitted, with a_var as an
+/// argument.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_slot a slot function to be invoked upon completion of the
+/// backend side of this command.
+///
+/// \param a_cookie a string that is going to be passed to signal
+/// IDebugger::variable_unfolded_signal.
void
GDBEngine::unfold_variable (const VariableSafePtr a_var,
const ConstVariableSlot &a_slot,
@@ -4941,7 +5389,45 @@ GDBEngine::unfold_variable (const VariableSafePtr a_var,
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
+ unfold_variable (a_var, a_slot, a_cookie,
+ /*a_should_emit_signal=*/true);
+}
+
+/// A subroutine of GDBEngine::unfold_variable above.
+///
+/// Query the backend for the member variables of the given variable.
+/// This is not recursive. Each member will in turn need to be
+/// unfolded to get its member variables.
+///
+/// \param a_var the variable to act upon.
+///
+/// \param a_slot a slot function to be invoked upon completion of the
+/// backend side of this command.
+///
+/// \param a_cookie a string that is going to be passed to signal
+/// IDebugger::variable_unfolded_signal.
+///
+/// \param a_should_emit_signal if TRUE, emits
+/// IDebugger::variable_unfolded_signal upon completion of the GDB
+/// side of this command. Otherwise, no signal is emitted.
+void
+GDBEngine::unfold_variable (VariableSafePtr a_var,
+ const ConstVariableSlot &a_slot,
+ const UString &a_cookie,
+ bool a_should_emit_signal)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
THROW_IF_FAIL (a_var);
+
+ // If this variable was asked to be revisualized, let the backend
+ // use the visualizer for it during its unfolding process.
+ if (a_var->needs_revisualizing ()) {
+ a_var->needs_revisualizing (false);
+ return unfold_variable_with_visualizer (a_var,
+ a_var->visualizer (),
+ a_slot);
+ }
if (a_var->internal_name ().empty ()) {
UString qname;
a_var->build_qualified_internal_name (qname);
@@ -4956,6 +5442,7 @@ GDBEngine::unfold_variable (const VariableSafePtr a_var,
a_cookie);
command.variable (a_var);
command.set_slot (a_slot);
+ command.should_emit_signal (a_should_emit_signal);
queue_command (command);
}
@@ -5135,41 +5622,65 @@ GDBEngine::set_variable_format (const VariableSafePtr a_var,
queue_command (command);
}
+/// Set the relevant confmgr key enabling or disabling
+/// pretty-printing.
+///
+/// \param a_flag TRUE to enable pretty-printing, false otherwise.
void
-GDBEngine::disable_pretty_printing ()
-{
- // Doing it this way for now b/c you can't change this in GDB on
- // the fly at the moment.
- m_priv->enable_pretty_printing = false;
- get_conf_mgr ().get_key_value (CONF_KEY_PRETTY_PRINTING,
- m_priv->enable_pretty_printing);
+GDBEngine::enable_pretty_printing (bool a_flag)
+{
+ // Note that disabling (passing false) this feature doesn't work
+ // in GDB </grin>.
+ //
+ // The workaround to disabling the feature is to set the
+ // visualizer to None on all subsequent varobjs that are created.
+ // For those that are already created, we basically set the
+ // visualizer to None, re-evaluate the expression of the variable
+ // and do that recursively for the member varobjs.
+
+ // Don't bother changing anything if we are asked to do what we
+ // already have.
+ if (a_flag == m_priv->enable_pretty_printing)
+ return;
+
+ // Note that on_conf_key_changed_signal instructs GDB to enable
+ // pretty printing when once the key is set to TRUE.
+ get_conf_mgr ().set_key_value (CONF_KEY_PRETTY_PRINTING,
+ a_flag);
}
-/// Set the variable vizualizer used by the GDB Pretty Printing system
-/// to print the value of a given variable.
+/// Instruct GDB to set the variable vizualizer used by the GDB Pretty
+/// Printing system to print the value of a given variable.
+///
/// \param a_var the variable to set the vizualizer for.
+///
/// \param a_vizualizer a string representing the vizualizer to set
/// for this variable. If you don't want any vizualizer to be set,
/// then set this variableto "None". If you want the default
/// vizualizer for this type to be set, then set this variable to
/// "gdb.default_visualizer".
+///
+/// \param a_slot the slot function called when GDB finishes to set
+/// the visualizer for this variable.
void
-GDBEngine::set_variable_vizualizer (const VariableSafePtr a_var,
- const std::string &a_vizualizer,
- const UString &a_cookie)
+GDBEngine::set_variable_visualizer (const VariableSafePtr a_var,
+ const std::string &a_visualizer,
+ const ConstVariableSlot &a_slot)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
THROW_IF_FAIL (a_var);
THROW_IF_FAIL (!a_var->internal_name ().empty ());
- UString cmd_str = "-var-set-vizualizer ";
+ UString cmd_str = "-var-set-visualizer ";
cmd_str += a_var->internal_name () + " ";
- cmd_str += a_vizualizer;
+ cmd_str += a_visualizer;
- Command command ("set-variable-vizualizer",
- cmd_str, a_cookie);
+ Command command ("set-variable-visualizer",
+ cmd_str);
command.variable (a_var);
+ command.set_slot (a_slot);
+ command.tag0 (a_visualizer);
queue_command (command);
}
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index 3ff7206..4e8a3ff 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -146,6 +146,9 @@ public:
sigc::signal<void, const VariableSafePtr, const UString&>&
variable_dereferenced_signal () const;
+ sigc::signal<void, const VariableSafePtr, const UString&>&
+ variable_visualized_signal () const;
+
sigc::signal<void, int, const UString&>& got_target_info_signal () const ;
sigc::signal<void>& running_signal () const;
@@ -217,6 +220,30 @@ public:
void on_detached_from_target_signal ();
void on_program_finished_signal ();
+ void on_rv_eval_var (const VariableSafePtr,
+ const UString&,
+ const ConstVariableSlot&);
+ void on_rv_unfold_var (const VariableSafePtr,
+ const UString&,
+ const ConstVariableSlot&);
+ void on_rv_set_visualizer_on_members (const VariableSafePtr,
+ const UString&,
+ const ConstVariableSlot&);
+ void on_rv_set_visualizer_on_next_sibling
+ (const VariableSafePtr,
+ const UString&,
+ IDebugger::VariableList::iterator &,
+ IDebugger::VariableList::iterator &,
+ const ConstVariableSlot&);
+
+ void on_rv_flag (const VariableSafePtr,
+ const UString&,
+ const ConstVariableSlot&);
+
+ void unfold_variable_with_visualizer (const VariableSafePtr,
+ const UString &a_visualizer,
+ const ConstVariableSlot&);
+
//***************
//</signal handlers>
//***************
@@ -438,6 +465,17 @@ public:
bool dereference_variable (const VariableSafePtr &a_var,
const UString &a_cookie);
+ void revisualize_variable (const VariableSafePtr a_var,
+ const ConstVariableSlot &a_slot);
+
+ void revisualize_variable (const VariableSafePtr a_var,
+ bool a_toggle_pretty_printing,
+ const ConstVariableSlot &a_slot);
+
+ void revisualize_variable_real (IDebugger::VariableSafePtr,
+ const UString&,
+ const ConstVariableSlot &a_slot);
+
void list_files (const UString &a_cookie);
bool extract_proc_info (Output &a_output,
@@ -504,6 +542,11 @@ public:
const ConstVariableSlot &a_s,
const UString &a_cookie="");
+ void create_variable (const UString &a_name,
+ const ConstVariableSlot &a_s,
+ const UString &a_cookie,
+ bool a_should_emit_signal);
+
void delete_variable (const VariableSafePtr a_var,
const UString &a_cookie);
@@ -513,10 +556,16 @@ public:
void unfold_variable (VariableSafePtr a_var,
const UString &a_cookie);
+
void unfold_variable (VariableSafePtr a_var,
const ConstVariableSlot &a_s,
const UString &a_cookie);
+ void unfold_variable (VariableSafePtr a_var,
+ const ConstVariableSlot &a_s,
+ const UString &a_cookie,
+ bool a_should_emit_signal);
+
void assign_variable (const VariableSafePtr a_var,
const UString &a_expression,
const UString &a_cookie);
@@ -557,11 +606,11 @@ public:
const Variable::Format a_format,
const UString &a_cookie);
- void disable_pretty_printing ();
+ void enable_pretty_printing (bool a_flag);
- void set_variable_vizualizer (const VariableSafePtr a_var,
+ void set_variable_visualizer (const VariableSafePtr a_var,
const std::string &a_vizualizer,
- const UString &a_cookie);
+ const ConstVariableSlot &a_slot);
};//end class GDBEngine
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index 489b460..31913dc 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -338,6 +338,10 @@ public:
class Variable;
typedef SafePtr<Variable, ObjectRef, ObjectUnref> VariableSafePtr;
typedef list<VariableSafePtr> VariableList;
+ typedef sigc::slot<void, const VariableSafePtr> ConstVariableSlot;
+ typedef sigc::slot<void, const VariableList> ConstVariableListSlot;
+ typedef sigc::slot<void, const UString&> ConstUStringSlot;
+
class Variable : public Object {
public:
enum Format {
@@ -366,6 +370,16 @@ public:
UString m_name_caption;
UString m_value;
UString m_type;
+ // When using GDB pretty-printers, this is a string naming the
+ // pretty printer used to visualize this variable. As
+ // disabling pretty printing is not possible globally in GDB
+ // we need to use this even when the user doesn't want to
+ // change it. Setting it to "" should do the right thing: if
+ // pretty printing is enabled, the variable will be displayed
+ // using the default pretty printer; if pretty printing is
+ // disabled the variable would be displayed using no pretty
+ // printer.
+ UString m_visualizer;
Variable *m_parent;
//if this variable is a pointer,
//it can be dereferenced. The variable
@@ -378,20 +392,21 @@ public:
// IDebugger::query_variable_path_expr()
UString m_path_expression;
Format m_format;
+ bool m_needs_revisualizing;
public:
Variable (const UString &a_internal_name,
const UString &a_name,
const UString &a_value,
const UString &a_type) :
- m_internal_name (a_internal_name),
+ m_internal_name (a_internal_name),
m_name (a_name),
m_value (a_value),
m_type (a_type),
m_parent (0),
m_num_expected_children (0),
- m_format (UNDEFINED_FORMAT)
-
+ m_format (UNDEFINED_FORMAT),
+ m_needs_revisualizing (false)
{
}
@@ -399,27 +414,36 @@ public:
const UString &a_value,
const UString &a_type) :
m_name (a_name),
- m_value (a_value),
- m_type (a_type),
- m_parent (0),
- m_num_expected_children (0)
+ m_value (a_value),
+ m_type (a_type),
+ m_parent (0),
+ m_num_expected_children (0),
+ m_format (UNDEFINED_FORMAT),
+ m_needs_revisualizing (false)
{
}
Variable (const UString &a_name) :
m_name (a_name),
- m_parent (0),
- m_num_expected_children (0)
+ m_parent (0),
+ m_num_expected_children (0),
+ m_format (UNDEFINED_FORMAT),
+ m_needs_revisualizing (false)
{}
Variable () :
m_parent (0),
- m_num_expected_children (0)
+ m_num_expected_children (0),
+ m_format (UNDEFINED_FORMAT),
+ m_needs_revisualizing (false)
+
{}
const VariableList& members () const {return m_members;}
+ VariableList& members () {return m_members;}
+
/// Returns the Nth member variable, if any.
/// Please note that this function has O(n) complexity. So use it with
/// care.
@@ -525,6 +549,9 @@ public:
void type (const UString &a_type) {m_type = a_type;}
void type (const string &a_type) {m_type = a_type;}
+ const UString& visualizer () const {return m_visualizer;}
+ void visualizer (const UString &a) {m_visualizer = a;}
+
/// Return true if this instance of Variable has a parent variable,
/// false otherwise.
bool has_parent () const
@@ -763,6 +790,9 @@ public:
Format format () const {return m_format;}
void format (Format a_format) {m_format = a_format;}
+ bool needs_revisualizing () const {return m_needs_revisualizing;}
+ void needs_revisualizing (bool a) {m_needs_revisualizing = a;}
+
};//end class Variable
enum State {
@@ -948,6 +978,9 @@ public:
const UString&/*cookie*/>&
variable_dereferenced_signal () const=0;
+ sigc::signal<void, const VariableSafePtr, const UString&>&
+ variable_visualized_signal () const;
+
virtual sigc::signal<void, const vector<UString>&, const UString&>&
files_listed_signal () const = 0;
@@ -1226,6 +1259,9 @@ public:
virtual bool dereference_variable (const VariableSafePtr &a_var,
const UString &a_cookie="") = 0;
+ virtual void revisualize_variable (const VariableSafePtr a_var,
+ const ConstVariableSlot &a_slot) = 0;
+
virtual void list_files (const UString &a_cookie="") = 0;
virtual void list_register_names (const UString &a_cookie="") = 0;
@@ -1275,10 +1311,6 @@ public:
bool a_pure_asm = true,
const UString &a_cookie = "") = 0;
- typedef sigc::slot<void, const VariableSafePtr> ConstVariableSlot;
- typedef sigc::slot<void, const VariableList> ConstVariableListSlot;
- typedef sigc::slot<void, const UString&> ConstUStringSlot;
-
virtual void create_variable (const UString &a_name,
const UString &a_cookie = "") = 0;
@@ -1339,11 +1371,8 @@ public:
const Variable::Format a_format,
const UString &a_cookie = "") = 0;
- virtual void disable_pretty_printing () = 0;
+ virtual void enable_pretty_printing (bool a_flag = true) = 0;
- virtual void set_variable_vizualizer (const VariableSafePtr a_var,
- const std::string &a_vizualizer,
- const UString &a_cookie = "") = 0;
};//end IDebugger
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index df2edf7..e34ac8f 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -2302,6 +2302,12 @@ DBGPerspective::on_show_log_view_changed_signal (bool a_show)
action->set_active (a_show);
}
+/// Function called whenever a the value of a configuration key
+/// changes on the sytem.
+///
+/// \param a_key the key which value changed
+///
+/// \param a_value the new value of the key
void
DBGPerspective::on_conf_key_changed_signal (const UString &a_key,
IConfMgr::Value &a_value)
@@ -2310,7 +2316,8 @@ DBGPerspective::on_conf_key_changed_signal (const UString &a_key,
NEMIVER_TRY
if (a_key == CONF_KEY_NEMIVER_SOURCE_DIRS) {
LOG_DD ("updated key source-dirs");
- m_priv->global_search_paths = boost::get<UString> (a_value).split_to_list (":");
+ m_priv->global_search_paths =
+ boost::get<UString> (a_value).split_to_list (":");
} else if (a_key == CONF_KEY_SHOW_DBG_ERROR_DIALOGS) {
m_priv->show_dbg_errors = boost::get<bool> (a_value);
} else if (a_key == CONF_KEY_SHOW_SOURCE_LINE_NUMBERS) {
@@ -2386,7 +2393,11 @@ DBGPerspective::on_conf_key_changed_signal (const UString &a_key,
m_priv->num_instr_to_disassemble = val;
} else if (a_key == CONF_KEY_ASM_STYLE_PURE) {
m_priv->asm_style_pure = boost::get<bool> (a_value);
+ } else if (a_key == CONF_KEY_PRETTY_PRINTING) {
+ get_local_vars_inspector ()
+ .visualize_local_variables_of_current_function ();
}
+
NEMIVER_CATCH
}
diff --git a/src/persp/dbgperspective/nmv-local-vars-inspector.cc b/src/persp/dbgperspective/nmv-local-vars-inspector.cc
index 1fba95b..182f619 100644
--- a/src/persp/dbgperspective/nmv-local-vars-inspector.cc
+++ b/src/persp/dbgperspective/nmv-local-vars-inspector.cc
@@ -381,6 +381,7 @@ public:
Gtk::TreeModel::iterator parent_row_it;
if (get_function_arguments_row_iterator (parent_row_it)) {
+ LOG_DD ("appending argument: " << a_var->name ());
vutil::append_a_variable (a_var,
*tree_view,
tree_store,
@@ -410,6 +411,53 @@ public:
}
}
+ /// Graphically update a local variable that has been
+ /// re-visualized.
+ ///
+ /// Re-visualization means that the variable's members have been
+ /// erased and the variable has been re-built, probably using a
+ /// different visualizer, at the backend level.
+ ///
+ /// \param a_var the local variable to grpahically update.
+ void
+ update_a_visualized_local_variable (const IDebugger::VariableSafePtr a_var)
+ {
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ THROW_IF_FAIL (tree_view);
+
+ Gtk::TreeModel::iterator parent_row_it, row_it;
+ if (get_local_variables_row_iterator (parent_row_it)) {
+ THROW_IF_FAIL (vutil::find_a_variable (a_var,
+ parent_row_it,
+ row_it));
+ vutil::visualize_a_variable (a_var, row_it,
+ *tree_view, tree_store);
+ }
+ }
+
+ /// Like update_a_visualized_local_variable, but for a function
+ /// argument.
+ ///
+ /// \param a_var the function argument variable to graphically
+ /// update.
+ void
+ update_a_visualized_function_arg (const IDebugger::VariableSafePtr a_var)
+ {
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ THROW_IF_FAIL (tree_view);
+
+ Gtk::TreeModel::iterator parent_row_it, row_it;
+ if (get_function_arguments_row_iterator (parent_row_it)) {
+ THROW_IF_FAIL (vutil::find_a_variable (a_var, parent_row_it,
+ row_it));
+ vutil::visualize_a_variable (a_var, row_it,
+ *tree_view,
+ tree_store);
+ }
+ }
+
/// \return true if the variable was found in the TreeModel, false
/// otherwise. If the variable was found, the function updates it.
bool
@@ -842,6 +890,47 @@ public:
NEMIVER_CATCH
}
+ /// Signal handler called when a local variable has been
+ /// re-visualized, probably using a new pretty-printing
+ /// visualizer.
+ ///
+ /// This function graphically updates the re-visualized local
+ /// variable.
+ ///
+ /// \param a_var the re-visualized variable to act upon.
+ void
+ on_local_var_visualized_signal (const IDebugger::VariableSafePtr a_var)
+
+ {
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ NEMIVER_TRY;
+
+ update_a_visualized_local_variable (a_var);
+
+ NEMIVER_CATCH;
+ }
+
+ /// Signal handler called when a function argument variable has
+ /// been re-visualized by the backend, probably with a new
+ /// pretty-printing visualizer.
+ ///
+ /// This function gaphically updates the re-visualized function
+ /// argument variable.
+ ///
+ /// \param a_arg the re-visualized argument variable to act upon.
+ void
+ on_function_arg_visualized_signal (const IDebugger::VariableSafePtr a_arg)
+ {
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ NEMIVER_TRY;
+
+ update_a_visualized_function_arg (a_arg);
+
+ NEMIVER_CATCH;
+ }
+
void
on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var,
const Gtk::TreeModel::Path a_var_node)
@@ -1147,6 +1236,26 @@ LocalVarsInspector::show_local_variables_of_current_function
m_priv->debugger->list_frames_arguments (frame_level, frame_level);
}
+/// Re-visualize the local variables of the current function, possibly
+/// using the a backend pretty-printing visualizer.
+void
+LocalVarsInspector::visualize_local_variables_of_current_function ()
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+ THROW_IF_FAIL (m_priv);
+ THROW_IF_FAIL (m_priv->debugger);
+
+ IDebugger::VariableList::const_iterator it;
+ for (it = m_priv->local_vars.begin ();
+ it != m_priv->local_vars.end ();
+ ++it)
+ m_priv->debugger->revisualize_variable
+ (*it,
+ sigc::mem_fun
+ (*m_priv,
+ &Priv::on_local_var_visualized_signal));
+}
+
void
LocalVarsInspector::re_init_widget ()
{
diff --git a/src/persp/dbgperspective/nmv-local-vars-inspector.h b/src/persp/dbgperspective/nmv-local-vars-inspector.h
index ce89182..85d0df9 100644
--- a/src/persp/dbgperspective/nmv-local-vars-inspector.h
+++ b/src/persp/dbgperspective/nmv-local-vars-inspector.h
@@ -58,9 +58,10 @@ public:
virtual ~LocalVarsInspector ();
Gtk::Widget& widget () const;
void set_local_variables
- (const std::list<IDebugger::VariableSafePtr> &a_vars);
+ (const std::list<IDebugger::VariableSafePtr> &a_vars);
void show_local_variables_of_current_function
- (const IDebugger::Frame &a_frame);
+ (const IDebugger::Frame &a_frame);
+ void visualize_local_variables_of_current_function ();
void re_init_widget ();
};//end LocalVarsInspector
diff --git a/src/persp/dbgperspective/nmv-variables-utils.cc b/src/persp/dbgperspective/nmv-variables-utils.cc
index 4a078b5..2e4e113 100644
--- a/src/persp/dbgperspective/nmv-variables-utils.cc
+++ b/src/persp/dbgperspective/nmv-variables-utils.cc
@@ -387,6 +387,9 @@ variables_match (const IDebugger::VariableSafePtr &a_var,
return true;
if (!var || !a_var)
return false;
+ if (a_var->internal_name () == var->internal_name ())
+ return true;
+
return var->equals_by_value (*a_var);
}
@@ -546,30 +549,127 @@ append_a_variable (const IDebugger::VariableSafePtr a_var,
if (!a_var) {
return false;
}
- update_a_variable_node (a_var, a_tree_view, row_it,
+ if (!set_a_variable (a_var, a_tree_view, a_tree_store,
+ row_it, a_truncate_type))
+ return false;
+ a_result = row_it;
+ return true;
+}
+
+/// (Re-)render a variable into the node holding its graphical
+/// representation.
+///
+/// \param a_var the variable to render
+///
+/// \param a_tree_view the treeview containing the graphical
+/// representation to set.
+///
+/// \param a_tree_store the treestore of the treeview.
+///
+/// \param a_row_it an iterator to the row of the graphical
+/// representation of the variable.
+///
+/// \param a_truncate_type if set to TRUE, the string representing the
+/// type is going to be truncated if it is too long.
+///
+/// \return TRUE upon successful completion
+bool
+set_a_variable (const IDebugger::VariableSafePtr a_var,
+ const Gtk::TreeView &a_tree_view,
+ const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
+ Gtk::TreeModel::iterator a_row_it,
+ bool a_truncate_type)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+ THROW_IF_FAIL (a_tree_store);
+
+ if (!a_var) {
+ return false;
+ }
+
+ update_a_variable_node (a_var, a_tree_view, a_row_it,
a_truncate_type, true, true);
+
list<IDebugger::VariableSafePtr>::const_iterator it;
if (a_var->needs_unfolding ()) {
// Mark *row_it as needing unfolding, and add an empty
// child node to it
- (*row_it)[get_variable_columns ().needs_unfolding] = true;
+ (*a_row_it)[get_variable_columns ().needs_unfolding] = true;
IDebugger::VariableSafePtr empty_var;
append_a_variable (empty_var, a_tree_view,
- a_tree_store, row_it,
+ a_tree_store, a_row_it,
a_truncate_type);
} else {
for (it = a_var->members ().begin ();
it != a_var->members ().end ();
++it) {
append_a_variable (*it, a_tree_view,
- a_tree_store, row_it,
+ a_tree_store, a_row_it,
a_truncate_type);
}
}
- a_result = row_it;
return true;
}
+/// Unlink the graphical nodes representing the member variables of
+/// the variable pointed to by the given row iterator.
+///
+/// \param a_row_it the iterator pointing at the graphical node which
+/// containing the variable which member variables we want to unlink.
+///
+/// \param a_store the treestore containing a_row_it.
+bool
+unlink_member_variable_rows (const Gtk::TreeModel::iterator &a_row_it,
+ const Glib::RefPtr<Gtk::TreeStore> &a_store)
+{
+ IDebugger::VariableSafePtr var;
+
+ var = a_row_it->get_value (get_variable_columns ().variable);
+ if (!var)
+ return false;
+
+ vector<Gtk::TreePath> paths;
+ for (Gtk::TreeModel::iterator it = a_row_it->children ().begin ();
+ it != a_row_it->children ().end ();
+ ++it) {
+ var = it->get_value (get_variable_columns ().variable);
+ if (var)
+ paths.push_back (a_store->get_path (it));
+ }
+ for (int i = paths.size (); i > 0; --i) {
+ Gtk::TreeIter it = a_store->get_iter (paths[i - 1]);
+ IDebugger::VariableSafePtr empty_var;
+ (*it)->get_value(get_variable_columns ().variable).reset ();
+ a_store->erase (it);
+ }
+ return true;
+}
+
+/// Re-visualize a given variable. That is, unlink the graphical
+/// nodes of the member variables of the given variable, and
+/// re-visualize that same variable into its graphical node.
+///
+/// \param a_var the variable to re-visualize
+///
+/// \param a_row_it an iterator to the graphical node of the variable
+/// to re-visualize
+///
+/// \param a_tree_view the treeview containing the graphical node
+///
+/// \param a_store the tree store containing the graphical node
+bool
+visualize_a_variable (const IDebugger::VariableSafePtr a_var,
+ const Gtk::TreeModel::iterator &a_row_it,
+ const Gtk::TreeView &a_tree_view,
+ const Glib::RefPtr<Gtk::TreeStore> &a_store)
+{
+ if (!unlink_member_variable_rows (a_row_it, a_store))
+ return false;
+
+ return set_a_variable (a_var, a_tree_view,
+ a_store, a_row_it,
+ /*a_truncate_type=*/true);
+}
NEMIVER_END_NAMESPACE (variables_utils2)
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/persp/dbgperspective/nmv-variables-utils.h b/src/persp/dbgperspective/nmv-variables-utils.h
index d0c2cf0..d650ec2 100644
--- a/src/persp/dbgperspective/nmv-variables-utils.h
+++ b/src/persp/dbgperspective/nmv-variables-utils.h
@@ -126,6 +126,20 @@ bool append_a_variable (const IDebugger::VariableSafePtr a_var,
Gtk::TreeModel::iterator &a_result,
bool a_truncate_type);
+bool set_a_variable (const IDebugger::VariableSafePtr a_var,
+ const Gtk::TreeView &a_tree_view,
+ const Glib::RefPtr<Gtk::TreeStore> &a_tree_store,
+ Gtk::TreeModel::iterator a_row_it,
+ bool a_truncate_type);
+
+bool unlink_member_variable_rows (const Gtk::TreeModel::iterator &a_row_it,
+ const Glib::RefPtr<Gtk::TreeStore> &a_store);
+
+bool visualize_a_variable (const IDebugger::VariableSafePtr a_var,
+ const Gtk::TreeModel::iterator &a_var_row_it,
+ const Gtk::TreeView &a_tree_view,
+ const Glib::RefPtr<Gtk::TreeStore> &a_store);
+
NEMIVER_END_NAMESPACE (variables_utils2)
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/tests/test-breakpoint.cc b/tests/test-breakpoint.cc
index e91f2ef..d8a20fc 100644
--- a/tests/test-breakpoint.cc
+++ b/tests/test-breakpoint.cc
@@ -242,7 +242,7 @@ test_main (int argc, char *argv[])
//*****************************
std::vector<UString> args, source_search_dir;
- debugger->disable_pretty_printing ();
+ debugger->enable_pretty_printing (false);
source_search_dir.push_back (".");
debugger->load_program ("fooprog", args, ".", source_search_dir);
debugger->set_breakpoint ("main");
diff --git a/tests/test-types.cc b/tests/test-types.cc
index 739a642..46ab536 100644
--- a/tests/test-types.cc
+++ b/tests/test-types.cc
@@ -96,7 +96,7 @@ test_main (int, char **)
debugger->variable_value_signal ().connect (&on_variable_value_signal);
- debugger->disable_pretty_printing ();
+ debugger->enable_pretty_printing (false);
std::vector<UString> args, source_search_dir;
source_search_dir.push_back (".");
debugger->load_program ("fooprog", args, ".", source_search_dir);
diff --git a/tests/test-var-path-expr.cc b/tests/test-var-path-expr.cc
index 4ab9f86..035a491 100644
--- a/tests/test-var-path-expr.cc
+++ b/tests/test-var-path-expr.cc
@@ -139,7 +139,7 @@ test_main (int argc, char *argv[])
debugger));
std::vector<UString> args, source_search_dir;
- debugger->disable_pretty_printing ();
+ debugger->enable_pretty_printing (false);
source_search_dir.push_back (".");
debugger->load_program ("fooprog", args, ".", source_search_dir);
debugger->set_breakpoint ("main");
diff --git a/tests/test-vars.cc b/tests/test-vars.cc
index 9fc4097..380e619 100644
--- a/tests/test-vars.cc
+++ b/tests/test-vars.cc
@@ -274,7 +274,7 @@ test_main (int argc __attribute__((unused)),
//</connect to IDebugger events>
//******************************
vector<UString> args;
- debugger->disable_pretty_printing ();
+ debugger->enable_pretty_printing (false);
debugger->load_program ("fooprog", args, ".");
debugger->set_breakpoint ("main");
debugger->set_breakpoint ("func4");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]