[anjuta] gdb: Add support for pretty printers (gdb > 7.0)
- From: Sebastien Granjoux <sgranjoux src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta] gdb: Add support for pretty printers (gdb > 7.0)
- Date: Sun, 27 Jun 2010 11:06:15 +0000 (UTC)
commit 37f55f6b57a4718f96f930def8f05ad13cbf9825
Author: Sébastien Granjoux <seb sfo free fr>
Date: Sun Jun 27 12:58:04 2010 +0200
gdb: Add support for pretty printers (gdb > 7.0)
libanjuta/interfaces/libanjuta.idl | 1 +
plugins/debug-manager/debug_tree.c | 4 +-
plugins/gdb/Makefile.am | 6 +-
plugins/gdb/anjuta-gdb.plugin.in | 2 +-
plugins/gdb/anjuta-gdb.ui | 124 ++++++++++
plugins/gdb/debugger.c | 122 +++++++++-
plugins/gdb/debugger.h | 11 +-
plugins/gdb/plugin.c | 66 +++++-
plugins/gdb/preferences.c | 467 ++++++++++++++++++++++++++++++++++++
plugins/gdb/preferences.h | 48 ++++
plugins/js-debugger/debugger-js.c | 2 +
11 files changed, 832 insertions(+), 21 deletions(-)
---
diff --git a/libanjuta/interfaces/libanjuta.idl b/libanjuta/interfaces/libanjuta.idl
index edcc4ae..a70920a 100644
--- a/libanjuta/interfaces/libanjuta.idl
+++ b/libanjuta/interfaces/libanjuta.idl
@@ -4560,6 +4560,7 @@ interface IAnjutaDebugger
gboolean exited;
gboolean deleted;
gint children;
+ gboolean has_more;
}
/**
diff --git a/plugins/debug-manager/debug_tree.c b/plugins/debug-manager/debug_tree.c
index f270def..ed196df 100644
--- a/plugins/debug-manager/debug_tree.c
+++ b/plugins/debug-manager/debug_tree.c
@@ -585,7 +585,7 @@ gdb_var_create (IAnjutaDebuggerVariableObject *variable, gpointer user_data, GEr
VALUE_COLUMN, variable->value, -1);
- if (variable->children == -1)
+ if ((variable->children == -1) || variable->has_more)
{
/* Find the number of children */
DmaVariablePacket *pack_child =
@@ -985,7 +985,7 @@ debug_tree_add_watch (DebugTree *tree, const IAnjutaDebuggerVariableObject* var,
(IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
pack);
}
- if (var->children == -1)
+ if ((var->children == -1) || var->has_more)
{
/* Get number of children */
DmaVariablePacket *pack =
diff --git a/plugins/gdb/Makefile.am b/plugins/gdb/Makefile.am
index 1ea0faf..22e7c5b 100644
--- a/plugins/gdb/Makefile.am
+++ b/plugins/gdb/Makefile.am
@@ -4,7 +4,7 @@ gdb_ui_DATA =
# Plugin glade file
anjuta_gladedir = $(anjuta_glade_dir)
-anjuta_glade_DATA =
+anjuta_glade_DATA = anjuta-gdb.ui
anjuta_datadir = $(anjuta_data_dir)
anjuta_data_DATA = gdb.init
@@ -43,7 +43,9 @@ libanjuta_gdb_la_SOURCES = \
plugin.c \
plugin.h \
utilities.c \
- utilities.h
+ utilities.h \
+ preferences.c \
+ preferences.h
noinst_PROGRAMS = gdbmi-test
gdbmi_test_SOURCES = gdbmi-test.c gdbmi.c gdbmi.h debugger.h
diff --git a/plugins/gdb/anjuta-gdb.plugin.in b/plugins/gdb/anjuta-gdb.plugin.in
index f13d5ed..437711f 100644
--- a/plugins/gdb/anjuta-gdb.plugin.in
+++ b/plugins/gdb/anjuta-gdb.plugin.in
@@ -3,7 +3,7 @@ _Name=Gdb
_Description=GNU Debugger Plugin
Location=anjuta-gdb:GdbPlugin
Icon=anjuta-gdb.plugin.png
-UserActivatable=no
+UserActivatable=yes
Interfaces=IAnjutaDebugger
[File Loader]
diff --git a/plugins/gdb/anjuta-gdb.ui b/plugins/gdb/anjuta-gdb.ui
new file mode 100644
index 0000000..369da85
--- /dev/null
+++ b/plugins/gdb/anjuta-gdb.ui
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkWindow" id="gdb_preferences_window">
+ <child>
+ <object class="GtkVBox" id="gdb_preferences_container">
+ <property name="visible">True</property>
+ <signal name="destroy" handler="gdb_on_destroy_preferences" swapped="no"/>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="printers_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <signal name="row-activated" handler="atp_on_tool_activated" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVButtonBox" id="vbuttonbox1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="border_width">5</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">start</property>
+ <child>
+ <object class="GtkButton" id="add_button">
+ <property name="label">gtk-add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="gdb_on_printer_add" swapped="no"/>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove_button">
+ <property name="label">gtk-remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="gdb_on_printer_remove" swapped="no"/>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="fill">True</property>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="ypad">6</property>
+ <property name="label" translatable="yes">Available pretty printers</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/plugins/gdb/debugger.c b/plugins/gdb/debugger.c
index 94a9b9b..140d70b 100644
--- a/plugins/gdb/debugger.c
+++ b/plugins/gdb/debugger.c
@@ -135,6 +135,9 @@ struct _DebuggerPriv
gboolean has_python_support;
gboolean has_thread_info;
gboolean has_frozen_varobjs;
+
+ /* Pretty printers command */
+ gchar *load_pretty_printer;
};
static gpointer parent_class;
@@ -303,6 +306,8 @@ debugger_initialize (Debugger *debugger)
debugger->priv->gdb_log = anjuta_log && (atoi(anjuta_log) > DEBUGGER_LOG_LEVEL);
debugger->priv->environment = NULL;
+
+ debugger->priv->load_pretty_printer = NULL;
}
static void
@@ -809,6 +814,74 @@ debugger_set_environment (Debugger *debugger, gchar **variables)
return TRUE;
}
+gboolean
+debugger_set_pretty_printers (Debugger *debugger, const GList *pretty_printers)
+{
+ GString *load = g_string_new (NULL);
+ GList *item;
+ GList *directories = NULL;
+
+ /* Unload previous pretty printers */
+ g_free (debugger->priv->load_pretty_printer);
+
+ /* Get all necessary directories */
+ for (item = g_list_first ((GList *)pretty_printers); item != NULL; item = g_list_next (item))
+ {
+ GdbPrettyPrinter *printer = (GdbPrettyPrinter *)item->data;
+ gchar *dir;
+
+ if (printer->enable)
+ {
+ dir = g_path_get_dirname (printer->path);
+ if (g_list_find_custom (directories, dir, (GCompareFunc)strcmp) == NULL)
+ {
+ directories = g_list_prepend (directories, dir);
+ }
+ else
+ {
+ g_free (dir);
+ }
+ }
+ }
+ /* Add them in the command */
+ if (directories != NULL)
+ {
+ g_string_append (load, "python\nimport sys\n");
+
+ for (item = g_list_first (directories); item != NULL; item = g_list_next (item))
+ {
+ g_string_append_printf (load, "sys.path.insert(0,'%s')\n", (gchar *)item->data);
+ g_free (item->data);
+ }
+ g_list_free (directories);
+
+ /* Import all modules and call register function*/
+ for (item = g_list_first ((GList *)pretty_printers); item != NULL; item = g_list_next (item))
+ {
+ GdbPrettyPrinter *printer = (GdbPrettyPrinter *)item->data;
+ gchar *name;
+
+ if (printer->enable && (printer->function != NULL))
+ {
+ /* Remove .py extension */
+ name = g_path_get_basename (printer->path);
+ if (g_str_has_suffix (name, ".py"))
+ {
+ name[strlen (name) - 3] = '\0';
+ }
+
+ if (printer->function != NULL)
+ g_string_append_printf (load, "import %s\n%s.%s(None)\n", name, name, printer->function);
+ }
+ }
+ g_string_append (load, "end");
+ }
+
+ debugger->priv->load_pretty_printer = g_string_free (load, FALSE);
+
+ return TRUE;
+}
+
static void
debugger_list_features_completed (Debugger *debugger,
const GDBMIValue *mi_result,
@@ -859,6 +932,12 @@ debugger_list_features_completed (Debugger *debugger,
{
debugger_queue_command (debugger, "set stop-on-solib-events 1", DEBUGGER_COMMAND_PREPEND, NULL, NULL, NULL);
}
+
+ if (debugger->priv->has_python_support && (debugger->priv->load_pretty_printer != NULL))
+ {
+ debugger_queue_command (debugger, debugger->priv->load_pretty_printer, 0, NULL, NULL, NULL);
+ debugger_queue_command (debugger, "-enable-pretty-printing", 0, NULL, NULL, NULL);
+ }
}
static gboolean
@@ -874,8 +953,10 @@ debugger_list_features (Debugger *debugger)
}
gboolean
-debugger_start (Debugger *debugger, const GList *search_dirs,
- const gchar *prog, gboolean is_libtool_prog)
+debugger_start (Debugger *debugger,
+ const GList *search_dirs,
+ const gchar *prog,
+ gboolean is_libtool_prog)
{
gchar *command_str, *dir, *tmp, *text, *msg;
gboolean ret;
@@ -943,7 +1024,7 @@ debugger_start (Debugger *debugger, const GList *search_dirs,
node = g_list_next (node);
}
- /* Now save the dir list. Order is automatically revesed */
+ /* Now save the dir list. Order is automatically reversed */
node = dir_list;
while (node)
{
@@ -952,7 +1033,7 @@ debugger_start (Debugger *debugger, const GList *search_dirs,
node = g_list_next (node);
}
g_list_free (dir_list);
-
+
if (prog && strlen(prog) > 0)
{
gchar *quoted_prog = gdb_quote (prog);
@@ -1085,7 +1166,7 @@ debugger_start (Debugger *debugger, const GList *search_dirs,
debugger_list_features (debugger);
debugger_queue_command (debugger, "handle SIGINT stop print nopass", 0, NULL, NULL, NULL);
-
+
return TRUE;
}
@@ -3798,31 +3879,35 @@ gdb_var_list_children (Debugger *debugger,
for(i = 0 ; i < numchild; ++i)
{
const GDBMIValue *const gdbmi_chl =
- gdbmi_value_list_get_nth (children, i);
+ gdbmi_value_list_get_nth (children, i);
IAnjutaDebuggerVariableObject *var;
-
+
var = g_new0 (IAnjutaDebuggerVariableObject, 1);
- literal = gdbmi_value_hash_lookup (gdbmi_chl, "name");
+ literal = gdbmi_value_hash_lookup (gdbmi_chl, "name");
if (literal)
- var->name = (gchar *)gdbmi_value_literal_get (literal);
+ var->name = (gchar *)gdbmi_value_literal_get (literal);
literal = gdbmi_value_hash_lookup (gdbmi_chl, "exp");
if (literal)
- var->expression = (gchar *)gdbmi_value_literal_get(literal);
-
+ var->expression = (gchar *)gdbmi_value_literal_get(literal);
+
literal = gdbmi_value_hash_lookup (gdbmi_chl, "type");
if (literal)
var->type = (gchar *)gdbmi_value_literal_get(literal);
- literal = gdbmi_value_hash_lookup (gdbmi_chl, "value");
+ literal = gdbmi_value_hash_lookup (gdbmi_chl, "value");
if (literal)
var->value = (gchar *)gdbmi_value_literal_get(literal);
- literal = gdbmi_value_hash_lookup (gdbmi_chl, "numchild");
+ literal = gdbmi_value_hash_lookup (gdbmi_chl, "numchild");
if (literal)
var->children = strtoul(gdbmi_value_literal_get(literal), NULL, 10);
+ literal = gdbmi_value_hash_lookup (gdbmi_chl, "has_more");
+ if (literal)
+ var->has_more = *gdbmi_value_literal_get(literal) == '1' ? TRUE : FALSE;
+
list = g_list_prepend (list, var);
}
list = g_list_reverse (list);
@@ -3866,6 +3951,16 @@ gdb_var_create (Debugger *debugger,
result = gdbmi_value_hash_lookup (mi_results, "numchild");
var.children = strtoul (gdbmi_value_literal_get(result), NULL, 10);
+
+ result = gdbmi_value_hash_lookup (mi_results, "has_more");
+ if (result != NULL)
+ {
+ var.has_more = *gdbmi_value_literal_get(result) == '1' ? TRUE : FALSE;
+ }
+ else
+ {
+ var.has_more = FALSE;
+ }
}
callback (&var, user_data, error);
@@ -4018,6 +4113,7 @@ debugger_finalize (GObject *obj)
g_string_free (debugger->priv->stdo_acc, TRUE);
g_string_free (debugger->priv->stde_line, TRUE);
g_free (debugger->priv->remote_server);
+ g_free (debugger->priv->load_pretty_printer);
g_free (debugger->priv);
G_OBJECT_CLASS (parent_class)->finalize (obj);
}
diff --git a/plugins/gdb/debugger.h b/plugins/gdb/debugger.h
index 5c92567..1640733 100644
--- a/plugins/gdb/debugger.h
+++ b/plugins/gdb/debugger.h
@@ -25,6 +25,8 @@
#include <gtk/gtk.h>
#include "gdbmi.h"
+#include "preferences.h"
+
#include <libanjuta/interfaces/ianjuta-message-view.h>
#include <libanjuta/interfaces/ianjuta-debugger.h>
@@ -84,8 +86,13 @@ GType debugger_get_type (void);
Debugger* debugger_new (GtkWindow *parent_win, GObject* instance);
void debugger_free (Debugger *debugger);
-gboolean debugger_start (Debugger *debugger, const GList *search_dirs,
- const gchar *prog, gboolean is_libtool_prog);
+gboolean debugger_set_pretty_printers (Debugger *debugger,
+ const GList *pretty_printers);
+
+gboolean debugger_start (Debugger *debugger,
+ const GList *search_dirs,
+ const gchar *prog,
+ gboolean is_libtool_prog);
gboolean debugger_stop (Debugger *debugger);
gboolean debugger_abort (Debugger *debugger);
diff --git a/plugins/gdb/plugin.c b/plugins/gdb/plugin.c
index 370d9be..20e0637 100644
--- a/plugins/gdb/plugin.c
+++ b/plugins/gdb/plugin.c
@@ -34,6 +34,7 @@
#include <sys/stat.h>
#include "debugger.h"
+#include "preferences.h"
#include <libanjuta/interfaces/ianjuta-debugger.h>
#include <libanjuta/interfaces/ianjuta-debugger-breakpoint.h>
@@ -42,6 +43,7 @@
#include <libanjuta/interfaces/ianjuta-debugger-instruction.h>
#include <libanjuta/interfaces/ianjuta-debugger-variable.h>
#include <libanjuta/interfaces/ianjuta-terminal.h>
+#include <libanjuta/interfaces/ianjuta-preferences.h>
#include <libanjuta/anjuta-plugin.h>
#include <signal.h>
@@ -64,6 +66,9 @@ struct _GdbPlugin
/* Terminal */
pid_t term_pid;
+
+ /* Pretty printer list */
+ GList *pretty_printers;
};
struct _GdbPluginClass
@@ -234,6 +239,30 @@ gdb_plugin_initialize (GdbPlugin *this)
g_signal_connect_swapped (this, "debugger-stopped", G_CALLBACK (on_debugger_stopped), this);
debugger_set_output_callback (this->debugger, this->output_callback, this->output_user_data);
if (this->view) debugger_set_log (this->debugger, this->view);
+
+ debugger_set_pretty_printers (this->debugger, this->pretty_printers);
+}
+
+/* Callback for saving session
+ *---------------------------------------------------------------------------*/
+
+static void
+on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, GdbPlugin *this)
+{
+ if (phase != ANJUTA_SESSION_PHASE_NORMAL)
+ return;
+
+ gdb_save_pretty_printers (session, this->pretty_printers);
+}
+
+static void on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, GdbPlugin *this)
+{
+ if (phase != ANJUTA_SESSION_PHASE_NORMAL)
+ return;
+
+ g_list_foreach (this->pretty_printers, (GFunc)gdb_pretty_printer_free, NULL);
+ g_list_free (this->pretty_printers);
+ this->pretty_printers = gdb_load_pretty_printers (session);
}
/* AnjutaPlugin functions
@@ -242,10 +271,18 @@ gdb_plugin_initialize (GdbPlugin *this)
static gboolean
gdb_plugin_activate_plugin (AnjutaPlugin* plugin)
{
- /* GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin); */
+ GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin);
DEBUG_PRINT ("%s", "GDB: Activating Gdb plugin...");
+ this->pretty_printers = NULL;
+ /* Connect to session signal */
+ g_signal_connect (plugin->shell, "save-session",
+ G_CALLBACK (on_session_save), this);
+ g_signal_connect (plugin->shell, "load-session",
+ G_CALLBACK (on_session_load), this);
+
+
return TRUE;
}
@@ -262,6 +299,10 @@ gdb_plugin_deactivate_plugin (AnjutaPlugin* plugin)
this->debugger = NULL;
}
+ g_list_foreach (this->pretty_printers, (GFunc)gdb_pretty_printer_free, NULL);
+ g_list_free (this->pretty_printers);
+ this->pretty_printers = NULL;
+
return TRUE;
}
@@ -1153,6 +1194,28 @@ idebugger_variable_iface_init (IAnjutaDebuggerVariableIface *iface)
iface->update = idebugger_variable_update;
}
+/* Implementation of IAnjutaPreference interface
+ *---------------------------------------------------------------------------*/
+
+static void
+ipreferences_merge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** error)
+{
+ gdb_merge_preferences (prefs, &(ANJUTA_PLUGIN_GDB (ipref)->pretty_printers));
+}
+
+static void
+ipreferences_unmerge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** error)
+{
+ gdb_unmerge_preferences (prefs);
+}
+
+static void
+ipreferences_iface_init(IAnjutaPreferencesIface* iface)
+{
+ iface->merge = ipreferences_merge;
+ iface->unmerge = ipreferences_unmerge;
+}
+
ANJUTA_PLUGIN_BEGIN (GdbPlugin, gdb_plugin);
ANJUTA_PLUGIN_ADD_INTERFACE(idebugger, IANJUTA_TYPE_DEBUGGER);
ANJUTA_PLUGIN_ADD_INTERFACE(idebugger_breakpoint, IANJUTA_TYPE_DEBUGGER_BREAKPOINT);
@@ -1160,6 +1223,7 @@ ANJUTA_PLUGIN_ADD_INTERFACE(idebugger_register, IANJUTA_TYPE_DEBUGGER_REGISTER);
ANJUTA_PLUGIN_ADD_INTERFACE(idebugger_memory, IANJUTA_TYPE_DEBUGGER_MEMORY);
ANJUTA_PLUGIN_ADD_INTERFACE(idebugger_instruction, IANJUTA_TYPE_DEBUGGER_INSTRUCTION);
ANJUTA_PLUGIN_ADD_INTERFACE(idebugger_variable, IANJUTA_TYPE_DEBUGGER_VARIABLE);
+ANJUTA_PLUGIN_ADD_INTERFACE (ipreferences, IANJUTA_TYPE_PREFERENCES);
ANJUTA_PLUGIN_END;
ANJUTA_SIMPLE_PLUGIN (GdbPlugin, gdb_plugin);
diff --git a/plugins/gdb/preferences.c b/plugins/gdb/preferences.c
new file mode 100644
index 0000000..358422a
--- /dev/null
+++ b/plugins/gdb/preferences.c
@@ -0,0 +1,467 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* preferences.c
+ *
+ * Copyright (C) 2010 Sébastien Granjoux
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "preferences.h"
+
+
+#include <libanjuta/anjuta-utils.h>
+
+
+#define BUILDER_FILE PACKAGE_DATA_DIR"/glade/anjuta-gdb.ui"
+
+#define BUILD_PREFS_DIALOG "preferences_dialog_build"
+#define GDB_PREFS_ROOT "gdb_preferences_container"
+#define GDB_PRINTER_TREEVIEW "printers_treeview"
+#define GDB_PRINTER_REMOVE_BUTTON "remove_button"
+
+
+#define ICON_FILE "anjuta-gdb.plugin.png"
+
+#define GDB_SECTION "Gdb"
+#define GDB_PRINTER_KEY "PrettyPrinter"
+
+
+/* column of the printer list view */
+enum {
+ GDB_PP_ACTIVE_COLUMN,
+ GDB_PP_FILENAME_COLUMN,
+ GDB_PP_REGISTER_COLUMN,
+ GDB_PP_N_COLUMNS
+};
+
+/* Node types
+ *---------------------------------------------------------------------------*/
+
+typedef struct
+{
+ GtkTreeView *treeview;
+ GtkListStore *model;
+ GtkWidget *remove_button;
+ GList **list;
+} PreferenceDialog;
+
+
+/* Private functions
+ *---------------------------------------------------------------------------*/
+
+static gboolean
+gdb_append_missing_register_function (GString *msg, GtkTreeModel *model, GtkTreeIter *iter)
+{
+ gboolean active;
+ gchar *path;
+ gchar *function;
+ gboolean missing;
+
+ gtk_tree_model_get (model, iter,
+ GDB_PP_ACTIVE_COLUMN, &active,
+ GDB_PP_FILENAME_COLUMN, &path,
+ GDB_PP_REGISTER_COLUMN, &function, -1);
+ if (function != NULL) function = g_strstrip (function);
+
+ missing = active && ((function == NULL) || (*function == '\0'));
+ if (missing)
+ {
+ g_string_append (msg, path);
+ g_string_append (msg, "\n");
+ gtk_list_store_set (GTK_LIST_STORE (model), iter, GDB_PP_ACTIVE_COLUMN, FALSE, -1);
+ }
+ g_free (path);
+ g_free (function);
+
+ return missing;
+}
+
+static void
+gdb_check_register_function (PreferenceDialog *dlg, GtkTreeIter *iter)
+{
+ GString *list;
+
+ list = g_string_new (NULL);
+ if (iter == NULL)
+ {
+ GtkTreeIter iter;
+ gboolean valid;
+
+ for (valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dlg->model), &iter);
+ valid; valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (dlg->model), &iter))
+ {
+ gdb_append_missing_register_function (list, GTK_TREE_MODEL (dlg->model), &iter);
+ }
+ }
+ else
+ {
+ gdb_append_missing_register_function (list, GTK_TREE_MODEL (dlg->model), iter);
+ }
+
+ if (list->len > 0)
+ {
+ gchar *msg;
+
+ msg = g_strdup_printf(_("The following pretty printers, without a register functions, have been disabled:\n %s"), list->str);
+ anjuta_util_dialog_warning (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (dlg->treeview))), msg);
+ g_free (msg);
+ g_string_free (list, TRUE);
+ }
+}
+
+static gchar *
+gdb_find_register_function (const gchar *path)
+{
+ GFile *file;
+ gchar *function = NULL;
+ gchar *content = NULL;
+
+ file = g_file_new_for_path (path);
+
+ if (g_file_load_contents (file, NULL, &content, NULL, NULL, NULL))
+ {
+ GRegex *regex;
+ GMatchInfo *match;
+
+ regex = g_regex_new ("^def\\s+(register\w*)\\s*\\(\\w+\\)\\s*:", G_REGEX_CASELESS | G_REGEX_MULTILINE, 0, NULL);
+ if (g_regex_match (regex, content, 0, &match))
+ {
+ function = g_match_info_fetch (match, 1);
+ g_match_info_free (match);
+ }
+ g_regex_unref (regex);
+ g_free (content);
+ }
+
+ g_object_unref (file);
+
+ return function;
+}
+
+static gboolean
+on_add_printer_in_list (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
+{
+ GList** list = (GList **)user_data;
+ gchar *filepath;
+ gchar *function;
+ gboolean active;
+ GdbPrettyPrinter *printer;
+
+ gtk_tree_model_get (model, iter, GDB_PP_ACTIVE_COLUMN, &active,
+ GDB_PP_FILENAME_COLUMN, &filepath,
+ GDB_PP_REGISTER_COLUMN, &function,
+ -1);
+ printer = g_slice_new0 (GdbPrettyPrinter);
+ printer->enable = active;
+ printer->path = filepath;
+ printer->function = function;
+ *list = g_list_prepend (*list, printer);
+
+ return FALSE;
+}
+
+/* Call backs
+ *---------------------------------------------------------------------------*/
+
+ /* Gtk builder callbacks */
+void gdb_on_printer_add (GtkButton *button, gpointer user_data);
+void gdb_on_printer_remove (GtkButton *button, gpointer user_data);
+void gdb_on_destroy_preferences (GtkObject *object, gpointer user_data);
+
+void
+gdb_on_destroy_preferences (GtkObject *object, gpointer user_data)
+{
+ PreferenceDialog *dlg = (PreferenceDialog *)user_data;
+ GList *new_list;
+
+ /* Free previous list and replace with new one */
+ g_list_foreach (*(dlg->list), (GFunc)gdb_pretty_printer_free, NULL);
+ g_list_free (*(dlg->list));
+ *(dlg->list) = NULL;
+
+ /* Replace with new one */
+ new_list = NULL;
+ gtk_tree_model_foreach (GTK_TREE_MODEL (dlg->model), on_add_printer_in_list, &new_list);
+ new_list = g_list_reverse (new_list);
+ *(dlg->list) = new_list;
+
+ g_free (dlg);
+}
+
+void
+gdb_on_printer_add (GtkButton *button, gpointer user_data)
+{
+ PreferenceDialog *dlg = (PreferenceDialog *)user_data;
+ GtkWidget *chooser;
+ GtkFileFilter *filter;
+
+ chooser = gtk_file_chooser_dialog_new (_("Select a pretty printer file"),
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_mime_type (filter, "text/x-python");
+ gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE);
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser),filter);
+
+ if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
+ {
+ GSList *filenames;
+ GSList *item;
+
+ filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (chooser));
+
+ for (item = filenames; item != NULL; item = g_slist_next (item))
+ {
+ GtkTreeIter iter;
+ gchar *path = (gchar *)item->data;
+ gchar *function;
+
+ function = gdb_find_register_function (path);
+
+ gtk_list_store_append (dlg->model, &iter);
+ gtk_list_store_set (dlg->model, &iter, GDB_PP_ACTIVE_COLUMN, TRUE,
+ GDB_PP_FILENAME_COLUMN, path,
+ GDB_PP_REGISTER_COLUMN, function,
+ -1);
+ g_free (path);
+ g_free (function);
+
+ gdb_check_register_function (dlg, &iter);
+ }
+ g_slist_free (filenames);
+ }
+ gtk_widget_destroy (chooser);
+}
+
+void
+gdb_on_printer_remove (GtkButton *button, gpointer user_data)
+{
+ PreferenceDialog *dlg = (PreferenceDialog *)user_data;
+ GtkTreeIter iter;
+ GtkTreeSelection* sel;
+
+ sel = gtk_tree_view_get_selection (dlg->treeview);
+ if (gtk_tree_selection_get_selected (sel, NULL, &iter))
+ {
+ gtk_list_store_remove (dlg->model, &iter);
+ }
+}
+
+static void
+gdb_on_printer_activate (GtkCellRendererToggle *cell_renderer, const gchar *path, gpointer user_data)
+{
+ PreferenceDialog *dlg = (PreferenceDialog *)user_data;
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dlg->model), &iter, path))
+ {
+ gboolean enable;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (dlg->model), &iter, GDB_PP_ACTIVE_COLUMN, &enable, -1);
+ enable = !enable;
+ gtk_list_store_set (dlg->model, &iter, GDB_PP_ACTIVE_COLUMN, enable, -1);
+
+ if (enable) gdb_check_register_function (dlg, &iter);
+ }
+}
+
+static void
+gdb_on_printer_function_changed (GtkCellRendererText *renderer,
+ gchar *path,
+ gchar *new_text,
+ gpointer user_data)
+{
+ PreferenceDialog *dlg = (PreferenceDialog *)user_data;
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dlg->model), &iter, path))
+ {
+ gchar *function = g_strstrip (new_text);
+ gtk_list_store_set (dlg->model, &iter, GDB_PP_REGISTER_COLUMN, function, -1);
+ }
+}
+
+static void
+gdb_on_printer_selection_changed (GtkTreeSelection *selection, gpointer user_data)
+{
+ PreferenceDialog *dlg = (PreferenceDialog *)user_data;
+ GtkTreeIter iter;
+ GtkTreeSelection* sel;
+ gboolean selected;
+
+ sel = gtk_tree_view_get_selection (dlg->treeview);
+ selected = gtk_tree_selection_get_selected (sel, NULL, &iter);
+ gtk_widget_set_sensitive(dlg->remove_button, selected);
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+void
+gdb_merge_preferences (AnjutaPreferences* prefs, GList **list)
+{
+ GtkBuilder *bxml;
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ GtkTreeSelection *selection;
+ PreferenceDialog *dlg;
+ GList *item;
+
+ g_return_if_fail (list != NULL);
+
+ /* Create the preferences page */
+ bxml = anjuta_util_builder_new (BUILDER_FILE, NULL);
+ if (!bxml) return;
+
+ dlg = g_new0 (PreferenceDialog, 1);
+
+ /* Get widgets */
+ anjuta_util_builder_get_objects (bxml,
+ GDB_PRINTER_TREEVIEW, &dlg->treeview,
+ GDB_PRINTER_REMOVE_BUTTON, &dlg->remove_button,
+ NULL);
+
+ /* Create tree view */
+ dlg->model = gtk_list_store_new (GDB_PP_N_COLUMNS,
+ G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING);
+ gtk_tree_view_set_model (dlg->treeview, GTK_TREE_MODEL (dlg->model));
+ g_object_unref (dlg->model);
+
+ renderer = gtk_cell_renderer_toggle_new ();
+ g_signal_connect (G_OBJECT (renderer), "toggled", G_CALLBACK (gdb_on_printer_activate), dlg);
+ column = gtk_tree_view_column_new_with_attributes (_("Activate"), renderer,
+ "active", GDB_PP_ACTIVE_COLUMN, NULL);
+ gtk_tree_view_append_column (dlg->treeview, column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("File"), renderer,
+ "text", GDB_PP_FILENAME_COLUMN, NULL);
+ gtk_tree_view_append_column (dlg->treeview, column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set(renderer, "editable", TRUE, NULL);
+ g_signal_connect(renderer, "edited", G_CALLBACK (gdb_on_printer_function_changed), dlg);
+ column = gtk_tree_view_column_new_with_attributes (_("Register Function"), renderer,
+ "text", GDB_PP_REGISTER_COLUMN, NULL);
+ gtk_tree_view_append_column (dlg->treeview, column);
+
+ /* Connect all signals */
+ gtk_builder_connect_signals (bxml, dlg);
+ selection = gtk_tree_view_get_selection (dlg->treeview);
+ g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (gdb_on_printer_selection_changed), dlg);
+
+
+ /* Fill tree view */
+ dlg->list = list;
+ for (item = g_list_first (*list); item != NULL; item = g_list_next (item))
+ {
+ GdbPrettyPrinter *printer = (GdbPrettyPrinter *)item->data;
+ GtkTreeIter iter;
+
+ gtk_list_store_append (dlg->model, &iter);
+ gtk_list_store_set (dlg->model, &iter, GDB_PP_ACTIVE_COLUMN, printer->enable ? TRUE : FALSE,
+ GDB_PP_FILENAME_COLUMN, printer->path,
+ GDB_PP_REGISTER_COLUMN, printer->function,
+ -1);
+ }
+
+ anjuta_preferences_add_from_builder (prefs, bxml, GDB_PREFS_ROOT, _("Gdb Debugger"), ICON_FILE);
+
+ g_object_unref (bxml);
+}
+
+void
+gdb_unmerge_preferences (AnjutaPreferences* prefs)
+{
+ anjuta_preferences_remove_page(prefs, _("Gdb Debugger"));
+}
+
+GList *
+gdb_load_pretty_printers (AnjutaSession *session)
+{
+ GList *session_list;
+ GList *list = NULL;
+ GList *item;
+
+ session_list = anjuta_session_get_string_list (session, GDB_SECTION, GDB_PRINTER_KEY);
+ for (item = g_list_first (session_list); item != NULL; item = g_list_next (item))
+ {
+ GdbPrettyPrinter *printer;
+ gchar *name = (gchar *)item->data;
+ gchar *ptr;
+
+ printer = g_slice_new0 (GdbPrettyPrinter);
+ ptr = strchr (name, ':');
+ if (ptr != NULL)
+ {
+ if (*name == 'E') printer->enable = TRUE;
+ name = ptr + 1;
+ }
+ ptr = strrchr (name, ':');
+ if (ptr != NULL)
+ {
+ *ptr = '\0';
+ printer->function = g_strdup (ptr + 1);
+ }
+ printer->path = g_strdup (name);
+
+ list = g_list_prepend (list, printer);
+ }
+
+ g_list_foreach (session_list, (GFunc)g_free, NULL);
+ g_list_free (session_list);
+
+ return list;
+}
+
+gboolean
+gdb_save_pretty_printers (AnjutaSession *session, GList *list)
+{
+ GList *session_list = NULL;
+ GList *item;
+
+ for (item = g_list_first (list); item != NULL; item = g_list_next (item))
+ {
+ GdbPrettyPrinter *printer = (GdbPrettyPrinter *)item->data;
+ gchar *name;
+
+ name = g_strconcat (printer->enable ? "E:" : "D:", printer->path, ":", printer->function == NULL ? "" : printer->function, NULL);
+
+ session_list = g_list_prepend (session_list, name);
+ }
+ session_list = g_list_reverse (session_list);
+ anjuta_session_set_string_list (session, GDB_SECTION, GDB_PRINTER_KEY, session_list);
+ g_list_foreach (session_list, (GFunc)g_free, NULL);
+ g_list_free (session_list);
+
+ return FALSE;
+}
+
+void
+gdb_pretty_printer_free (GdbPrettyPrinter *printer)
+{
+ g_free (printer->path);
+ g_free (printer->function);
+ g_slice_free (GdbPrettyPrinter, printer);
+}
diff --git a/plugins/gdb/preferences.h b/plugins/gdb/preferences.h
new file mode 100644
index 0000000..a832deb
--- /dev/null
+++ b/plugins/gdb/preferences.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* preferences.h
+ *
+ * Copyright (C) 2010 Sébastien Granjoux
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PREFERENCES_H_
+#define _PREFERENCES_H_
+
+#include <libanjuta/anjuta-preferences.h>
+#include <libanjuta/anjuta-session.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ gboolean enable;
+ gchar *path;
+ gchar *function;
+} GdbPrettyPrinter;
+
+GList *gdb_load_pretty_printers (AnjutaSession *session);
+gboolean gdb_save_pretty_printers (AnjutaSession *session, GList *list);
+
+void gdb_pretty_printer_free (GdbPrettyPrinter *printer);
+
+void gdb_merge_preferences (AnjutaPreferences* prefs, GList **list);
+void gdb_unmerge_preferences (AnjutaPreferences* prefs);
+
+G_END_DECLS
+
+#endif /* _PREFERENCES_H_ */
diff --git a/plugins/js-debugger/debugger-js.c b/plugins/js-debugger/debugger-js.c
index 887cd11..79297d5 100644
--- a/plugins/js-debugger/debugger-js.c
+++ b/plugins/js-debugger/debugger-js.c
@@ -179,6 +179,7 @@ variable_create (DebuggerJs* object, struct Task *task)
var->type = g_strdup ("object");
var->value = g_strdup ("object");
var->children = 0;
+ var->has_more = FALSE;
var->changed = TRUE;
var->exited = FALSE;
var->deleted = FALSE;
@@ -337,6 +338,7 @@ varibale_list_children (DebuggerJs* object, struct Task *task)
var->type = g_strdup (str + k + 1);
var->value = g_strdup ("");
var->children = 1;
+ var->has_more = FALSE;
k = i;
}
else if (j == 1)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]