[Nemiver-list] global variables support patch



Hello,


Here's a first try at global variables.

It's kind of messy and far from perfect, but it at least it works...

Most of the code was duplicated from the local-variables handling, and
modified where needed.


Three patch files attached:


i-debugger-h

----------------

This adds two methods to the IDebugger interface. One
(list_global_variables) asks the debugger for a list a global variables,
the secone (global_variables_listed_signal) is a list of signal which
will fire when the debugger.


gdb-engine-cc

-------------------

This patch adds the implementation for the above two methods, and adds a
new struct called "OnGlobalVariablesListedHandler". It is based on
"OnLocalVariablesListedHandler" but it is messier, because here we need
to parse a textual string returned by GDB (remember that global
variables are listed with "info-variables" command, as
"-symbol-list-variables" is not implemented in GDB yet).

Basically, it iterates over all global variables, collects the into a
list<VariableSafePtr> and then emits the "global_variables_listed" signal.


local-vars-inspector-cc

-----------------------------

Even though you're planning a re-write of the variables widget, I wanted
to see the globals right now... so this patch adds a third row to the
variables inspector, called "Global Variables" besides "Local Variables"
and "Function Arguments".

Most of the added code is simply a duplication of the local variable
handling.


When you see "if (it)" or "if (!ret)" in the patch, it means the
original code was first trying something at the local variables, and if
that failed ("if (!ret)"), tried it on the function argument variables.
this patch adds another try, at the global variables.



----------


This was tested against SVN revision 554.

If you patch from inside the nemiver directory, you might need "patch
-p1" to make it work.



Comments are welcomed,

     Gordon.





--- nemiver/src/dbgengine/nmv-gdb-engine.cc	2007-09-07 16:18:11.000000000 +0300
+++ nemiver-globals/src/dbgengine/nmv-gdb-engine.cc	2007-09-07 15:43:32.000000000 +0300
@@ -139,6 +139,9 @@ public:
     sigc::signal<void, const list<VariableSafePtr>&, const UString&>&
                         local_variables_listed_signal () const ;
 
+    sigc::signal<void, const list<VariableSafePtr>&, const UString&>&
+                        global_variables_listed_signal () const ;
+
     sigc::signal<void,
                  const UString&,
                  const IDebugger::VariableSafePtr&,
@@ -318,6 +321,8 @@ public:
                                 const UString &a_cookie) ;
 
     void list_local_variables (const UString &a_cookie) ;
+    
+    void list_global_variables ( const UString &a_cookie ) ;
 
     void evaluate_expression (const UString &a_expr,
                               const UString &a_cookie) ;
@@ -471,6 +476,9 @@ struct GDBEngine::Priv {
     mutable sigc::signal<void, const list<VariableSafePtr>&, const UString& >
                                     local_variables_listed_signal  ;
 
+    mutable sigc::signal<void, const list<VariableSafePtr>&, const UString& >
+                                    global_variables_listed_signal  ;
+
     mutable sigc::signal<void,
                          const UString&,
                          const IDebugger::VariableSafePtr&,
@@ -1704,6 +1712,146 @@ struct OnLocalVariablesListedHandler : O
     }
 };//struct OnLocalVariablesListedHandler
 
+struct OnGlobalVariablesListedHandler : OutputHandler {
+
+    GDBEngine *m_engine ;
+
+    OnGlobalVariablesListedHandler (GDBEngine *a_engine) :
+        m_engine (a_engine)
+    {}
+
+    bool can_handle (CommandAndOutput &a_in)
+    {
+        if (a_in.command().name()=="list-global-variables") {
+            LOG_DD ("list-global-variables / -symbol-list-variables handler selected") ;
+            return true ;
+        }
+        return false ;
+    }
+    
+    /*
+	parse the result of gdb's "info variables" command.
+    
+	To understand what the heck is going on here, simply run "info variables"
+	inside a running gdb.
+    
+	Each line of gdb's result is put inside an "OutOfBandRecord" object.
+	This function collects all the (non-empty) lines, and extract the global variables'
+	names and types.
+    */
+    void parse_info_variables_list(Output &a_output, list<IDebugger::VariableSafePtr> &var_list)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD ;
+
+        NEMIVER_TRY
+
+	bool first_line = true ;
+	UString current_file;
+
+	if (a_output.has_out_of_band_record()) {
+		list<Output::OutOfBandRecord>::iterator it = a_output.out_of_band_records().begin();
+		while (it != a_output.out_of_band_records().end() ) {
+			const Output::OutOfBandRecord &oobr = *it ;
+			if (oobr.has_stream_record()) {
+				const Output::StreamRecord &sr = oobr.stream_record();
+				
+				UString line (sr.debugger_console());
+				
+				//Empty lines, or lines with only "\n"
+				if (line.length()<=1) {
+					it++;
+					continue ;
+				}
+				
+				line.erase(line.length()-1,1); //chomp
+				
+				if (first_line) {
+					if (line.compare(0,22,"All defined variables:")==0) {
+						first_line=false;
+						it++;
+						continue ;
+					}
+					else {
+						LOG_DD("globals: First result line isn't \"All Defined Variables:\". bad GDB ? line follows:");
+						LOG_DD("globals: " << line ) ;
+						break ;
+					}
+				}
+				
+				
+				if ( (line.compare(0,5,"File ") == 0) && (line.at(line.length()-1)==':') ) {
+					//New file ?
+					line.erase(0,5);
+					line.erase(line.length()-1,1);
+					current_file = line;
+					LOG_DD("globals: new file: " << current_file ) ;
+				}
+				else 
+				if (line.compare("Non-debugging symbols:")==0) {
+					//We're not interested in non-debugging symbols, so we can stop now
+					LOG_DD("got Non-debugging symbols, stopping.");
+					break ;
+				} else 
+				if (line.at(line.length()-1)==';') {
+					//Every global variable is expected to end with ';' character
+					//in gdb's "info variables" command.
+					line.erase(line.length()-1,1);
+					
+					vector<UString> parts = line.split(" ");
+					//The last part is the variable's name.
+					//The one-before-last part is the variable's type.
+					//Before that "const" and "static" may appear
+					
+					Glib::ustring vName = parts.back();
+					parts.pop_back();
+					Glib::ustring vType = parts.back();
+					
+					if (vName.at(0)=='*')
+						vName.erase(0,1);
+					
+					LOG_DD("globals: got variable: " <<
+						  " File: " << current_file <<
+						  " Name: " << vName <<
+						  " Type: " << vType ) ;
+					
+					IDebugger::VariableSafePtr a_var;
+					a_var = IDebugger::VariableSafePtr (new IDebugger::Variable(vName)) ; 
+					var_list.push_back(a_var);
+					
+				} else {
+					LOG_DD("globals: don't know how to handle line '" << line << "'" ) ;
+				}
+				
+			} else {
+				LOG_DD ("globals: OOB record doesn't have stream_record!!");
+			}
+			it++;
+		}
+	}
+	else {
+		LOG_DD ("globals: no OOB records!!");
+		return ;
+	}
+
+	NEMIVER_CATCH_NOX
+    }
+    
+
+    void do_handle (CommandAndOutput &a_in)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD ;
+        THROW_IF_FAIL (m_engine) ;
+
+	list<IDebugger::VariableSafePtr> var_list;
+	parse_info_variables_list(a_in.output(), var_list);
+	    
+        m_engine->global_variables_listed_signal ().emit
+            (var_list, a_in.command ().cookie ()) ;
+		
+        m_engine->set_state (IDebugger::READY) ;
+    }
+};//struct OnGlobalVariablesListedHandler
+
 struct OnResultRecordHandler : OutputHandler {
 
     GDBEngine *m_engine ;
@@ -2338,6 +2486,8 @@ GDBEngine::init_output_handlers ()
     m_priv->output_handler_list.add
         (OutputHandlerSafePtr (new OnLocalVariablesListedHandler (this)));
     m_priv->output_handler_list.add
+        (OutputHandlerSafePtr (new OnGlobalVariablesListedHandler (this)));
+    m_priv->output_handler_list.add
             (OutputHandlerSafePtr (new OnResultRecordHandler (this))) ;
     m_priv->output_handler_list.add
             (OutputHandlerSafePtr (new OnVariableTypeHandler (this))) ;
@@ -2500,6 +2650,12 @@ GDBEngine::local_variables_listed_signal
     return m_priv->local_variables_listed_signal ;
 }
 
+sigc::signal<void, const list<IDebugger::VariableSafePtr>&, const UString& >&
+GDBEngine::global_variables_listed_signal () const
+{
+    return m_priv->global_variables_listed_signal ;
+}
+
 sigc::signal<void,
              const UString&,
              const IDebugger::VariableSafePtr&,
@@ -3050,6 +3206,16 @@ GDBEngine::list_local_variables (const U
 }
 
 void
+GDBEngine::list_global_variables (const UString &a_cookie)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD ;
+    Command command ("list-global-variables",
+                     "info variables",
+                     a_cookie) ;
+    queue_command (command) ;
+}
+
+void
 GDBEngine::evaluate_expression (const UString &a_expr,
                                 const UString &a_cookie)
 {
--- nemiver/src/dbgengine/nmv-i-debugger.h	2007-09-07 16:18:11.000000000 +0300
+++ nemiver-globals/src/dbgengine/nmv-i-debugger.h	2007-09-07 14:58:16.000000000 +0300
@@ -504,6 +504,9 @@ public:
     virtual sigc::signal<void, const list<VariableSafePtr>&, const UString& >&
                             local_variables_listed_signal () const = 0;
 
+    virtual sigc::signal<void, const list<VariableSafePtr>&, const UString& >&
+                            global_variables_listed_signal () const = 0;
+
     virtual sigc::signal<void,
                          const UString&/*variable name*/,
                          const VariableSafePtr&/*variable*/,
@@ -679,6 +682,8 @@ public:
 
     virtual void list_local_variables (const UString &a_cookie="")  = 0;
 
+    virtual void list_global_variables (const UString &a_cookie="")  = 0;
+
     virtual void evaluate_expression (const UString &a_expr,
                                       const UString &a_cookie="")  = 0;
 
--- nemiver/src/persp/dbgperspective/nmv-local-vars-inspector.cc	2007-09-07 16:18:16.000000000 +0300
+++ nemiver-globals/src/persp/dbgperspective/nmv-local-vars-inspector.cc	2007-09-07 16:29:30.000000000 +0300
@@ -45,8 +45,10 @@ public:
     SafePtr<Gtk::TreeView> tree_view ;
     Glib::RefPtr<Gtk::TreeStore> tree_store ;
     Gtk::TreeModel::iterator cur_selected_row ;
+    SafePtr<Gtk::TreeRowReference> global_variables_row_ref ;
     SafePtr<Gtk::TreeRowReference> local_variables_row_ref ;
     SafePtr<Gtk::TreeRowReference> function_arguments_row_ref ;
+    std::map<UString, IDebugger::VariableSafePtr> global_vars_to_set ;
     std::map<UString, IDebugger::VariableSafePtr> local_vars_to_set ;
     std::map<UString, IDebugger::VariableSafePtr> function_arguments_to_set ;
     SafePtr<Gtk::Menu> contextual_menu ;
@@ -136,6 +138,14 @@ public:
         function_arguments_row_ref.reset
             (new Gtk::TreeRowReference (tree_store, tree_store->get_path (it))) ;
         THROW_IF_FAIL (function_arguments_row_ref) ;
+
+        it = tree_store->append () ;
+        THROW_IF_FAIL (it) ;
+        (*it)[variables_utils::get_variable_columns ().name] =
+                                                        _("Global Variables");
+        global_variables_row_ref.reset
+            (new Gtk::TreeRowReference (tree_store, tree_store->get_path (it))) ;
+        THROW_IF_FAIL (global_variables_row_ref) ;
     }
 
     void get_function_arguments_row_iterator (Gtk::TreeModel::iterator &a_it)
@@ -150,6 +160,12 @@ public:
         a_it = tree_store->get_iter (local_variables_row_ref->get_path ()) ;
     }
 
+    void get_global_variables_row_iterator (Gtk::TreeModel::iterator &a_it)
+    {
+        THROW_IF_FAIL (global_variables_row_ref) ;
+        a_it = tree_store->get_iter (global_variables_row_ref->get_path ()) ;
+    }
+
     bool set_a_variable_type (const UString &a_var_name,
                               const UString &a_type,
                               Gtk::TreeModel::iterator &a_it)
@@ -164,6 +180,10 @@ public:
         Gtk::TreeModel::iterator root_it ;
         get_local_variables_row_iterator (root_it) ;
         bool ret = get_variable_iter_from_qname (a_var_name, root_it, row_it) ;
+	if (!ret) {
+	    get_global_variables_row_iterator(root_it) ;
+	    ret = get_variable_iter_from_qname (a_var_name, root_it, row_it) ;
+	}
         if (!ret) {
             get_function_arguments_row_iterator (root_it) ;
             ret = get_variable_iter_from_qname (a_var_name, root_it, row_it) ;
@@ -216,6 +236,20 @@ public:
         }
     }
 
+    void set_global_variables (const std::list<IDebugger::VariableSafePtr> &a_vars)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD ;
+        THROW_IF_FAIL (tree_store) ;
+        THROW_IF_FAIL (global_variables_row_ref) ;
+
+        std::list<IDebugger::VariableSafePtr>::const_iterator it ;
+        for (it = a_vars.begin () ; it != a_vars.end () ; ++it) {
+            THROW_IF_FAIL ((*it)->name () != "") ;
+            global_vars_to_set[(*it)->name ()] = *it ;
+            debugger->print_variable_value ((*it)->name ()) ;
+        }
+    }
+
     void set_function_arguments
                 (const std::list<IDebugger::VariableSafePtr> &a_vars)
     {
@@ -249,6 +283,11 @@ public:
             LOG_DD ("scheduling function args derefed pointers updating") ;
             update_derefed_pointer_variable_children (it) ;
         }
+        get_global_variables_row_iterator (it) ;
+        if (it) {
+            LOG_DD ("scheduling global derefed pointers updating") ;
+            update_derefed_pointer_variable_children (it) ;
+        }
     }
 
     ///walk the children of a variable
@@ -346,6 +385,8 @@ public:
         THROW_IF_FAIL (debugger) ;
         debugger->local_variables_listed_signal ().connect
             (sigc::mem_fun (*this, &Priv::on_local_variables_listed_signal)) ;
+        debugger->global_variables_listed_signal ().connect
+            (sigc::mem_fun (*this, &Priv::on_global_variables_listed_signal)) ;
         debugger->stopped_signal ().connect
             (sigc::mem_fun (*this, &Priv::on_stopped_signal)) ;
         debugger->variable_value_signal ().connect
@@ -386,6 +427,21 @@ public:
         NEMIVER_CATCH
     }
 
+    void on_global_variables_listed_signal
+                                (const list<IDebugger::VariableSafePtr> &a_vars,
+                                 const UString &a_cookie)
+    {
+        LOG_FUNCTION_SCOPE_NORMAL_DD ;
+
+        if (a_cookie.empty ()) {}
+
+        NEMIVER_TRY
+
+	set_global_variables (a_vars) ;
+		
+        NEMIVER_CATCH
+    }
+
     void on_frames_params_listed_signal
             (const map<int, list<IDebugger::VariableSafePtr> > &a_frames_params,
              const UString &a_cookie)
@@ -443,6 +499,7 @@ public:
                 update_derefed_pointer_variables () ;
             }
             debugger->list_local_variables () ;
+	    debugger->list_global_variables () ;
         }
 
         NEMIVER_CATCH
@@ -473,6 +530,13 @@ public:
         nil = local_vars_to_set.end () ;
         row_ref = local_variables_row_ref.get () ;
         map_ptr = &local_vars_to_set ;
+		
+	if (it == nil) {
+		it = global_vars_to_set.find (a_var_name) ;
+		nil = global_vars_to_set.end () ;
+		row_ref = global_variables_row_ref.get () ;
+		map_ptr = &global_vars_to_set ;
+	}
 
         if (it == nil) {
             it = function_arguments_to_set.find (a_var_name) ;
@@ -614,6 +678,21 @@ public:
         } else {
             ret = get_variable_iter_from_qname (a_var_name, start_row_it, row_it);
         }
+	
+        if (!ret) {
+            get_global_variables_row_iterator (start_row_it) ;
+            ret = get_variable_iter_from_qname ("*" + a_var_name,
+                                                start_row_it, row_it);
+            vars_to_set_map = &global_vars_to_set ;
+            if (ret) {
+                update_ptr_member = true ;
+            } else {
+                ret = get_variable_iter_from_qname (a_var_name,
+                                                    start_row_it,
+                                                    row_it);
+            }
+        }
+
         if (!ret) {
             get_function_arguments_row_iterator (start_row_it) ;
             ret = get_variable_iter_from_qname ("*" + a_var_name,


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