This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GDB C plugin system, and STL container viewer as an example


Hello,

	some days ago, I send here a (crap and buggy) patch that allows GDB to
display STL containers. I know that this patch was too intrusive and
dependent of the STL version.

	Today, I wrote another patch that allows me to load plugin into GDB
that are called in particular situations, like displaying the content of
a variable of a particular type, or creating varobjects in MI
interpreter. It is used to format any kind of datas as I want it to be
displayed.

	I submit a new version of my STL container viewer, but this time as a
plugin. It handles STL container access as it was a classic C array, and
answers queries like 'sizeof'... It also support MI interpreter, so that
GDB could be used with frontend, still displaying data correctly. I
tried it with Eclipse/CDT, KDevelop, KDBG, Nemiver and Insight/GDB. All
works well !

	In order to compile the plugin, you'll have to modify the Makefile and
set the correct value for GDB_SOURCES variable.

	After that, launch a GDB session, and execute the command

(gdb) loadplugin /path/to/plugin/stl.so

	A typical session could look like that

(gdb) b 122
Breakpoint 1 at 0x8049602: file main.cpp, line 122.
(gdb) r
Starting program: /home/bsr/sources/stl/a.out 

Breakpoint 1, main () at main.cpp:122
122	    return 0;
(gdb) whatis m
type = std::map<const char*,int,std::less<const
char*>,std::allocator<std::pair<const char* const, int> > >
(gdb) p m
$1 = {
  {
    0x8051ec6 "un",
    1
  }, 
  {
    0x8051ec9 "deux",
    2
  }, 
  {
    0x8051ece "trois",
    3
  }
}

(gdb) p m[2]
$2 = {
  first = 0x8051ece "trois", 
  second = 3
}
(gdb) p sizeof(m)
$3 = 12
(gdb) stlsizeof 1
sizeof operator on STL containers will print the number of elements.
(gdb) p sizeof(m)
$4 = 3
(gdb) ...



	You could simply put the command into your ".gdbinit" to allow
frontends to use STL data formatter.

PS: I know that there is a Python scripting patch in progress. Mine is
only a small patch to allows people to use this feature today, waiting a
cleaner engine !
diff -BNurw gdb-6.8/gdb/cli/cli-cmds.c gdb-6.8-patched/gdb/cli/cli-cmds.c
--- gdb-6.8/gdb/cli/cli-cmds.c	2008-01-01 23:53:14.000000000 +0100
+++ gdb-6.8-patched/gdb/cli/cli-cmds.c	2008-05-23 09:16:11.000000000 +0200
@@ -45,6 +45,8 @@
 #include "cli/cli-setshow.h"
 #include "cli/cli-cmds.h"
 
+#include "plugin.h"
+
 #ifdef TUI
 #include "tui/tui.h"		/* For tui_active et.al.   */
 #endif
@@ -1159,6 +1161,16 @@
 		    value);
 }
 
+static void
+loadplugin_command (char *args, int from_tty)
+{
+    printf_unfiltered(_("Loading plugin \"%s\n"), args);
+    if (!load_plugin(args))
+    {
+        error (_("cannot load plugin."));
+    }
+}
+
 
 void
 init_cli_cmds (void)
@@ -1423,4 +1435,10 @@
 			   NULL,
 			   NULL,
 			   &setlist, &showlist);
+
+  source_help_text = xstrprintf (_("\
+Load a GDB plugin."));
+  c = add_cmd ("loadplugin", class_support, loadplugin_command,
+	       source_help_text, &cmdlist);
+  set_cmd_completer (c, filename_completer);
 }
diff -BNurw gdb-6.8/gdb/cp-valprint.c gdb-6.8-patched/gdb/cp-valprint.c
--- gdb-6.8/gdb/cp-valprint.c	2008-01-01 23:53:09.000000000 +0100
+++ gdb-6.8-patched/gdb/cp-valprint.c	2008-05-23 09:16:11.000000000 +0200
@@ -36,6 +36,7 @@
 #include "valprint.h"
 #include "cp-support.h"
 #include "language.h"
+#include "plugin.h"
 
 /* Controls printing of vtbl's */
 int vtblprint;
@@ -161,6 +162,11 @@
 
   CHECK_TYPEDEF (type);
 
+  if (plugins_try_print(type, address, stream, format, recurse, pretty))
+  {
+      return;
+  }
+
   fprintf_filtered (stream, "{");
   len = TYPE_NFIELDS (type);
   n_baseclasses = TYPE_N_BASECLASSES (type);
diff -BNurw gdb-6.8/gdb/Makefile.in gdb-6.8-patched/gdb/Makefile.in
--- gdb-6.8/gdb/Makefile.in	2008-03-17 13:15:08.000000000 +0100
+++ gdb-6.8-patched/gdb/Makefile.in	2008-05-23 10:26:48.000000000 +0200
@@ -622,7 +622,7 @@
 	sentinel-frame.c \
 	serial.c ser-base.c ser-unix.c \
 	solib.c solib-null.c source.c \
-	stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \
+	stabsread.c stack.c std-regs.c plugin.c symfile.c symfile-mem.c symmisc.c \
 	symtab.c \
 	target.c target-descriptions.c target-memory.c \
 	thread.c top.c tracepoint.c \
@@ -885,6 +885,7 @@
 srec_h = srec.h
 stabsread_h = stabsread.h
 stack_h = stack.h
+plugin_h = plugin.h
 symfile_h = symfile.h $(symtab_h)
 symtab_h = symtab.h
 target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h) $(vec_h)
@@ -1072,7 +1073,7 @@
 	tramp-frame.o \
 	solib.o solib-null.o \
 	prologue-value.o memory-map.o xml-support.o \
-	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
+	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o plugin.o
 
 TSOBS = inflow.o
 
@@ -2012,7 +2013,9 @@
 cp-valprint.o: cp-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \
 	$(gdbtypes_h) $(expression_h) $(value_h) $(command_h) $(gdbcmd_h) \
 	$(demangle_h) $(annotate_h) $(gdb_string_h) $(c_lang_h) $(target_h) \
-	$(cp_abi_h) $(valprint_h) $(cp_support_h) $(language_h)
+	$(cp_abi_h) $(valprint_h) $(cp_support_h) $(language_h) $(plugin_h)
+plugin.o: $(defs_h) $(gdbtypes_h) $(block_h) $(gdbcore_h) \
+	$(value_h) $(expression_h) $(c_lang_h) $(varobj_h)
 cris-tdep.o: cris-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \
 	$(frame_base_h) $(trad_frame_h) $(dwarf2_frame_h) $(symtab_h) \
 	$(inferior_h) $(gdbtypes_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) \
@@ -2078,7 +2081,7 @@
 	$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
 	$(f_lang_h) $(cp_abi_h) $(infcall_h) $(objc_lang_h) $(block_h) \
 	$(parser_defs_h) $(cp_support_h) $(gdb_assert_h) $(exceptions_h) \
-	$(uiout_h) $(regcache_h)
+	$(uiout_h) $(regcache_h) $(plugin_h)
 event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
 	$(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
 event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
@@ -2921,7 +2924,7 @@
 	$(regcache_h) $(dis_asm_h) $(osabi_h)
 valarith.o: valarith.c $(defs_h) $(value_h) $(symtab_h) $(gdbtypes_h) \
 	$(expression_h) $(target_h) $(language_h) $(gdb_string_h) \
-	$(doublest_h) $(dfp_h) $(infcall_h)
+	$(doublest_h) $(dfp_h) $(infcall_h) $(plugin_h)
 valops.o: valops.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(value_h) $(frame_h) \
 	$(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \
 	$(gdbcmd_h) $(regcache_h) $(cp_abi_h) $(block_h) $(infcall_h) \
@@ -2937,7 +2940,7 @@
 	$(gdb_assert_h) $(regcache_h) $(block_h) $(dfp_h)
 varobj.o: varobj.c $(defs_h) $(exceptions_h) $(value_h) $(expression_h) \
 	$(frame_h) $(language_h) $(wrapper_h) $(gdbcmd_h) $(block_h) \
-	$(gdb_assert_h) $(gdb_string_h) $(varobj_h) $(vec_h)
+	$(gdb_assert_h) $(gdb_string_h) $(varobj_h) $(vec_h) $(plugin_h)
 vaxbsd-nat.o: vaxbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) $(target_h) \
 	$(vax_tdep_h) $(inf_ptrace_h) $(bsd_kvm_h)
 vax-nat.o: vax-nat.c $(defs_h) $(inferior_h) $(gdb_assert_h) $(vax_tdep_h) \
diff -BNurw gdb-6.8/gdb/plugin.c gdb-6.8-patched/gdb/plugin.c
--- gdb-6.8/gdb/plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.8-patched/gdb/plugin.c	2008-05-23 10:22:20.000000000 +0200
@@ -0,0 +1,422 @@
+#include "defs.h"
+#include "c-lang.h"
+#include "plugin.h"
+#include "gdbtypes.h"
+#include "block.h"
+#include "gdbcore.h"
+#include "value.h"
+#include "varobj.h"
+#include "expression.h"
+#include "command.h"
+#include "completer.h"
+
+#include <dlfcn.h>
+#include <string.h>
+
+typedef int            (*init_plugin_fct)(struct plugin_functions);
+typedef void           (*uninit_plugin_fct)();
+typedef int            (*type_handled_fct)(const char * type_name, int type_name_len);
+typedef int            (*get_num_children_fct)(struct varobj * varobj);
+typedef int            (*print_fct)(const char * type_name, int type_name_len, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty);
+typedef int            (*operator_handled_fct)(const char *type_name, int type_name_len, enum exp_opcode op);
+typedef struct value * (*unary_operation_fct)(const char *type_name, int type_name_len, CORE_ADDR address, enum exp_opcode op);
+typedef struct value * (*binary_operation_fct)(const char *type_name, int type_name_len, CORE_ADDR address, struct value * other, enum exp_opcode op);
+typedef struct type *  (*get_child_item_type_at_fct)(struct varobj *, int index);
+typedef struct value * (*get_child_item_value_at_fct)(struct varobj *, int index);
+
+struct loaded_plugin
+{
+    struct loaded_plugin *      next;
+    int                         id;
+
+    void *                      module;
+
+    init_plugin_fct             init;
+    uninit_plugin_fct           uninit;
+    type_handled_fct            type_handled;
+    get_num_children_fct        get_num_children;
+    print_fct                   print;
+
+    operator_handled_fct        operator_handled;
+    unary_operation_fct         unary_operation;
+    binary_operation_fct        binary_operation;
+
+    get_child_item_type_at_fct  get_child_item_type_at;
+    get_child_item_value_at_fct get_child_item_value_at;
+};
+
+static int                      plugin_id = 1;
+static struct loaded_plugin *   plugins   = NULL;
+
+struct block * get_current_block()
+{
+    struct frame_info * current_frame = get_current_frame();
+    CORE_ADDR pc = get_frame_address_in_block(current_frame);
+    return block_for_pc(pc);
+}
+
+struct type * get_type(const char * name, struct block * block)
+{
+    struct type *type;
+    struct type *ptr_type;
+    char *rname = (char *)malloc(strlen(name) + 1);
+    char *old   = rname;
+    int  nbPtrs = 0;
+
+    strcpy(rname, name);
+    if (!strncmp(rname, "const ", 6)) rname += 6;
+    while (rname[strlen(rname) - 1] == '*')
+    {
+      nbPtrs++;
+      rname[strlen(rname) - 1] = 0;
+    }
+
+    while (rname[strlen(rname) - 1] == ' ')
+    {
+      rname[strlen(rname) - 1] = 0;
+    }
+
+    type = lookup_typename(rname, block, 1);
+    while (nbPtrs--)
+    {
+      ptr_type = NULL;
+      make_pointer_type(type, &ptr_type);
+      type = ptr_type;
+    }
+
+    free(old);
+    return type;
+}
+
+const char * get_type_name(struct type * type)
+{
+    if (type == NULL) return NULL;
+    return type->main_type->name;
+}
+
+int get_type_length(struct type * type)
+{
+    return TYPE_LENGTH(type);
+}
+
+void print(struct type * type, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty)
+{
+    gdb_byte * b = (gdb_byte *)malloc(TYPE_LENGTH(type));
+    read_memory(address, b, TYPE_LENGTH(type));
+    c_val_print(type, b, 0, address, stream, format, 0, recurse, pretty);
+    free(b);
+}
+
+CORE_ADDR get_value_address(struct value * value)
+{
+    return VALUE_ADDRESS(value) + value_offset(value);
+}
+
+void add_command(char *name, char *help, void (*handler)(char *, int), enum completer_type comp)
+{
+    extern struct cmd_list_element *cmdlist;
+    struct cmd_list_element *c;
+    c = add_cmd (name, class_support, handler, help, &cmdlist);
+    switch(comp)
+    {
+        case COMPLETE_FILENAME:
+            set_cmd_completer (c, filename_completer);
+            break;
+        case COMPLETE_LOCATION:
+            set_cmd_completer (c, location_completer);
+            break;
+        default:
+            break;
+    }
+}
+
+static struct plugin_functions all_functions =
+    {
+        add_command,
+        print_spaces_filtered,
+        printf_unfiltered,
+        printf_filtered,
+        fprintf_unfiltered,
+        fprintf_filtered,
+        get_current_block,
+        get_type,
+        get_type_name,
+        get_type_length,
+        read_memory_integer,
+        read_memory,
+        print,
+        value_at,
+        value_as_long,
+        value_from_longest,
+        get_value_address,
+        varobj_get_gdb_type,
+        varobj_get_gdb_value,
+        varobj_get_block
+    };
+
+int load_plugin(const char * filename)
+{
+    struct loaded_plugin * plugin;
+
+    void * module = dlopen(filename, RTLD_NOW | RTLD_DEEPBIND);
+    if (module == 0)
+    {
+        fprintf(stderr, "Cannot load plugin %s : cannot open file\n", filename);
+        fprintf(stderr, "%s\n", dlerror());
+        return 0;
+    }
+
+    plugin                          = (struct loaded_plugin *)malloc(sizeof(struct loaded_plugin));
+    plugin->module                  = module;
+    plugin->init                    = (init_plugin_fct)            dlsym(module, "init_plugin");
+    plugin->uninit                  = (uninit_plugin_fct)          dlsym(module, "uninit_plugin");
+    plugin->type_handled            = (type_handled_fct)           dlsym(module, "type_handled");
+    plugin->get_num_children        = (get_num_children_fct)       dlsym(module, "get_num_children");
+    plugin->print                   = (print_fct)                  dlsym(module, "print");
+    plugin->operator_handled        = (operator_handled_fct)       dlsym(module, "operator_handled");
+    plugin->unary_operation         = (unary_operation_fct)        dlsym(module, "unary_operation");
+    plugin->binary_operation        = (binary_operation_fct)       dlsym(module, "binary_operation");
+    plugin->get_child_item_type_at  = (get_child_item_type_at_fct) dlsym(module, "get_child_item_type_at");
+    plugin->get_child_item_value_at = (get_child_item_value_at_fct)dlsym(module, "get_child_item_value_at");
+
+    if (plugin->init == 0
+     || plugin->uninit == 0
+     || plugin->type_handled == 0
+     || plugin->get_num_children == 0
+     || plugin->print == 0
+     || plugin->operator_handled == 0
+     || plugin->unary_operation == 0
+     || plugin->binary_operation == 0
+     || plugin->get_child_item_type_at == 0
+     || plugin->get_child_item_value_at == 0)
+    {
+        dlclose(module);
+        free(plugin);
+        fprintf(stderr, "Cannot load plugin %s : missing symbol\n", filename);
+        return 0;
+    }
+
+    if (!plugin->init(all_functions))
+    {
+        dlclose(plugin->module);
+        free(plugin);
+        fprintf(stderr, "Cannot load plugin %s : init_plugin return false\n", filename);
+        return 0;
+    }
+
+    plugin->next = plugins;
+    plugin->id   = plugin_id++;
+    plugins = plugin;
+    return plugin->id;
+}
+
+void unload_plugin(int id)
+{
+    struct loaded_plugin * current  = plugins;
+    struct loaded_plugin * previous = NULL;
+    while (current)
+    {
+        if (current->id == id)
+        {
+            dlclose(current->module);
+            if (previous)
+            {
+                previous->next = current->next;
+            }
+            else
+            {
+                plugins = current->next;
+            }
+            free(current);
+            return;
+        }
+        previous = current;
+        current  = current->next;
+    }
+}
+
+int plugins_type_handled(struct type * type)
+{
+    const char * type_name;
+    int type_name_len;
+    struct loaded_plugin * plugin = plugins;
+
+    if (!type || !type->main_type || !type->main_type->name) return 0;
+    type_name     = type->main_type->name;
+    type_name_len = strlen(type_name);
+
+    while (plugin)
+    {
+        if (plugin->type_handled(type_name, type_name_len))
+        {
+            return 1;
+        }
+        plugin = plugin->next;
+    }
+
+    return 0;
+}
+
+int plugins_try_print(struct type * type, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty)
+{
+    const char * type_name;
+    int type_name_len;
+    struct loaded_plugin * plugin = plugins;
+
+    if (!type || !type->main_type || !type->main_type->name) return 0;
+    type_name     = type->main_type->name;
+    type_name_len = strlen(type_name);
+
+    while (plugin)
+    {
+        if (plugin->type_handled(type_name, type_name_len))
+        {
+            return plugin->print(type_name, type_name_len, address, stream, format, recurse, pretty);
+        }
+        plugin = plugin->next;
+    }
+
+    return 0;
+}
+
+int plugins_get_num_children(struct varobj * varobj)
+{
+    const char * type_name;
+    int type_name_len;
+    struct loaded_plugin * plugin = plugins;
+    struct type * type = varobj_get_gdb_type(varobj);
+
+    if (!type || !type->main_type || !type->main_type->name) return 0;
+    type_name     = type->main_type->name;
+    type_name_len = strlen(type_name);
+
+    while (plugin)
+    {
+        if (plugin->type_handled(type_name, type_name_len))
+        {
+            return plugin->get_num_children(varobj);
+        }
+        plugin = plugin->next;
+    }
+
+    return 0;
+}
+
+int plugins_operator_handled(struct type * type, enum exp_opcode op)
+{
+    const char * type_name;
+    int type_name_len;
+    struct loaded_plugin * plugin = plugins;
+
+    if (!type || !type->main_type || !type->main_type->name) return 0;
+    type_name     = type->main_type->name;
+    type_name_len = strlen(type_name);
+
+    while (plugin)
+    {
+        if (plugin->operator_handled(type_name, type_name_len, op))
+        {
+            return 1;
+        }
+        plugin = plugin->next;
+    }
+
+    return 0;
+}
+
+struct value * plugins_try_unary(struct value * arg, enum exp_opcode op)
+{
+    const char * type_name;
+    int type_name_len;
+    struct loaded_plugin * plugin = plugins;
+
+    struct type * type = check_typedef(value_type(arg));
+    CORE_ADDR addr_arg = VALUE_ADDRESS(arg) + value_offset(arg);
+
+    if (!type || !type->main_type || !type->main_type->name) return 0;
+    type_name     = type->main_type->name;
+    type_name_len = strlen(type_name);
+
+    while (plugin)
+    {
+        if (plugin->operator_handled(type_name, type_name_len, op))
+        {
+            return plugin->unary_operation(type_name, type_name_len, addr_arg, op);
+        }
+        plugin = plugin->next;
+    }
+
+    return 0;
+}
+
+struct value * plugins_try_binary(struct value * arg1, struct value * arg2, enum exp_opcode op)
+{
+    const char * type_name;
+    int type_name_len;
+    struct loaded_plugin * plugin = plugins;
+
+    struct type * type = check_typedef(value_type(arg1));
+    CORE_ADDR addr_arg1 = VALUE_ADDRESS(arg1) + value_offset(arg1);
+
+    if (!type || !type->main_type || !type->main_type->name) return 0;
+    type_name     = type->main_type->name;
+    type_name_len = strlen(type_name);
+
+    while (plugin)
+    {
+        if (plugin->operator_handled(type_name, type_name_len, op))
+        {
+            return plugin->binary_operation(type_name, type_name_len, addr_arg1, arg2, op);
+        }
+        plugin = plugin->next;
+    }
+
+    return 0;
+}
+
+struct type * plugins_get_child_item_type_at(struct varobj * varobj, int index)
+{
+    const char * type_name;
+    int type_name_len;
+    struct loaded_plugin * plugin = plugins;
+    struct type * type = varobj_get_gdb_type(varobj);
+
+    if (!type || !type->main_type || !type->main_type->name) return 0;
+    type_name     = type->main_type->name;
+    type_name_len = strlen(type_name);
+
+    while (plugin)
+    {
+        if (plugin->type_handled(type_name, type_name_len))
+        {
+            return plugin->get_child_item_type_at(varobj, index);
+        }
+        plugin = plugin->next;
+    }
+
+    return 0;
+}
+
+struct value * plugins_get_child_item_value_at(struct varobj * varobj, int index)
+{
+    const char * type_name;
+    int type_name_len;
+    struct loaded_plugin * plugin = plugins;
+    struct type * type = varobj_get_gdb_type(varobj);
+
+    if (!type || !type->main_type || !type->main_type->name) return 0;
+    type_name     = type->main_type->name;
+    type_name_len = strlen(type_name);
+
+    while (plugin)
+    {
+        if (plugin->type_handled(type_name, type_name_len))
+        {
+            return plugin->get_child_item_value_at(varobj, index);
+        }
+        plugin = plugin->next;
+    }
+
+    return 0;
+}
+
diff -BNurw gdb-6.8/gdb/plugin.h gdb-6.8-patched/gdb/plugin.h
--- gdb-6.8/gdb/plugin.h	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.8-patched/gdb/plugin.h	2008-05-23 10:21:59.000000000 +0200
@@ -0,0 +1,87 @@
+#ifndef PLUGIN_H__
+#define PLUGIN_H__
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "expression.h"
+
+struct type;
+struct block;
+struct ui_file;
+struct value;
+struct varobj;
+
+/*
+ * A plugin should implement those functions:
+ *
+ * int            init_plugin(struct plugin_functions);
+ * void           uninit_plugin();
+ *
+ * int            type_handled(const char * type_name, int type_name_len);
+ * int            get_num_children(struct varobj *varobj);
+ * int            print(const char * type_name, int type_name_len, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty);
+ *
+ * int            operator_handled(const char * type_name, int type_name_len, enum exp_opcode op);
+ * struct value * unary_operation(const char * type_name, int type_name_len, CORE_ADDR address, enum exp_opcode op);
+ * struct value * binary_operation(const char * type_name, int type_name_len, CORE_ADDR address, struct value * other, enum exp_opcode op);
+ *
+ * struct type *  get_child_item_type_at(struct varobj *, int index);
+ * struct value * get_child_item_value_at(struct varobj *, int index);
+ */
+
+enum completer_type
+{
+    COMPLETE_FILENAME,
+    COMPLETE_LOCATION,
+    COMPLETE_NONE
+};
+
+/*
+ * Available function for plugins
+ */
+struct plugin_functions
+{
+    void            (*add_cli_command)(char * name, char * help, void (*handler)(char *,int), enum completer_type comp);
+
+    void            (*print_spaces_filtered)(int count, struct ui_file * stream);
+    void            (*printf_unfiltered)(const char * format, ...);
+    void            (*printf_filtered)(const char * format, ...);
+    void            (*fprintf_unfiltered)(struct ui_file * stream, const char * format, ...);
+    void            (*fprintf_filtered)(struct ui_file * stream, const char * format, ...);
+    struct block *  (*get_current_block)();
+
+    struct type *   (*get_type)(const char * name, struct block * block);
+    const char *    (*get_type_name)(struct type * type);
+    int             (*get_type_length)(struct type * type);
+
+    LONGEST         (*read_memory_integer)(CORE_ADDR address, int size);
+    void            (*read_memory)(CORE_ADDR address, gdb_byte * destination, int size);
+
+    void            (*print)(struct type * type, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty);
+
+    struct value *  (*value_at)(struct type * type, CORE_ADDR address);
+    LONGEST         (*value_as_long)(struct value *);
+    struct value *  (*value_from_longest)(struct type * type, LONGEST num);
+    CORE_ADDR       (*get_value_address)(struct value *);
+
+    struct type *   (*get_varobj_type)(struct varobj *);
+    struct value *  (*get_varobj_value)(struct varobj *);
+    struct block *  (*get_varobj_block)(struct varobj *);
+};
+
+int             load_plugin(const char * filename);
+void            unload_plugin(int id);
+
+int             plugins_type_handled(struct type * type);
+int             plugins_try_print(struct type * type, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty);
+int             plugins_get_num_children(struct varobj * varobj);
+
+int             plugins_operator_handled(struct type * type, enum exp_opcode op);
+struct value *  plugins_try_unary(struct value * arg, enum exp_opcode op);
+struct value *  plugins_try_binary(struct value * arg1, struct value * arg2, enum exp_opcode op);
+
+struct type *   plugins_get_child_item_type_at(struct varobj * varobj, int index);
+struct value *  plugins_get_child_item_value_at(struct varobj * varobj, int index);
+
+#endif
+
diff -BNurw gdb-6.8/gdb/valarith.c gdb-6.8-patched/gdb/valarith.c
--- gdb-6.8/gdb/valarith.c	2008-02-04 01:23:04.000000000 +0100
+++ gdb-6.8-patched/gdb/valarith.c	2008-05-23 10:21:35.000000000 +0200
@@ -31,6 +31,9 @@
 #include "dfp.h"
 #include <math.h>
 #include "infcall.h"
+#include "block.h"
+#include "gdbcore.h"
+#include "plugin.h"
 
 /* Define whether or not the C operator '/' truncates towards zero for
    differently signed operands (truncation direction is undefined in C). */
@@ -309,6 +313,9 @@
   if (TYPE_CODE (type2) == TYPE_CODE_REF)
     type2 = check_typedef (TYPE_TARGET_TYPE (type2));
 
+  if (plugins_operator_handled(type1, op))
+    return 1;
+
   return (TYPE_CODE (type1) == TYPE_CODE_STRUCT
 	  || TYPE_CODE (type2) == TYPE_CODE_STRUCT);
 }
@@ -326,6 +334,10 @@
   if (op == UNOP_ADDR)
     return 0;
   type1 = check_typedef (value_type (arg1));
+
+  if (plugins_operator_handled(type1, op))
+    return 1;
+
   for (;;)
     {
       if (TYPE_CODE (type1) == TYPE_CODE_STRUCT)
@@ -354,12 +366,19 @@
   char *ptr;
   char tstr[13];
   int static_memfuncp;
+  struct value * plugin_res;
 
   arg1 = coerce_ref (arg1);
   arg2 = coerce_ref (arg2);
   arg1 = coerce_enum (arg1);
   arg2 = coerce_enum (arg2);
 
+  plugin_res = plugins_try_binary(arg1, arg2, op);
+  if (plugin_res)
+  {
+      return plugin_res;
+  }
+
   /* now we know that what we have to do is construct our
      arg vector and find the right function to call it with.  */
 
@@ -516,10 +535,17 @@
   char *ptr, *mangle_ptr;
   char tstr[13], mangle_tstr[13];
   int static_memfuncp, nargs;
+  struct value * plugin_res;
 
   arg1 = coerce_ref (arg1);
   arg1 = coerce_enum (arg1);
 
+  plugin_res = plugins_try_unary(arg1, op);
+  if (plugin_res)
+  {
+      return plugin_res;
+  }
+
   /* now we know that what we have to do is construct our
      arg vector and find the right function to call it with.  */
 
diff -BNurw gdb-6.8/gdb/varobj.c gdb-6.8-patched/gdb/varobj.c
--- gdb-6.8/gdb/varobj.c	2008-02-04 08:49:04.000000000 +0100
+++ gdb-6.8-patched/gdb/varobj.c	2008-05-23 09:16:11.000000000 +0200
@@ -24,6 +24,7 @@
 #include "language.h"
 #include "wrapper.h"
 #include "gdbcmd.h"
+#include "gdbcore.h"
 #include "block.h"
 
 #include "gdb_assert.h"
@@ -32,6 +33,8 @@
 #include "varobj.h"
 #include "vec.h"
 
+#include "plugin.h"
+
 /* Non-zero if we want to see trace of varobj level stuff.  */
 
 int varobjdebug = 0;
@@ -1151,6 +1154,17 @@
       if (type_changed)
 	VEC_safe_push (varobj_p, result, *varp);
       
+      if (plugins_type_handled(varobj_get_gdb_type(*varp)))
+      {
+          int new_childs = plugins_get_num_children(*varp);
+          if (new_childs != (*varp)->num_children)
+          {
+              (*varp)->num_children = new_childs;
+              (*varp)->children = varobj_list_children (*varp);
+              VEC_safe_push (varobj_p, result, *varp);
+          }
+      }
+
         if (install_new_value ((*varp), new, type_changed))
 	  {
 	    /* If type_changed is 1, install_new_value will never return
@@ -2222,6 +2236,7 @@
     {
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
+        if (!plugins_type_handled(varobj_get_gdb_type(var)))
       return xstrdup ("{...}");
       /* break; */
 
@@ -2267,6 +2282,11 @@
   struct type *type;
   int children, dont_know;
 
+  if (plugins_type_handled(varobj_get_gdb_type(var)))
+  {
+      return plugins_get_num_children(var);
+  }
+
   dont_know = 1;
   children = 0;
 
@@ -2410,7 +2430,19 @@
       || TYPE_CODE (type) == TYPE_CODE_UNION)
     {
       char *join = was_ptr ? "->" : ".";
-      if (CPLUS_FAKE_CHILD (parent))
+
+      if (plugins_type_handled(varobj_get_gdb_type(parent)))
+      {
+        if (cname)
+          *cname = xstrprintf("%d", index);
+        if (ctype)
+          *ctype = plugins_get_child_item_type_at(parent, index);
+        if (cvalue)
+          *cvalue = plugins_get_child_item_value_at(parent, index);
+        if (cfull_expression)
+          *cfull_expression = xstrprintf("(%s)[%d]", parent_expression, index);
+      }
+      else if (CPLUS_FAKE_CHILD (parent))
 	{
 	  /* The fields of the class type are ordered as they
 	     appear in the class.  We are given an index for a
@@ -2725,3 +2757,15 @@
   }
   return;
 }
+
+struct block *
+varobj_get_block (struct varobj *var)
+{
+  return var->root->valid_block;
+}
+
+struct value *
+varobj_get_gdb_value (struct varobj *var)
+{
+  return var->value;
+}
diff -BNurw gdb-6.8/gdb/varobj.h gdb-6.8-patched/gdb/varobj.h
--- gdb-6.8/gdb/varobj.h	2008-01-30 08:17:31.000000000 +0100
+++ gdb-6.8-patched/gdb/varobj.h	2008-05-23 09:16:11.000000000 +0200
@@ -61,6 +61,7 @@
 
 /* Struct thar describes a variable object instance */
 struct varobj;
+struct block;
 
 typedef struct varobj *varobj_p;
 DEF_VEC_P (varobj_p);
@@ -122,4 +123,8 @@
 
 extern int varobj_editable_p (struct varobj *var);
 
+extern struct block * varobj_get_block (struct varobj *var);
+
+extern struct value * varobj_get_gdb_value (struct varobj *var);
+
 #endif /* VAROBJ_H */
diff -BNurw gdb-6.8/gdb/eval.c gdb-6.8-patched/gdb/eval.c
--- gdb-6.8/gdb/eval.c	2008-02-04 01:23:04.000000000 +0100
+++ gdb-6.8-patched/gdb/eval.c	2008-05-23 10:47:30.000000000 +0200
@@ -41,6 +41,8 @@
 
 #include "gdb_assert.h"
 
+#include "plugin.h"
+
 /* This is defined in valops.c */
 extern int overload_resolution;
 
@@ -2305,6 +2307,11 @@
     case OP_VAR_VALUE:
       (*pos) += 4;
       type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
+      if (plugins_operator_handled(type, UNOP_SIZEOF))
+      {
+        val = value_of_variable(exp->elts[pc + 2].symbol, exp->elts[pc + 1].block);
+        return plugins_try_unary(val, UNOP_SIZEOF);
+      }
       return
 	value_from_longest (builtin_type_int, (LONGEST) TYPE_LENGTH (type));
 
#include "stdio.h"
#include "plugin.h"
#include <string.h>

static int stllimit = 0;
static int stlsizeof = 0;
static int stlprintcompatible = 1;

#define TREE_PARENT(A) ((CORE_ADDR)read_memory_integer ((A) + 1 * ptr_size, ptr_size))
#define TREE_LEFT(A)   ((CORE_ADDR)read_memory_integer ((A) + 2 * ptr_size, ptr_size))
#define TREE_RIGHT(A)  ((CORE_ADDR)read_memory_integer ((A) + 3 * ptr_size, ptr_size))

static struct plugin_functions ext_fcts;

void handle_stllimit(char * args, int from_tty)
{
    if (args && strlen(args))
    {
        stllimit = atoi(args);
    }

    if (stllimit == 0)
    {
        ext_fcts.printf_unfiltered("STL limit set to UNLIMITED\n");
    }
    else
    {
        ext_fcts.printf_unfiltered("STL limit set to %d\n", stllimit);
    }
}

void handle_stlstyle(char * args, int from_tty)
{
    if (args && strlen(args))
    {
        stlprintcompatible = atoi(args);
    }

    ext_fcts.printf_unfiltered("STL container style %d\n", stlprintcompatible);
}

void handle_stlsizeof(char *args, int from_tty)
{
    if (args && strlen(args))
    {
        stlsizeof = atoi(args);
    }

    if (stlsizeof)
    {
        ext_fcts.printf_unfiltered("sizeof operator on STL containers will print the number of elements.\n");
    }
    else
    {
        ext_fcts.printf_unfiltered("sizeof operator on STL containers will print the total size in bytes.\n");
    }
}

int init_plugin(struct plugin_functions fcts)
{
    ext_fcts = fcts;
    ext_fcts.add_cli_command("stllimit", "Set the maximum number of element display for STL containers", handle_stllimit, COMPLETE_NONE);
    ext_fcts.add_cli_command("stlstyle", "Set the display style of STL containers", handle_stlstyle, COMPLETE_NONE);
    ext_fcts.add_cli_command("stlsizeof", "Set if sizeof(X) on an STL container should return the number of elements (argument != 0) or the total number of bytes (argument = 0).\n", handle_stlsizeof, COMPLETE_NONE);
    ext_fcts.printf_unfiltered("GDB STL plugin loaded\n");
    return 1;
}

void uninit_plugin()
{
}

/*
 * helpers
 */

int get_stl_inner_type(const char * type_name, char *inner_type_name)
{
    int level = 1;
    char *pname = (char *)type_name;

    while (*pname && *pname != '<') pname++;
    if (*pname == 0)
    {
        // This is not a template !
        *inner_type_name = 0;
        return 0;
    }

    pname++;

    while (!(level == 1 && *pname == ','))
    {
        if (*pname == '<') level++;
        else if (*pname == '>') level--;
        if (!(level == 1 && *pname == ',')) *inner_type_name++ = *pname++;
    }
    *inner_type_name = 0;

    return 1;
}

int get_stl_inner_type_pair(const char * type_name, char *inner_type_key, char *inner_type_value, char *pair_name)
{
    int level = 1;
    char *pname = (char *)type_name;

    while (*pname && *pname != '<') pname++;
    if (*pname == 0)
    {
        // This is not a template !
        *inner_type_key   = 0;
        *inner_type_value = 0;
        return 0;
    }

    pname++;

    while (!(level == 1 && *pname == ','))
    {
        if (*pname == '<') level++;
        else if (*pname == '>') level--;
        if (!(level == 1 && *pname == ',')) *inner_type_key++ = *pname++;
    }
    *inner_type_key = 0;

    if (*pname == ',')
    {
        pname++;
        while (!(level == 1 && *pname == ','))
        {
            if (*pname == '<') level++;
            else if (*pname == '>') level--;
            if (!(level == 1 && *pname == ',')) *inner_type_value++ = *pname++;
        }
        *inner_type_value = 0;
    }

    if (pair_name == NULL) return 1;

    level = 0;
    pname++;
    while (!(level == 0 && *pname == ','))
    {
        if (*pname == '<') level++;
        else if (*pname == '>') level--;
        pname++;
    }
    pname++;

    if (strncmp(pname, "std::allocator<std::pair<", 25))
    {
        puts(pname);
        return 0;
    }
    pname += 15;
    level = 0;
    while (!(level == 0 && *pname == '>'))
    {
        if (*pname == '<') level++;
        else if (*pname == '>') level--;
        *pair_name++ = *pname++;
    }
    *pair_name++ = 0;

    return 1;
}

struct type * get_stl_container_inner_type(struct varobj * var)
{
    char * inner_name;
    struct type * type = ext_fcts.get_varobj_type(var);
    struct type * inner;
    struct block * block = ext_fcts.get_varobj_block(var);
    const char * type_name = ext_fcts.get_type_name(type);
    inner_name = (char *)malloc(strlen(type_name) + 1);
    if (!get_stl_inner_type(type_name, inner_name))
        return NULL;
    inner = ext_fcts.get_type(inner_name, block);
    free(inner_name);
    return inner;
}

/*
 * printers
 */

void print_stl_vector(const char * type_name, int type_name_len,
        CORE_ADDR address,
        struct ui_file *stream, int format, int recurse,
        enum val_prettyprint pretty)
{
    char                *inner_name;
    struct type         *void_type;
    struct type         *inner_type;
    struct block        *block;
    int                 ptr_size;
    unsigned int        idx;
    CORE_ADDR           begin;
    CORE_ADDR           end;

    inner_name = (char *)malloc(type_name_len + 1);

    if (get_stl_inner_type (type_name, inner_name))
    {
        if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "vector<%s>", inner_name);
        ext_fcts.fprintf_filtered (stream, "{");
        if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
        block         = ext_fcts.get_current_block();
        inner_type    = ext_fcts.get_type(inner_name, block);
        void_type     = ext_fcts.get_type("void *", block);
        ptr_size      = ext_fcts.get_type_length(void_type);

        if (inner_type == NULL)
        {
            if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
            ext_fcts.fprintf_filtered (stream, "  // no information for type %s\n", inner_name);
        }
        else
        {
            idx   = 0;
            begin = (CORE_ADDR)ext_fcts.read_memory_integer(address,            ptr_size);
            end   = (CORE_ADDR)ext_fcts.read_memory_integer(address + ptr_size, ptr_size);
            while (begin != end)
            {
                if (stllimit && idx >= stllimit)
                {
                    fprintf_filtered (stream, "...");
                    break;
                }
                if (pretty) ext_fcts.print_spaces_filtered(2 + 2 * recurse, stream);
                if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
                idx++;
                ext_fcts.print(inner_type, begin, stream, format, recurse + 1, pretty);
                begin += ext_fcts.get_type_length(inner_type);
                if (begin != end) ext_fcts.fprintf_filtered(stream, ", ");
                if (pretty)
                {
                    ext_fcts.fprintf_filtered(stream, "\n");
                }
            }
        }
        if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
        ext_fcts.fprintf_filtered (stream, "}");
        if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
    }

    free(inner_name);
}

void print_stl_list(const char * type_name, int type_name_len,
        CORE_ADDR address,
        struct ui_file *stream, int format, int recurse,
        enum val_prettyprint pretty)
{
    char                *inner_name;
    CORE_ADDR           node;
    CORE_ADDR           data_ptr;
    struct type         *inner_type;
    struct type         *void_type;
    struct block        *block;
    int                 ptr_size;
    unsigned int        idx;

    inner_name = (char *)malloc(strlen(type_name) + 1);

    if (get_stl_inner_type(type_name, inner_name))
    {
        if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "list<%s>", inner_name);
        ext_fcts.fprintf_filtered (stream, "{");
        if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
        block         = ext_fcts.get_current_block();
        inner_type    = ext_fcts.get_type(inner_name, block);
        void_type     = ext_fcts.get_type("void *", block);
        ptr_size      = ext_fcts.get_type_length(void_type);

        if (inner_type == NULL)
        {
            if (pretty) ext_fcts.print_spaces_filtered(2 + 2 * recurse, stream);
            ext_fcts.fprintf_filtered(stream, "  // no information for type %s\n", inner_name);
        }
        else
        {
            idx  = 0;
            node = (CORE_ADDR)read_memory_integer (address, ptr_size);
            while (node != address)
            {
                if (stllimit && idx >= stllimit)
                {
                    ext_fcts.fprintf_filtered (stream, "...");
                    break;
                }
                data_ptr = (CORE_ADDR)(node + ptr_size * 2);
                if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
                if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
                idx++;
                ext_fcts.print(inner_type, data_ptr, stream, format, recurse + 1, pretty);
                node = (CORE_ADDR)ext_fcts.read_memory_integer (node, ptr_size);
                if (node != address) ext_fcts.fprintf_filtered(stream, ", ");
                if (pretty)
                {
                    ext_fcts.fprintf_filtered(stream, "\n");
                }
            }
        }
        if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
        ext_fcts.fprintf_filtered (stream, "}");
        if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
    }

    free(inner_name);
}

void print_stl_set(const char * type_name, int type_name_len,
        CORE_ADDR address,
        struct ui_file *stream, int format, int recurse,
        enum val_prettyprint pretty)
{
    char                *inner_name;
    CORE_ADDR           node;
    CORE_ADDR           left;
    CORE_ADDR           tmp_node;
    CORE_ADDR           data_ptr;
    struct type         *inner_type;
    struct type         *void_type;
    struct block        *block;
    int                 ptr_size;
    unsigned int        idx;
    int                 count;

    inner_name = (char *)malloc(strlen(type_name) + 1);

    if (get_stl_inner_type(type_name, inner_name))
    {
        if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "set<%s>", inner_name);
        ext_fcts.fprintf_filtered (stream, "{");
        if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
        block         = ext_fcts.get_current_block();
        inner_type    = ext_fcts.get_type(inner_name, block);
        void_type     = ext_fcts.get_type("void *", block);
        ptr_size      = ext_fcts.get_type_length(void_type);

        if (inner_type == NULL)
        {
            if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
            ext_fcts.fprintf_filtered (stream, "  // no information for type %s\n", inner_name);
        }
        else
        {
            node  = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size);
            count = (int)read_memory_integer(address + 5 * ptr_size, ptr_size);
            for (idx=0; idx<count; idx++)
            {
                if (stllimit && idx >= stllimit)
                {
                    ext_fcts.fprintf_filtered (stream, "...");
                    break;
                }
                data_ptr = (CORE_ADDR)(node + ptr_size * 4);
                if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
                if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
                ext_fcts.print(inner_type, data_ptr, stream, format, recurse + 1, pretty);

                if (TREE_RIGHT(node) != 0)
                {
                    node = TREE_RIGHT(node);
                    while ((left = TREE_LEFT(node)))
                    {
                        node = left;
                    }
                }
                else
                {
                    tmp_node = TREE_PARENT(node);
                    while (node == TREE_RIGHT(node))
                    {
                        node     = tmp_node;
                        tmp_node = TREE_PARENT(node);
                    }
                    if (TREE_RIGHT(node) != tmp_node)
                    {
                        node = tmp_node;
                    }
                }

                if (idx != count - 1) ext_fcts.fprintf_filtered(stream, ", ");
                if (pretty)
                {
                    ext_fcts.fprintf_filtered(stream, "\n");
                }
            }
        }
        if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
        ext_fcts.fprintf_filtered (stream, "}");
        if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
    }

    free(inner_name);
}

void print_stl_map(const char * type_name, int type_name_len,
        CORE_ADDR address,
        struct ui_file *stream, int format, int recurse,
        enum val_prettyprint pretty)
{
    char                *inner_key;
    char                *inner_value;
    CORE_ADDR           node;
    CORE_ADDR           left;
    CORE_ADDR           tmp_node;
    CORE_ADDR           data_ptr;
    struct type         *inner_type_key;
    struct type         *inner_type_value;
    struct type         *void_type;
    struct block        *block;
    int                 ptr_size;
    unsigned int        idx;
    int                 count;

    inner_key   = (char *)malloc(strlen(type_name) + 1);
    inner_value = (char *)malloc(strlen(type_name) + 1);

    if (get_stl_inner_type_pair(type_name, inner_key, inner_value, NULL))
    {
        if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "map<%s, %s>", inner_key, inner_value);
        ext_fcts.fprintf_filtered (stream, "{");
        if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
        block            = ext_fcts.get_current_block();
        inner_type_key   = ext_fcts.get_type(inner_key,   block);
        inner_type_value = ext_fcts.get_type(inner_value, block);
        void_type        = ext_fcts.get_type("void *", block);
        ptr_size         = ext_fcts.get_type_length(void_type);

        if (inner_type_key == NULL || inner_type_value == NULL)
        {
            if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
            ext_fcts.fprintf_filtered (stream, "  // no information for type std::pair<%s, %s>\n", inner_key, inner_value);
        }
        else
        {
            node    = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size);
            count   = (int)read_memory_integer(address + 5 * ptr_size, ptr_size);
            for (idx=0; idx<count; idx++)
            {
                if (stllimit && idx >= stllimit)
                {
                    ext_fcts.fprintf_filtered (stream, "...");
                    break;
                }
                data_ptr = (CORE_ADDR)(node + ptr_size * 4);

                if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
                if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
                ext_fcts.fprintf_filtered (stream, "{");
                if (pretty) ext_fcts.fprintf_filtered(stream, "\n");

                if (pretty) ext_fcts.print_spaces_filtered (4 + 2 * recurse, stream);
                if (!stlprintcompatible)
                {
                    ext_fcts.fprintf_filtered(stream, "key ");
                    if (pretty) ext_fcts.fprintf_filtered(stream, "  ");
                    ext_fcts.fprintf_filtered(stream, "= ");
                }
                ext_fcts.print(inner_type_key, data_ptr, stream, format, recurse + 3, pretty);
                if (pretty) ext_fcts.fprintf_filtered(stream, ",\n"); else ext_fcts.fprintf_filtered(stream, ", ");
                if (pretty) ext_fcts.print_spaces_filtered (4 + 2 * recurse, stream);
                if (!stlprintcompatible)
                {
                    ext_fcts.fprintf_filtered(stream, "value = ");
                }
                ext_fcts.print(inner_type_value, data_ptr + ptr_size, stream, format, recurse + 3, pretty);
                if (pretty) ext_fcts.fprintf_filtered(stream, "\n");

                if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
                ext_fcts.fprintf_filtered(stream, "}");

                if (TREE_RIGHT(node) != 0)
                {
                    node = TREE_RIGHT(node);
                    while ((left = TREE_LEFT(node)))
                    {
                        node = left;
                    }
                }
                else
                {
                    tmp_node = TREE_PARENT(node);
                    while (node == TREE_RIGHT(node))
                    {
                        node     = tmp_node;
                        tmp_node = TREE_PARENT(node);
                    }
                    if (TREE_RIGHT(node) != tmp_node)
                    {
                        node = tmp_node;
                    }
                }

                if (idx != count - 1) ext_fcts.fprintf_filtered(stream, ", ");
                if (pretty)
                {
                    ext_fcts.fprintf_filtered(stream, "\n");
                }
            }
        }
        if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
        ext_fcts.fprintf_filtered (stream, "}");
        if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
    }

    free(inner_key);
    free(inner_value);
}

void print_stl_deque(const char * type_name, int type_name_len,
        CORE_ADDR address,
        struct ui_file *stream, int format, int recurse,
        enum val_prettyprint pretty)
{
    char                *inner_name;
    CORE_ADDR           node;
    CORE_ADDR           data_ptr;
    CORE_ADDR           map;
    CORE_ADDR           cur_node;
    int                 iter_beg_cur;
    int                 iter_beg_first;
    int                 iter_beg_last;
    int                 iter_beg_node;
    int                 iter_end_cur;
    int                 iter_end_first;
    int                 iter_end_last;
    int                 iter_end_node;
    int                 elems_per_nodes;
    int                 size;
    struct type         *inner_type;
    struct type         *void_type;
    struct block        *block;
    int                 ptr_size;
    unsigned int        idx;
    int                 nodes_rem;

    inner_name = (char *)malloc(strlen(type_name) + 1);

    if (get_stl_inner_type(type_name, inner_name))
    {
        if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "deque<%s>", inner_name);
        ext_fcts.fprintf_filtered (stream, "{");
        if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
        block         = ext_fcts.get_current_block();
        inner_type    = ext_fcts.get_type(inner_name, block);
        void_type     = ext_fcts.get_type("void *", block);
        ptr_size      = ext_fcts.get_type_length(void_type);

        if (inner_type == NULL)
        {
            if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
            ext_fcts.fprintf_filtered (stream, "  // no information for type %s\n", inner_name);
        }
        else
        {
            map             = read_memory_integer (address, ptr_size);
            iter_beg_cur    = read_memory_integer (address + ptr_size * 2, ptr_size);
            iter_beg_first  = read_memory_integer (address + ptr_size * 3, ptr_size);
            iter_beg_last   = read_memory_integer (address + ptr_size * 4, ptr_size);
            iter_beg_node   = read_memory_integer (address + ptr_size * 5, ptr_size);
            iter_end_cur    = read_memory_integer (address + ptr_size * 6, ptr_size);
            iter_end_first  = read_memory_integer (address + ptr_size * 7, ptr_size);
            iter_end_last   = read_memory_integer (address + ptr_size * 8, ptr_size);
            iter_end_node   = read_memory_integer (address + ptr_size * 9, ptr_size);
            elems_per_nodes = TYPE_LENGTH(inner_type) < 512 ? 512 / TYPE_LENGTH(inner_type) : 1;
            size            = ( elems_per_nodes * (iter_end_node - iter_beg_node - ptr_size) + (iter_end_cur - iter_end_first) + (iter_beg_last - iter_beg_cur) ) / ptr_size;
            idx             = 0;
            nodes_rem       = elems_per_nodes;
            data_ptr        = iter_beg_cur;
            cur_node        = iter_beg_node;
            while (idx < size)
            {
                if (stllimit && idx >= stllimit)
                {
                    ext_fcts.fprintf_filtered (stream, "...");
                    break;
                }
                if (nodes_rem)
                {
                    if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
                    if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
                    ext_fcts.print(inner_type, data_ptr, stream, format, recurse + 1, pretty);
                    if (idx != size - 1) ext_fcts.fprintf_filtered(stream, ", ");
                    if (pretty) ext_fcts.fprintf_filtered(stream, "\n");
                    data_ptr += TYPE_LENGTH(inner_type);
                    nodes_rem--;
                    idx++;
                }
                else
                {
                    nodes_rem = elems_per_nodes;
                    cur_node += ptr_size;
                    data_ptr  = read_memory_integer (cur_node, ptr_size);
                }
            }
            if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
            ext_fcts.fprintf_filtered (stream, "}");
            if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
        }
    }

    free(inner_name);
}

void print_stl_string(const char * type_name, int type_name_len,
        CORE_ADDR address,
        struct ui_file *stream, int format, int recurse,
        enum val_prettyprint pretty)
{
    struct type         *char_type;
    struct block        *block;
    int                 ptr_size;
    CORE_ADDR           string_ptr;

    block            = ext_fcts.get_current_block();
    char_type        = ext_fcts.get_type("char *", block);
    ptr_size         = ext_fcts.get_type_length(char_type);

    string_ptr = ext_fcts.read_memory_integer(address, ptr_size);
    val_print_string(string_ptr, -1, 1, stream);
}

/*
 * getters
 */

struct value * get_stl_list_item_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
    char                *inner_name;
    CORE_ADDR           node;
    CORE_ADDR           data_ptr;
    struct type         *inner_type;
    struct type         *void_type;
    struct block        *block;
    int                 ptr_size;
    unsigned int        idx;

    if (index < 0) return NULL;

    inner_name = (char *)malloc(strlen(type_name) + 1);

    if (get_stl_inner_type(type_name, inner_name))
    {
        block         = ext_fcts.get_current_block();
        inner_type    = ext_fcts.get_type(inner_name, block);
        void_type     = ext_fcts.get_type("void *", block);
        ptr_size      = ext_fcts.get_type_length(void_type);

        if (inner_type == NULL)
        {
            free(inner_name);
            return NULL;
        }
        else
        {
            idx  = 0;
            node = (CORE_ADDR)ext_fcts.read_memory_integer(address, ptr_size);
            while (node != address && idx <= index)
            {
                if (idx == index)
                {
                    free(inner_name);
                    return ext_fcts.value_at(inner_type, (CORE_ADDR)(node + ptr_size * 2));
                }
                node = (CORE_ADDR)ext_fcts.read_memory_integer (node, ptr_size);
                idx++;
            }
        }
    }

    free(inner_name);
    return NULL;
}

struct value * get_stl_vector_item_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
    char                *inner_name;
    struct type         *void_type;
    struct type         *inner_type;
    struct block        *block;
    int                 ptr_size;
    CORE_ADDR           begin;
    CORE_ADDR           end;

    if (index < 0) return NULL;

    inner_name = (char *)malloc(strlen(type_name) + 1);

    if (get_stl_inner_type(type_name, inner_name))
    {
        block         = ext_fcts.get_current_block();
        inner_type    = ext_fcts.get_type(inner_name, block);
        void_type     = ext_fcts.get_type("void *", block);
        ptr_size      = ext_fcts.get_type_length(void_type);

        if (inner_type == NULL)
        {
            free(inner_name);
            return NULL;
        }
        else
        {
            begin  = (CORE_ADDR)read_memory_integer (address,            ptr_size);
            end    = (CORE_ADDR)read_memory_integer (address + ptr_size, ptr_size);
            begin += index * TYPE_LENGTH (inner_type);
            if (begin >= end)
            {
                free(inner_name);
                return NULL;
            }
            return ext_fcts.value_at(inner_type, begin);
        }
    }

    free(inner_name);
    return NULL;
}

struct value * get_stl_set_item_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
    char                *inner_name;
    CORE_ADDR           node;
    CORE_ADDR           left;
    CORE_ADDR           tmp_node;
    CORE_ADDR           data_ptr;
    struct type         *inner_type;
    struct type         *void_type;
    struct block        *block;
    int                 ptr_size;
    unsigned int        idx;
    int                 count;

    if (index < 0) return NULL;

    inner_name = (char *)malloc(strlen(type_name) + 1);

    if (get_stl_inner_type(type_name, inner_name))
    {
        block         = ext_fcts.get_current_block();
        inner_type    = ext_fcts.get_type(inner_name, block);
        void_type     = ext_fcts.get_type("void *", block);
        ptr_size      = ext_fcts.get_type_length(void_type);

        if (inner_type == NULL)
        {
            free(inner_name);
            return NULL;
        }
        else
        {
            node  = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size);
            count = (int)read_memory_integer(address + 5 * ptr_size, ptr_size);
            if (index >= count)
            {
                free(inner_name);
                return NULL;
            }
            for (idx=0; idx<index; idx++)
            {
                if (TREE_RIGHT(node) != 0)
                {
                    node = TREE_RIGHT(node);
                    while ((left = TREE_LEFT(node)))
                    {
                        node = left;
                    }
                }
                else
                {
                    tmp_node = TREE_PARENT(node);
                    while (node == TREE_RIGHT(node))
                    {
                        node     = tmp_node;
                        tmp_node = TREE_PARENT(node);
                    }
                    if (TREE_RIGHT(node) != tmp_node)
                    {
                        node = tmp_node;
                    }
                }
            }
            free(inner_name);
            return ext_fcts.value_at(inner_type, (CORE_ADDR)(node + ptr_size * 4));
        }
    }

    free(inner_name);
    return NULL;
}

struct value * get_stl_map_pair_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
    char                *inner_key;
    char                *inner_value;
    char                *pair_name;
    CORE_ADDR           node;
    CORE_ADDR           left;
    CORE_ADDR           tmp_node;
    CORE_ADDR           data_ptr;
    struct type         *void_type;
    struct type         *pair_type;
    struct block        *block;
    int                 ptr_size;
    unsigned int        idx;
    int                 count;

    if (index < 0) return NULL;

    inner_key   = (char *)malloc(strlen(type_name) + 1);
    inner_value = (char *)malloc(strlen(type_name) + 1);
    pair_name   = (char *)malloc(strlen(type_name) + 1);

    if (get_stl_inner_type_pair(type_name, inner_key, inner_value, pair_name))
    {
        block         = ext_fcts.get_current_block();
        pair_type     = ext_fcts.get_type(pair_name, block);
        void_type     = ext_fcts.get_type("void *", block);
        ptr_size      = ext_fcts.get_type_length(void_type);

        if (pair_type == NULL)
        {
            free (inner_key);
            free (inner_value);
            free (pair_name);
            return NULL;
        }
        else
        {
            node    = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size);
            count   = (int)read_memory_integer(address + 5 * ptr_size, ptr_size);
            if (index >= count)
            {
                free (inner_key);
                free (inner_value);
                free (pair_name);
                return NULL;
            }
            for (idx=0; idx<index; idx++)
            {
                if (TREE_RIGHT(node) != 0)
                {
                    node = TREE_RIGHT(node);
                    while ((left = TREE_LEFT(node)))
                    {
                        node = left;
                    }
                }
                else
                {
                    tmp_node = TREE_PARENT(node);
                    while (node == TREE_RIGHT(node))
                    {
                        node     = tmp_node;
                        tmp_node = TREE_PARENT(node);
                    }
                    if (TREE_RIGHT(node) != tmp_node)
                    {
                        node = tmp_node;
                    }
                }
            }

            free (inner_key);
            free (inner_value);
            free (pair_name);
            return ext_fcts.value_at(pair_type, (CORE_ADDR)(node + ptr_size * 4));
        }
    }

    free(inner_key);
    free(inner_value);
    free (pair_name);
    return NULL;
}

struct value * get_stl_deque_item_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
    char                *inner_name;
    CORE_ADDR           node;
    CORE_ADDR           data_ptr;
    CORE_ADDR           map;
    CORE_ADDR           cur_node;
    int                 iter_beg_cur;
    int                 iter_beg_first;
    int                 iter_beg_last;
    int                 iter_beg_node;
    int                 iter_end_cur;
    int                 iter_end_first;
    int                 iter_end_last;
    int                 iter_end_node;
    int                 elems_per_nodes;
    int                 size;
    struct type         *inner_type;
    struct type         *void_type;
    struct block        *block;
    int                 ptr_size;
    unsigned int        idx;
    int                 nodes_rem;

    if (index < 0) return NULL;

    inner_name = (char *)malloc(strlen(type_name) + 1);

    if (get_stl_inner_type(type_name, inner_name))
    {
        block         = ext_fcts.get_current_block();
        inner_type    = ext_fcts.get_type(inner_name, block);
        void_type     = ext_fcts.get_type("void *", block);
        ptr_size      = ext_fcts.get_type_length(void_type);

        if (inner_type == NULL)
        {
            free(inner_name);
            return NULL;
        }
        else
        {
            map             = read_memory_integer (address, ptr_size);
            iter_beg_cur    = read_memory_integer (address + ptr_size * 2, ptr_size);
            iter_beg_first  = read_memory_integer (address + ptr_size * 3, ptr_size);
            iter_beg_last   = read_memory_integer (address + ptr_size * 4, ptr_size);
            iter_beg_node   = read_memory_integer (address + ptr_size * 5, ptr_size);
            iter_end_cur    = read_memory_integer (address + ptr_size * 6, ptr_size);
            iter_end_first  = read_memory_integer (address + ptr_size * 7, ptr_size);
            iter_end_last   = read_memory_integer (address + ptr_size * 8, ptr_size);
            iter_end_node   = read_memory_integer (address + ptr_size * 9, ptr_size);
            elems_per_nodes = TYPE_LENGTH(inner_type) < 512 ? 512 / TYPE_LENGTH(inner_type) : 1;
            size            = ( elems_per_nodes * (iter_end_node - iter_beg_node - ptr_size) + (iter_end_cur - iter_end_first) + (iter_beg_last - iter_beg_cur) ) / ptr_size;
            idx             = 0;
            nodes_rem       = elems_per_nodes;
            data_ptr        = iter_beg_cur;
            cur_node        = iter_beg_node;
            if (index >= size)
            {
                free(inner_name);
                return NULL;
            }
            while (idx < size)
            {
                if (index == idx)
                {
                    free(inner_name);
                    return ext_fcts.value_at(inner_type, data_ptr);
                }
                if (nodes_rem)
                {
                    nodes_rem--;
                    data_ptr += TYPE_LENGTH(inner_type);
                    idx++;
                }
                else
                {
                    nodes_rem = elems_per_nodes;
                    cur_node += ptr_size;
                    data_ptr  = read_memory_integer (cur_node, ptr_size);
                }
            }
        }
    }

    free(inner_name);
    return NULL;
}


int get_stl_list_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
    int children = 0;
    char * inner_name = (char *)malloc(strlen(type_name) + 1);
    if (get_stl_inner_type(type_name, inner_name))
    {
        struct type *       void_type     = ext_fcts.get_type("void *", block);
        struct type *       inner_type    = ext_fcts.get_type(inner_name, block);
        int                 ptr_size      = ext_fcts.get_type_length(void_type);
        CORE_ADDR           node          = (CORE_ADDR)read_memory_integer (varadr, ptr_size);
        while (node != varadr)
        {
            node = (CORE_ADDR)ext_fcts.read_memory_integer (node, ptr_size);
            children++;
        }
    }
    free (inner_name);
    return children;
}

int get_stl_list_size_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (!type) return 0;
    return get_stl_list_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}

int get_stl_vector_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
    int children = 0;
    char * inner_name = (char *)malloc(strlen(type_name) + 1);
    if (get_stl_inner_type(type_name, inner_name))
    {
        struct type *       void_type     = ext_fcts.get_type("void *", block);
        struct type *       inner_type    = ext_fcts.get_type(inner_name, block);
        int                 ptr_size      = ext_fcts.get_type_length(void_type);
        CORE_ADDR           begin         = (CORE_ADDR)read_memory_integer (varadr,            ptr_size);
        CORE_ADDR           end           = (CORE_ADDR)read_memory_integer (varadr + ptr_size, ptr_size);
        children = (end - begin) / TYPE_LENGTH (inner_type);
    }
    free (inner_name);
    return children;
}

int get_stl_vector_size_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (!type) return 0;
    return get_stl_vector_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}

int get_stl_set_or_multiset_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
    struct type *       void_type     = ext_fcts.get_type("void *", block);
    int                 ptr_size      = ext_fcts.get_type_length(void_type);
    return (int)read_memory_integer(varadr + 5 * ptr_size, ptr_size);
}

int get_stl_set_or_multiset_size_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (!type) return 0;
    return get_stl_set_or_multiset_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}

int get_stl_map_or_multimap_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
    struct type *       void_type     = ext_fcts.get_type("void *", block);
    int                 ptr_size      = ext_fcts.get_type_length(void_type);
    return (int)read_memory_integer(varadr + 5 * ptr_size, ptr_size);
}

int get_stl_map_or_multimap_size_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (!type) return 0;
    return get_stl_map_or_multimap_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}

int get_stl_deque_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
    char * inner_name    = (char *)malloc(strlen(type_name) + 1);

    struct type *       void_type     = ext_fcts.get_type("void *", block);
    int                 ptr_size      = ext_fcts.get_type_length(void_type);
    if (get_stl_inner_type(type_name, inner_name))
    {
        struct type *       inner_type    = ext_fcts.get_type(inner_name, block);
        int iter_beg_cur    = read_memory_integer (varadr + ptr_size * 2, ptr_size);
        int iter_beg_first  = read_memory_integer (varadr + ptr_size * 3, ptr_size);
        int iter_beg_last   = read_memory_integer (varadr + ptr_size * 4, ptr_size);
        int iter_beg_node   = read_memory_integer (varadr + ptr_size * 5, ptr_size);
        int iter_end_cur    = read_memory_integer (varadr + ptr_size * 6, ptr_size);
        int iter_end_first  = read_memory_integer (varadr + ptr_size * 7, ptr_size);
        int iter_end_last   = read_memory_integer (varadr + ptr_size * 8, ptr_size);
        int iter_end_node   = read_memory_integer (varadr + ptr_size * 9, ptr_size);
        int elems_per_nodes = ext_fcts.get_type_length(inner_type) < 512 ? 512 / ext_fcts.get_type_length(inner_type) : 1;
        return ( elems_per_nodes * (iter_end_node - iter_beg_node - ptr_size) + (iter_end_cur - iter_end_first) + (iter_beg_last - iter_beg_cur) ) / ptr_size;
    }
    return 0;
}

int get_stl_deque_size_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (!type) return 0;
    return get_stl_deque_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}

/*
 * predicates
 */

int is_stl_vector_from_name(const char * name, int len)
{
    if (len > 2 && name[len - 1] == '>')
    {
        if (!strncmp(name, "std::vector<", 12))
            return 1;
        if (!strncmp(name, "std::_Vector_base<", 18))
            return 1;
    }
    return 0;
}

int is_stl_list_from_name(const char * name, int len)
{
    if (len > 2 && name[len - 1] == '>')
    {
        if (!strncmp(name, "std::list<", 10))
            return 1;
        if (!strncmp(name, "std::_List_base<", 16))
            return 1;
    }
    return 0;
}

int is_stl_set_or_multiset_from_name(const char * name, int len)
{
    if (len > 2 && name[len - 1] == '>')
    {
        if (!strncmp(name, "std::set<", 9))
            return 1;
        if (!strncmp(name, "std::multiset<", 14))
            return 1;
        if (!strncmp(name, "std::_Rb_tree<", 14))
            return 1;
    }
    return 0;
}

int is_stl_map_or_multimap_from_name(const char * name, int len)
{
    if (len > 2 && name[len - 1] == '>')
    {
        if (!strncmp(name, "std::map<", 9))
            return 1;
        if (!strncmp(name, "std::multimap<", 14))
            return 1;
    }
    return 0;
}

int is_stl_deque_from_name(const char * name, int len)
{
    if (len > 2 && name[len - 1] == '>')
    {
        if (!strncmp(name, "std::deque<", 11))
            return 1;
        if (!strncmp(name, "std::_Deque_base<", 17))
            return 1;
    }
    return 0;
}

int is_stl_string_from_name(const char * name, int len)
{
    len = strlen (name);
    if (len > 2 && name[len - 1] == '>' && !strncmp(name, "std::basic_string<char,", 23))
        return 1;
    return 0;
}

int is_stl_vector_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (type)
    {
        const char * type_name = ext_fcts.get_type_name(type);
        int len = strlen(type_name);
        return is_stl_vector_from_name(type_name, len);
    }
    return 0;
}

int is_stl_list_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (type)
    {
        const char * type_name = ext_fcts.get_type_name(type);
        int len = strlen(type_name);
        return is_stl_list_from_name(type_name, len);
    }
    return 0;
}

int is_stl_map_or_multimap_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (type)
    {
        const char * type_name = ext_fcts.get_type_name(type);
        int len = strlen(type_name);
        return is_stl_map_or_multimap_from_name(type_name, len);
    }
    return 0;
}

int is_stl_set_or_multiset_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (type)
    {
        const char * type_name = ext_fcts.get_type_name(type);
        int len = strlen(type_name);
        return is_stl_set_or_multiset_from_name(type_name, len);
    }
    return 0;
}

int is_stl_deque_from_varobj(struct varobj * var)
{
    struct type * type = ext_fcts.get_varobj_type(var);
    if (type)
    {
        const char * type_name = ext_fcts.get_type_name(type);
        int len = strlen(type_name);
        return is_stl_deque_from_name(type_name, len);
    }
    return 0;
}

int type_handled(const char * type_name, int type_name_len)
{
    if (is_stl_vector_from_name(type_name, type_name_len)
            || is_stl_list_from_name(type_name, type_name_len)
            || is_stl_set_or_multiset_from_name(type_name, type_name_len)
            || is_stl_map_or_multimap_from_name(type_name, type_name_len)
            || is_stl_deque_from_name(type_name, type_name_len)
            || is_stl_string_from_name(type_name, type_name_len))
    {
        return 1;
    }
    return 0;
}

int get_num_children(struct varobj *varobj)
{
    if (is_stl_vector_from_varobj(varobj))
    {
        return get_stl_vector_size_from_varobj(varobj);
    }
    else if (is_stl_list_from_varobj(varobj))
    {
        return get_stl_list_size_from_varobj(varobj);
    }
    else if (is_stl_map_or_multimap_from_varobj(varobj))
    {
        return get_stl_map_or_multimap_size_from_varobj(varobj);
    }
    else if (is_stl_set_or_multiset_from_varobj(varobj))
    {
        return get_stl_set_or_multiset_size_from_varobj(varobj);
    }
    else if (is_stl_deque_from_varobj(varobj))
    {
        return get_stl_deque_size_from_varobj(varobj);
    }
    return 0;
}

int print(const char * type_name, int type_name_len, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty)
{
    if (is_stl_vector_from_name(type_name, type_name_len))
    {
        print_stl_vector(type_name, type_name_len, address, stream, format, recurse, pretty);
        return 1;
    }
    else if (is_stl_list_from_name(type_name, type_name_len))
    {
        print_stl_list(type_name, type_name_len, address, stream, format, recurse, pretty);
        return 1;
    }
    else if (is_stl_set_or_multiset_from_name(type_name, type_name_len))
    {
        print_stl_set(type_name, type_name_len, address, stream, format, recurse, pretty);
        return 1;
    }
    else if (is_stl_map_or_multimap_from_name(type_name, type_name_len))
    {
        print_stl_map(type_name, type_name_len, address, stream, format, recurse, pretty);
        return 1;
    }
    else if (is_stl_deque_from_name(type_name, type_name_len))
    {
        print_stl_deque(type_name, type_name_len, address, stream, format, recurse, pretty);
        return 1;
    }
    else if (is_stl_string_from_name(type_name, type_name_len))
    {
        print_stl_string(type_name, type_name_len, address, stream, format, recurse, pretty);
        return 1;
    }
    return 0;
}

int operator_handled(const char * type_name, int type_name_len, enum exp_opcode op)
{
    if (is_stl_vector_from_name(type_name, type_name_len)
            || is_stl_list_from_name(type_name, type_name_len)
            || is_stl_set_or_multiset_from_name(type_name, type_name_len)
            || is_stl_map_or_multimap_from_name(type_name, type_name_len)
            || is_stl_deque_from_name(type_name, type_name_len))
    {
        if (op == BINOP_SUBSCRIPT) return 1;
        if (op == UNOP_LENGTH)     return 1;
        if (op == UNOP_SIZEOF)     return 1;
    }
    return 0;
}

struct value * unary_operation(const char * type_name, int type_name_len, CORE_ADDR address, enum exp_opcode op)
{
    int size = 0;
    switch(op)
    {
        case UNOP_LENGTH:
        case UNOP_SIZEOF:
            if (is_stl_vector_from_name(type_name, type_name_len))
            {
                size = get_stl_vector_size(type_name, ext_fcts.get_current_block(), address);
            }
            else if (is_stl_list_from_name(type_name, type_name_len))
            {
                size = get_stl_list_size(type_name, ext_fcts.get_current_block(), address);
            }
            else if (is_stl_map_or_multimap_from_name(type_name, type_name_len))
            {
                size = get_stl_map_or_multimap_size(type_name, ext_fcts.get_current_block(), address);
            }
            else if (is_stl_set_or_multiset_from_name(type_name, type_name_len))
            {
                size = get_stl_set_or_multiset_size(type_name, ext_fcts.get_current_block(), address);
            }
            else if (is_stl_deque_from_name(type_name, type_name_len))
            {
                size = get_stl_deque_size(type_name, ext_fcts.get_current_block(), address);
            }
            if (stlsizeof == 0 && op == UNOP_SIZEOF)
            {
                char * inner_type = (char *)malloc(type_name_len + 1);
                get_stl_inner_type(type_name, inner_type);
                size *= ext_fcts.get_type_length(ext_fcts.get_type(inner_type, ext_fcts.get_current_block()));
                free(inner_type);
            }
            return ext_fcts.value_from_longest(ext_fcts.get_type("int", ext_fcts.get_current_block()), size);
        default:
            break;
    }
    return NULL;
}

struct value * binary_operation(const char * type_name, int type_name_len, CORE_ADDR address, struct value * other, enum exp_opcode op)
{
    switch(op)
    {
        case BINOP_SUBSCRIPT:
            if (is_stl_vector_from_name(type_name, type_name_len))
            {
                return get_stl_vector_item_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
            }
            else if (is_stl_list_from_name(type_name, type_name_len))
            {
                return get_stl_list_item_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
            }
            else if (is_stl_map_or_multimap_from_name(type_name, type_name_len))
            {
                return get_stl_map_pair_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
            }
            else if (is_stl_set_or_multiset_from_name(type_name, type_name_len))
            {
                return get_stl_set_item_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
            }
            else if (is_stl_deque_from_name(type_name, type_name_len))
            {
                return get_stl_deque_item_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
            }
            break;
        default:
            break;
    }
    return NULL;
}

struct type * get_child_item_type_at(struct varobj * varobj, int index)
{
    return get_stl_container_inner_type(varobj);
}

struct value * get_child_item_value_at(struct varobj * varobj, int index)
{
    struct type * type = ext_fcts.get_varobj_type(varobj);
    const char * type_name = ext_fcts.get_type_name(type);
    CORE_ADDR address = ext_fcts.get_value_address(ext_fcts.get_varobj_value(varobj));
    int type_name_len = strlen(type_name);

    if (is_stl_vector_from_name(type_name, type_name_len))
    {
        return get_stl_vector_item_at(type_name, type_name_len, address, index);
    }
    else if (is_stl_list_from_name(type_name, type_name_len))
    {
        return get_stl_list_item_at(type_name, type_name_len, address, index);
    }
    else if (is_stl_map_or_multimap_from_name(type_name, type_name_len))
    {
        return get_stl_map_pair_at(type_name, type_name_len, address, index);
    }
    else if (is_stl_set_or_multiset_from_name(type_name, type_name_len))
    {
        return get_stl_set_item_at(type_name, type_name_len, address, index);
    }
    else if (is_stl_deque_from_name(type_name, type_name_len))
    {
        return get_stl_deque_item_at(type_name, type_name_len, address, index);
    }
    return NULL;
}

GDB_SOURCES=../gdb-6.8-patched
CC=gcc
CFLAGS=-I$(GDB_SOURCES)/gdb -I$(GDB_SOURCES)/include -I$(GDB_SOURCES)/gdb/config

all: stl.so

stl.so: main.c
	$(CC) $(CFLAGS) -o $@ -shared -O3 $<

clean:
	rm -f stl.so


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]