summaryrefslogtreecommitdiff
path: root/gdb/typeprint.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2012-11-12 17:41:54 +0000
committerTom Tromey <tromey@redhat.com>2012-11-12 17:41:54 +0000
commit5d78b09716632218e61d95025f64b789f01be655 (patch)
tree78710011a53f3e9fb05b10d47556e9309a250a2b /gdb/typeprint.c
parent463288d719fec19e54633a159200f759633f21ea (diff)
downloadgdb-5d78b09716632218e61d95025f64b789f01be655.tar.gz
* NEWS: Update.
* data-directory/Makefile.in (PYTHON_FILES): Add type_printers.py. * python/lib/gdb/command/type_printers.py: New file. * python/lib/gdb/command/types.py (TypePrinter): New class. (_get_some_type_recognizers, get_type_recognizers, apply_type_recognizers, register_type_printer): New functions. * python/py-objfile.c (objfile_object) <type_printers>: New field. (objfpy_dealloc): Decref new field. (objfpy_new): Set new field. (objfpy_get_type_printers, objfpy_set_type_printers): New functions. (objfile_to_objfile_object): Set new field. (objfile_getset): Add "type_printers". * python/py-progspace.c (pspace_object) <type_printers>: New field. (pspy_dealloc): Decref new field. (pspy_new): Set new field. (pspy_get_type_printers, pspy_set_type_printers): New functions. (pspace_to_pspace_object): Set new field. (pspace_getset): Add "type_printers". * python/python.c (start_type_printers, apply_type_printers, free_type_printers): New functions. (_initialize_python): Set gdb.type_printers. * python/python.h (start_type_printers, apply_type_printers, free_type_printers): Declare. * typeprint.c (type_print_raw_options, default_ptype_flags): Update for new fields. (do_free_global_table, create_global_typedef_table, find_global_typedef): New functions. (find_typedef_in_hash): Use find_global_typedef. (whatis_exp): Use create_global_typedef_table. Change cleanup handling. * typeprint.h (struct type_print_options) <global_typedefs, global_printers>: New fields. doc * gdb.texinfo (Symbols): Document "info type-printers", "enable type-printer" and "disable type-printer". (Python API): Add new node to menu. (Type Printing API): New node. (Progspaces In Python): Document type_printers field. (Objfiles In Python): Likewise. (gdb.types) <get_type_recognizers, apply_type_recognizers, register_type_printer, TypePrinter>: Document. testsuite * gdb.base/completion.exp: Update for "info type-printers". * gdb.python/py-typeprint.cc: New file. * gdb.python/py-typeprint.exp: New file. * gdb.python/py-typeprint.py: New file.
Diffstat (limited to 'gdb/typeprint.c')
-rw-r--r--gdb/typeprint.c106
1 files changed, 93 insertions, 13 deletions
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index 0e1c93c0a8c..cf3ba381a44 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -38,6 +38,7 @@
#include <errno.h>
#include <ctype.h>
#include "cli/cli-utils.h"
+#include "python/python.h"
extern void _initialize_typeprint (void);
@@ -52,7 +53,9 @@ const struct type_print_options type_print_raw_options =
1, /* raw */
1, /* print_methods */
1, /* print_typedefs */
- NULL /* local_typedefs */
+ NULL, /* local_typedefs */
+ NULL, /* global_table */
+ NULL /* global_printers */
};
/* The default flags for 'ptype' and 'whatis'. */
@@ -62,7 +65,9 @@ static struct type_print_options default_ptype_flags =
0, /* raw */
1, /* print_methods */
1, /* print_typedefs */
- NULL /* local_typedefs */
+ NULL, /* local_typedefs */
+ NULL, /* global_table */
+ NULL /* global_printers */
};
@@ -235,6 +240,74 @@ copy_typedef_hash (struct typedef_hash_table *table)
return result;
}
+/* A cleanup to free the global typedef hash. */
+
+static void
+do_free_global_table (void *arg)
+{
+ struct type_print_options *flags = arg;
+
+ free_typedef_hash (flags->global_typedefs);
+ free_type_printers (flags->global_printers);
+}
+
+/* Create the global typedef hash. */
+
+static struct cleanup *
+create_global_typedef_table (struct type_print_options *flags)
+{
+ gdb_assert (flags->global_typedefs == NULL && flags->global_printers == NULL);
+ flags->global_typedefs = create_typedef_hash ();
+ flags->global_printers = start_type_printers ();
+ return make_cleanup (do_free_global_table, flags);
+}
+
+/* Look up the type T in the global typedef hash. If it is found,
+ return the typedef name. If it is not found, apply the
+ type-printers, if any, given by start_type_printers and return the
+ result. A NULL return means that the name was not found. */
+
+static const char *
+find_global_typedef (const struct type_print_options *flags,
+ struct type *t)
+{
+ char *applied;
+ void **slot;
+ struct typedef_field tf, *new_tf;
+
+ if (flags->global_typedefs == NULL)
+ return NULL;
+
+ tf.name = NULL;
+ tf.type = t;
+
+ slot = htab_find_slot (flags->global_typedefs->table, &tf, INSERT);
+ if (*slot != NULL)
+ {
+ new_tf = *slot;
+ return new_tf->name;
+ }
+
+ /* Put an entry into the hash table now, in case apply_type_printers
+ recurses. */
+ new_tf = XOBNEW (&flags->global_typedefs->storage, struct typedef_field);
+ new_tf->name = NULL;
+ new_tf->type = t;
+
+ *slot = new_tf;
+
+ applied = apply_type_printers (flags->global_printers, t);
+
+ if (applied != NULL)
+ {
+ new_tf->name = obstack_copy0 (&flags->global_typedefs->storage, applied,
+ strlen (applied));
+ xfree (applied);
+ }
+
+ return new_tf->name;
+}
+
/* Look up the type T in the typedef hash table in with FLAGS. If T
is in the table, return its short (class-relative) typedef name.
Otherwise return NULL. If the table is NULL, this always returns
@@ -243,16 +316,19 @@ copy_typedef_hash (struct typedef_hash_table *table)
const char *
find_typedef_in_hash (const struct type_print_options *flags, struct type *t)
{
- struct typedef_field tf, *found;
+ if (flags->local_typedefs != NULL)
+ {
+ struct typedef_field tf, *found;
- if (flags->local_typedefs == NULL)
- return NULL;
+ tf.name = NULL;
+ tf.type = t;
+ found = htab_find (flags->local_typedefs->table, &tf);
- tf.name = NULL;
- tf.type = t;
- found = htab_find (flags->local_typedefs->table, &tf);
+ if (found != NULL)
+ return found->name;
+ }
- return found == NULL ? NULL : found->name;
+ return find_global_typedef (flags, t);
}
@@ -325,7 +401,7 @@ whatis_exp (char *exp, int show)
{
struct expression *expr;
struct value *val;
- struct cleanup *old_chain = NULL;
+ struct cleanup *old_chain;
struct type *real_type = NULL;
struct type *type;
int full = 0;
@@ -334,6 +410,8 @@ whatis_exp (char *exp, int show)
struct value_print_options opts;
struct type_print_options flags = default_ptype_flags;
+ old_chain = make_cleanup (null_cleanup, NULL);
+
if (exp)
{
if (*exp == '/')
@@ -373,7 +451,7 @@ whatis_exp (char *exp, int show)
}
expr = parse_expression (exp);
- old_chain = make_cleanup (free_current_contents, &expr);
+ make_cleanup (free_current_contents, &expr);
val = evaluate_type (expr);
}
else
@@ -394,6 +472,9 @@ whatis_exp (char *exp, int show)
printf_filtered ("type = ");
+ if (!flags.raw)
+ create_global_typedef_table (&flags);
+
if (real_type)
{
printf_filtered ("/* real type = ");
@@ -406,8 +487,7 @@ whatis_exp (char *exp, int show)
LA_PRINT_TYPE (type, "", gdb_stdout, show, 0, &flags);
printf_filtered ("\n");
- if (exp)
- do_cleanups (old_chain);
+ do_cleanups (old_chain);
}
static void