[nemiver/better-variable-format: 1/8] Backend support for GDB/MI variable format



commit 2603126a5cddb10bcbd0d1d846e4eb2228e64d1d
Author: Dodji Seketeli <dodji gnome org>
Date:   Mon Aug 30 11:15:55 2010 +0200

    Backend support for GDB/MI variable format
    
    	* src/dbgengine/nmv-gdbmi-parser.h (parse_variable_format):
    	Declare new GDBMI parser entry point.
    	* src/dbgengine/nmv-gdbmi-parser.cc (parse_variable_format):
    	Define it.
    	(parse_result_record): Support variable format result record. Use
    	parse_variable_format.
    	* src/dbgengine/nmv-i-debugger.h (IDebugger::Variable::Format):
    	New enum.
    	(query_variable_format, set_variable_format): Declare new entry
    	points.
    	* src/dbgengine/nmv-dbg-common.h (ResultRecord::variable_format)
    	(ResultRecord::has_variable_format): New accessors to support
    	variable format in the result record.
    	* src/dbgengine/nmv-debugger-utils.[cc|h] (string_to_variable_format)
    	(variable_format_to_string): New (de)serialization functions.
    	* src/dbgengine/nmv-gdb-engine.h (query_variable_format)
    	(set_variable_format): Likewise.
    	* src/dbgengine/nmv-gdb-engine.cc (query_variable_format)
    	(set_variable_format): Define these.
    	(struct OnVariableFormatHandler): New output handler.
    	(init_output_handlers): Add it to the list of output handlers.
    	* src/dbgengine/Makefile.am: Make the libgdbmod use the static lib
    	libdebuggerutils.
    	* tests/test-variable-format.cc: New test.
    	* tests/Makefile.am: Added new test-variable-format to the build
    	system. Link runtestgdbmi and runtestvarobjwalker with
    	libdebuggerutils.la
    	* tests/fooprog.cc: Add a new func1_1 to test for some variable
    	value. Used by the new tests/test-variable-format.cc.

 src/dbgengine/Makefile.am           |    4 +-
 src/dbgengine/nmv-dbg-common.h      |   25 +++++++++
 src/dbgengine/nmv-debugger-utils.cc |   57 +++++++++++++++++++++
 src/dbgengine/nmv-debugger-utils.h  |    4 ++
 src/dbgengine/nmv-gdb-engine.cc     |   92 +++++++++++++++++++++++++++++++++++
 src/dbgengine/nmv-gdb-engine.h      |    8 +++
 src/dbgengine/nmv-gdbmi-parser.cc   |   76 +++++++++++++++++++++++++++++
 src/dbgengine/nmv-gdbmi-parser.h    |    5 ++
 src/dbgengine/nmv-i-debugger.h      |   27 ++++++++++-
 tests/Makefile.am                   |    6 ++-
 tests/fooprog.cc                    |    9 +++-
 tests/test-variable-format.cc       |    3 +-
 12 files changed, 308 insertions(+), 8 deletions(-)
---
diff --git a/src/dbgengine/Makefile.am b/src/dbgengine/Makefile.am
index f1f1d10..8415db2 100644
--- a/src/dbgengine/Makefile.am
+++ b/src/dbgengine/Makefile.am
@@ -95,8 +95,8 @@ publicheaders_DATA=$(dynmodheaders)
 publicheadersdir=$(NEMIVER_INCLUDE_DIR)/dynmods
 
 libgdbmod_la_LDFLAGS=-module -avoid-version -Wl,--as-needed
-libgdbmod_la_LIBADD=libdbgcommon.la libgdbmiparser.la libgdbengine.la \
- NEMIVERCOMMON_LIBS@ \
+libgdbmod_la_LIBADD=libdbgcommon.la libgdbmiparser.la \
+libgdbengine.la libdebuggerutils.la @NEMIVERCOMMON_LIBS@ \
 $(abs_top_builddir)/src/langs/libnemivercparser.la \
 $(abs_top_builddir)/src/common/libnemivercommon.la
 
diff --git a/src/dbgengine/nmv-dbg-common.h b/src/dbgengine/nmv-dbg-common.h
index 3885e3d..7f48b25 100644
--- a/src/dbgengine/nmv-dbg-common.h
+++ b/src/dbgengine/nmv-dbg-common.h
@@ -434,6 +434,10 @@ public:
         UString m_path_expression;
         bool m_has_path_expression;
 
+        // The variable format of a variable object
+        IDebugger::Variable::Format m_variable_format;
+        bool m_has_variable_format;
+
     public:
         ResultRecord () {clear ();}
 
@@ -476,6 +480,8 @@ public:
             m_has_changed_var_list = false;
             m_path_expression.clear ();
             m_has_path_expression = false;
+            m_variable_format = IDebugger::Variable::UNDEFINED_FORMAT;
+            m_has_variable_format = false;
         }
 
         /// \name accessors
@@ -751,6 +757,25 @@ public:
             m_has_path_expression = a;
         }
 
+        IDebugger::Variable::Format variable_format () const
+        {
+            return m_variable_format;
+        }
+        void variable_format (IDebugger::Variable::Format a_format)
+        {
+            m_variable_format = a_format;
+            has_variable_format (true);
+        }
+
+        bool has_variable_format () const
+        {
+            return m_has_variable_format;
+        }
+        void has_variable_format (bool a_flag)
+        {
+            m_has_variable_format = a_flag;
+        }
+
         /// @}
 
     };//end class ResultRecord
diff --git a/src/dbgengine/nmv-debugger-utils.cc b/src/dbgengine/nmv-debugger-utils.cc
index 9842fff..abbd8dc 100644
--- a/src/dbgengine/nmv-debugger-utils.cc
+++ b/src/dbgengine/nmv-debugger-utils.cc
@@ -139,5 +139,62 @@ load_debugger_iface_with_gconf ()
     return debugger;
 }
 
+/// Read a string and convert it into the IDebugger::Variable::Format
+/// enum.
+/// \param a_str the string to consider
+/// \return resulting format enum
+IDebugger::Variable::Format
+string_to_variable_format (const std::string &a_str)
+{
+    IDebugger::Variable::Format result =
+        IDebugger::Variable::UNKNOWN_FORMAT;
+
+    if (a_str == "binary") {
+        result = IDebugger::Variable::BINARY_FORMAT;
+    } else if (a_str == "decimal") {
+        result = IDebugger::Variable::DECIMAL_FORMAT;
+    } else if (a_str == "hexadecimal") {
+        result = IDebugger::Variable::HEXADECIMAL_FORMAT;
+    } else if (a_str == "octal") {
+        result = IDebugger::Variable::OCTAL_FORMAT;
+    } else if (a_str == "natural") {
+        result = IDebugger::Variable::NATURAL_FORMAT;
+    }
+    return result;
+}
+
+/// Serialize an IDebugger::Variable::Format enum into a string.
+/// \param a_format the instance of format to serialize.
+/// \return the resulting serialization.
+std::string
+variable_format_to_string (IDebugger::Variable::Format a_format)
+{
+    std::string result;
+    switch (a_format) {
+    case IDebugger::Variable::UNDEFINED_FORMAT:
+        result = "undefined";
+        break;
+    case IDebugger::Variable::BINARY_FORMAT:
+        result = "binary";
+        break;
+    case IDebugger::Variable::DECIMAL_FORMAT:
+        result = "decimal";
+        break;
+    case IDebugger::Variable::HEXADECIMAL_FORMAT:
+        result = "hexadecimal";
+        break;
+    case IDebugger::Variable::OCTAL_FORMAT:
+        result = "octal";
+        break;
+    case IDebugger::Variable::NATURAL_FORMAT:
+        result = "natural";
+        break;
+    case IDebugger::Variable::UNKNOWN_FORMAT:
+        result = "unknown";
+        break;
+    }
+    return result;
+}
+
 NEMIVER_END_NAMESPACE (debugger_utils)
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/dbgengine/nmv-debugger-utils.h b/src/dbgengine/nmv-debugger-utils.h
index caa7ada..7ffb4e0 100644
--- a/src/dbgengine/nmv-debugger-utils.h
+++ b/src/dbgengine/nmv-debugger-utils.h
@@ -49,6 +49,10 @@ void dump_variable_value (IDebugger::VariableSafePtr a_var,
 
 IDebuggerSafePtr load_debugger_iface_with_gconf ();
 
+IDebugger::Variable::Format string_to_variable_format (const std::string &);
+
+std::string variable_format_to_string (IDebugger::Variable::Format);
+
 NEMIVER_END_NAMESPACE (debugger_utils)
 NEMIVER_END_NAMESPACE (nemiver)
 
diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index 7df7866..b34e2a5 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -2643,6 +2643,45 @@ struct OnListChangedVariableHandler : public OutputHandler
     }
 };//end OnListChangedVariableHandler
 
+struct OnVariableFormatHandler : public OutputHandler
+{
+    GDBEngine *m_engine;
+
+    OnVariableFormatHandler (GDBEngine *a_engine) :
+        m_engine (a_engine)
+    {
+    }
+
+    bool can_handle (CommandAndOutput &a_in)
+    {
+        if (a_in.command ().name () == "query-variable-format"
+            && a_in.output ().result_record ().kind ()
+               == Output::ResultRecord::DONE) {
+            return true;
+        }
+        return false;
+    }
+
+    void do_handle (CommandAndOutput &a_in)
+    {
+        if (a_in.command ().name () == "query-variable-format"
+            && a_in.output ().result_record ().has_variable_format ()) {
+            // Set the result we got from gdb into the variable handed to us
+            // by the the client code.
+            a_in.command ().variable ()->format
+                (a_in.output ().result_record ().variable_format ());
+
+            // Call the slot associated to
+            // IDebugger::query_variable_format.
+            if (a_in.command ().has_slot ()) {
+                typedef IDebugger::ConstVariableSlot SlotType;
+                SlotType slot = a_in.command ().get_slot<SlotType> ();
+                slot (a_in.command ().variable ());
+            }
+        }
+    }
+};//end OnVariableFormatHandler
+
 //****************************
 //</GDBengine output handlers
 //***************************
@@ -3011,6 +3050,8 @@ GDBEngine::init_output_handlers ()
             (OutputHandlerSafePtr (new OnUnfoldVariableHandler (this)));
     m_priv->output_handler_list.add
             (OutputHandlerSafePtr (new OnListChangedVariableHandler (this)));
+    m_priv->output_handler_list.add
+            (OutputHandlerSafePtr (new OnVariableFormatHandler (this)));
 }
 
 sigc::signal<void, Output&>&
@@ -5031,6 +5072,57 @@ GDBEngine::query_variable_path_expr (const VariableSafePtr a_var,
     queue_command (command);
 }
 
+/// Ask GDB what the value display format of a variable is.
+/// \param a_var the variable to consider
+/// \param a_slot the slot to invoke upon receiving the reply from
+/// GDB.
+/// \param a_cookie the cookie of this request
+void
+GDBEngine::query_variable_format (const VariableSafePtr a_var,
+                                  const ConstVariableSlot &a_slot,
+                                  const UString &a_cookie)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    THROW_IF_FAIL (a_var);
+    THROW_IF_FAIL (!a_var->internal_name ().empty ());
+
+    UString cmd_str = "-var-show-format ";
+    cmd_str += a_var->internal_name ();
+
+    Command command ("query-variable-format",
+                     cmd_str, a_cookie);
+    command.variable (a_var);
+    command.set_slot (a_slot);
+    queue_command (command);
+}
+
+/// Set the value display format of variable a_var
+/// \param a_var the variable to consider
+/// \param a_format the format to set the display format of the
+/// variable to.
+/// \param a_cookie the cookie of this request.
+void
+GDBEngine::set_variable_format (const VariableSafePtr a_var,
+				const Variable::Format a_format,
+				const UString &a_cookie)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    THROW_IF_FAIL (a_var);
+    THROW_IF_FAIL (!a_var->internal_name ().empty ());
+    THROW_IF_FAIL (a_format > IDebugger::Variable::UNDEFINED_FORMAT
+                   && a_format < IDebugger::Variable::UNKNOWN_FORMAT);
+
+    UString cmd_str = "-var-set-format ";
+    cmd_str +=
+        a_var->internal_name () + " " +
+        debugger_utils::variable_format_to_string (a_format);
+    Command command ("set-variable-format",
+                     cmd_str, a_cookie);
+    queue_command (command);
+}
+
 //****************************
 //</GDBEngine methods>
 //****************************
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index fd986b8..0ba717c 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -548,6 +548,14 @@ public:
     void query_variable_path_expr (const VariableSafePtr,
                                    const ConstVariableSlot &a_slot,
                                    const UString &a_cookie);
+
+    void query_variable_format (const VariableSafePtr a_var,
+                                const ConstVariableSlot &a_slot,
+                                const UString &a_cookie);
+
+    void set_variable_format (const VariableSafePtr a_var,
+			      const Variable::Format a_format,
+			      const UString &a_cookie);
 };//end class GDBEngine
 
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/dbgengine/nmv-gdbmi-parser.cc b/src/dbgengine/nmv-gdbmi-parser.cc
index b76d970..145e8c0 100644
--- a/src/dbgengine/nmv-gdbmi-parser.cc
+++ b/src/dbgengine/nmv-gdbmi-parser.cc
@@ -26,7 +26,9 @@
 #include <cstring>
 #include <sstream>
 #include "common/nmv-str-utils.h"
+#include "common/nmv-asm-utils.h"
 #include "nmv-gdbmi-parser.h"
+#include "nmv-debugger-utils.h"
 
 using nemiver::common::UString;
 
@@ -194,6 +196,7 @@ const char* CHANGELIST = "changelist";
 const char* PREFIX_PATH_EXPR = "path_expr=";
 const char* PATH_EXPR = "path_expr";
 static const char* PREFIX_ASM_INSTRUCTIONS= "asm_insns=";
+const char* PREFIX_VARIABLE_FORMAT = "format=";
 
 static bool
 is_string_start (gunichar a_c)
@@ -2013,6 +2016,22 @@ fetch_gdbmi_result:
                 } else {
                     LOG_PARSING_ERROR2 (cur);
                 }
+            } else if (!RAW_INPUT.compare (cur,
+                                           strlen (PREFIX_VARIABLE_FORMAT),
+                                           PREFIX_VARIABLE_FORMAT)) {
+                IDebugger::Variable::Format format =
+                            IDebugger::Variable::UNDEFINED_FORMAT;
+                UString value;
+                if (parse_variable_format (cur, cur, format, value)) {
+                    result_record.variable_format (format);
+                    if (!value.empty ()) {
+                        IDebugger::VariableSafePtr var (new IDebugger::Variable);
+                        var->value (value);
+                        result_record.variable_value (var);
+                    }
+                } else {
+                    LOG_PARSING_ERROR2 (cur);
+                }
             } else {
                 GDBMIResultSafePtr result;
                 if (!parse_gdbmi_result (cur, cur, result)
@@ -3633,6 +3652,63 @@ GDBMIParser::parse_var_path_expression (UString::size_type a_from,
 }
 
 bool
+GDBMIParser::parse_variable_format (UString::size_type a_from,
+                                    UString::size_type &a_to,
+                                    IDebugger::Variable::Format &a_format,
+                                    UString &a_value)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_D (GDBMI_PARSING_DOMAIN);
+    UString::size_type cur = a_from;
+    CHECK_END2 (cur);
+
+    if (RAW_INPUT.compare (cur, strlen (PREFIX_VARIABLE_FORMAT),
+                           PREFIX_VARIABLE_FORMAT)) {
+        LOG_PARSING_ERROR2 (cur);
+        return false;
+    }
+
+    UString name, value;
+    if (!parse_gdbmi_string_result (cur, cur, name, value)) {
+        LOG_PARSING_ERROR2 (cur);
+        return false;
+    }
+    const char *FORMAT = "format";
+    if (name != FORMAT) {
+        LOG_ERROR ("expected gdbmi variable " << FORMAT << ", got: "
+                   << name << "\'");
+        return false;
+    }
+
+    a_format = debugger_utils::string_to_variable_format (value);
+    if (a_format == IDebugger::Variable::UNKNOWN_FORMAT) {
+        LOG_ERROR ("got unknown variable format: '" << a_format << "'");
+        return false;
+    }
+
+    SKIP_WS2 (cur);
+    if (RAW_CHAR_AT (cur) == ',') {
+        ++cur;
+        SKIP_WS2 (cur);
+        name.clear (), value.clear ();
+        if (!parse_gdbmi_string_result (cur, cur, name, value)) {
+            LOG_PARSING_ERROR2 (cur);
+            return false;
+        }
+        const char *VALUE = "value";
+        if (name == VALUE) {
+            if (value.empty ()) {
+                LOG_ERROR ("the 'value' property should have a non-empty value");
+                return true;
+            }
+            a_value = value;
+        }
+    }
+
+    a_to = cur;
+    return true;
+}
+
+bool
 GDBMIParser::parse_register_names (UString::size_type a_from,
                                    UString::size_type &a_to,
                                    std::map<IDebugger::register_id_t,
diff --git a/src/dbgengine/nmv-gdbmi-parser.h b/src/dbgengine/nmv-gdbmi-parser.h
index 01d3c80..3b2d0ea 100644
--- a/src/dbgengine/nmv-gdbmi-parser.h
+++ b/src/dbgengine/nmv-gdbmi-parser.h
@@ -639,6 +639,11 @@ public:
                                     UString::size_type &a_to,
                                     UString &a_expression);
 
+    bool parse_variable_format (UString::size_type a_from,
+                                UString::size_type &a_to,
+                                IDebugger::Variable::Format &a_format,
+                                UString &a_value);
+
     bool parse_result_record (UString::size_type a_from,
                               UString::size_type &a_to,
                               Output::ResultRecord &a_record);
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index 9c869ff..d1803bc 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -339,6 +339,17 @@ public:
     typedef SafePtr<Variable, ObjectRef, ObjectUnref> VariableSafePtr;
     typedef list<VariableSafePtr> VariableList;
     class Variable : public Object {
+    public:
+        enum Format {
+            UNDEFINED_FORMAT = 0,
+            BINARY_FORMAT,
+            DECIMAL_FORMAT,
+            HEXADECIMAL_FORMAT,
+            OCTAL_FORMAT,
+            NATURAL_FORMAT,
+            UNKNOWN_FORMAT // must be last
+        };
+    private:
         // non copyable.
         Variable (const Variable &);
         Variable& operator= (const Variable &);
@@ -366,6 +377,7 @@ public:
         // If empty, it can be set by calling
         // IDebugger::query_variable_path_expr()
         UString m_path_expression;
+        Format m_format;
 
     public:
         Variable (const UString &a_internal_name,
@@ -377,7 +389,8 @@ public:
             m_value (a_value),
             m_type (a_type),
             m_parent (0),
-            m_num_expected_children (0)
+            m_num_expected_children (0),
+            m_format (UNDEFINED_FORMAT)
 
         {
         }
@@ -746,6 +759,10 @@ public:
         {
             m_path_expression = a_expr;
         }
+
+        Format format () const {return m_format;}
+        void format (Format a_format) {m_format = a_format;}
+
     };//end class Variable
 
     enum State {
@@ -1309,10 +1326,18 @@ public:
 
     virtual void query_variable_path_expr (const VariableSafePtr a_var,
                                            const UString &a_cookie = "") = 0;
+
     virtual void query_variable_path_expr (const VariableSafePtr a_var,
                                            const ConstVariableSlot &a_slot,
                                            const UString &a_cookie = "") = 0;
 
+    virtual void query_variable_format (const VariableSafePtr a_var,
+                                        const ConstVariableSlot &a_slot,
+                                        const UString &a_cookie = "") = 0;
+
+    virtual void set_variable_format (const VariableSafePtr a_var,
+                                      const Variable::Format a_format,
+                                      const UString &a_cookie = "") = 0;
 };//end IDebugger
 
 NEMIVER_END_NAMESPACE (nemiver)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 03d6ab0..53bf4d2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -15,7 +15,8 @@ runtestwatchpoint runtestderef \
 runtestlocalvarslist runtestcpplexer \
 runtestcppparser runtestvarpathexpr \
 runtestlibtoolwrapperdetection \
-runtestenv runtesttypes runtestdisassemble
+runtestenv runtesttypes runtestdisassemble \
+runtestvariableformat
 
 else
 
@@ -34,7 +35,8 @@ runtestgdbmi_SOURCES=$(h)/test-gdbmi.cc
 runtestgdbmi_LDADD= @NEMIVERCOMMON_LIBS@ \
 @BOOST_UNIT_TEST_FRAMEWORK_STATIC_LIB@ \
 $(top_builddir)/src/common/libnemivercommon.la \
-$(top_builddir)/src/dbgengine/libgdbmiparser.la
+$(top_builddir)/src/dbgengine/libgdbmiparser.la \
+$(top_builddir)/src/dbgengine/libdebuggerutils.la
 
 gtkmmtest_SOURCES=$(h)/gtkmm-test.cc
 gtkmmtest_CXXFLAGS= @NEMIVERUICOMMON_CFLAGS@
diff --git a/tests/fooprog.cc b/tests/fooprog.cc
index 430af63..61bdb96 100644
--- a/tests/fooprog.cc
+++ b/tests/fooprog.cc
@@ -2,10 +2,17 @@
 #include <iostream>
 
 void
+func1_1 (int i_i)
+{
+  ++i_i;
+}
+
+void
 func1 ()
 {
-    int i = 0;
+    int i = 17;
     ++i;
+    func1_1 (i);
 }
 
 void
diff --git a/tests/test-variable-format.cc b/tests/test-variable-format.cc
index 1268d64..c74590f 100644
--- a/tests/test-variable-format.cc
+++ b/tests/test-variable-format.cc
@@ -114,7 +114,7 @@ test_main (int, char **)
     //load the IDebugger interface
     IDebuggerSafePtr debugger =
         debugger_utils::load_debugger_iface_with_gconf ();
-        
+
     //setup the debugger with the glib mainloop
     debugger->set_event_loop_context (Glib::MainContext::get_default ());
 
@@ -140,7 +140,6 @@ test_main (int, char **)
     //****************************************
     s_loop->run ();
 
-
     NEMIVER_CATCH_AND_RETURN_NOX (-1);
 
     BOOST_REQUIRE (s_got_format);



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