From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20575 invoked by alias); 6 Nov 2008 19:58:20 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 20503 invoked by uid 306); 6 Nov 2008 19:58:19 -0000 Date: Thu, 06 Nov 2008 19:58:00 -0000 Message-ID: <20081106195819.20482.qmail@sourceware.org> From: tromey@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-tromey-python: gdb X-Git-Refname: refs/heads/archer-tromey-python X-Git-Reftype: branch X-Git-Oldrev: e066d5afc0238f478df70c2b2f0c52d58959eb4d X-Git-Newrev: 95bc4ef80d85b793a2cc50d39db64f2e7abd8551 X-SW-Source: 2008-q4/txt/msg00073.txt.bz2 List-Id: The branch, archer-tromey-python has been updated via 95bc4ef80d85b793a2cc50d39db64f2e7abd8551 (commit) from e066d5afc0238f478df70c2b2f0c52d58959eb4d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 95bc4ef80d85b793a2cc50d39db64f2e7abd8551 Author: Tom Tromey Date: Thu Nov 6 12:57:17 2008 -0700 gdb * varobj.c (struct varobj) : New field. (varobj_set_display_format): Update. (varobj_get_display_hint): Likewise. (varobj_get_num_children): Likewise. (varobj_list_children): Likewise. (install_new_value): Destroy old pretty-printer. (install_visualizer): Update. Recompute children when visualizer is removed. (install_default_visualizer): Don't instantiate printer. Add 'type' argument. (new_variable): Initialize new field. (free_variable): Destroy new field. (instantiate_pretty_printer): New function. (varobj_set_visualizer): Don't instantiate printer. * python/python-internal.h (objfpy_get_mi_printers, objfpy_get_cli_printers): Remove. (objfpy_get_printers): Declare. (gdbpy_instantiate_printer): Declare. * python/python.c (find_pretty_printer): Remove is_mi and dictp arguments. (_initialize_python): Initialize pretty_printers, not cli_pretty_printers and mi_pretty_printers. <_format_children>: Update. Conditionally call 'children'. (apply_pretty_printer): Update. Instantiate printer. (apply_val_pretty_printer): Update. Instantiate printer. (pretty_print_one_value): Rename func argument to printer. Remove value argument. Update. (gdbpy_instantiate_printer): New function. (apply_varobj_pretty_printer): Update. (gdbpy_get_varobj_pretty_printer): Update. * python/python-objfile.c (objfile_object): Remove mi_printers, cli_printers; add printers. (objfpy_dealloc): Update. (objfpy_new): Update. (objfpy_get_printers): Rename from objfpy_get_mi_printers. Update. (objfpy_set_printers): Rename from objfpy_set_mi_printers. Update. (objfpy_get_cli_printers): Remove. (objfpy_set_cli_printers): Remove. (objfile_to_objfile_object): Update. (objfile_getset): Update. gdb/doc * gdb.texinfo (Pretty Printing): Update. (GDB/MI Variable Objects): Likewise. gdb/testsuite * gdb.python/python-mi.exp: Update. * gdb.python/python-prettyprint.py: Move to purely class-based printers. ----------------------------------------------------------------------- Summary of changes: gdb/ChangeLog | 45 +++++ gdb/doc/ChangeLog | 5 + gdb/doc/gdb.texinfo | 92 ++++------ gdb/python/python-internal.h | 4 +- gdb/python/python-objfile.c | 88 ++-------- gdb/python/python.c | 221 +++++++++++++----------- gdb/testsuite/ChangeLog | 6 + gdb/testsuite/gdb.python/python-mi.exp | 4 +- gdb/testsuite/gdb.python/python-prettyprint.py | 76 +++++---- gdb/varobj.c | 150 +++++++++------- 10 files changed, 360 insertions(+), 331 deletions(-) First 500 lines of diff: diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5533820..9333dcf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,48 @@ +2008-11-06 Tom Tromey + + * varobj.c (struct varobj) : New field. + (varobj_set_display_format): Update. + (varobj_get_display_hint): Likewise. + (varobj_get_num_children): Likewise. + (varobj_list_children): Likewise. + (install_new_value): Destroy old pretty-printer. + (install_visualizer): Update. Recompute children when visualizer + is removed. + (install_default_visualizer): Don't instantiate printer. Add + 'type' argument. + (new_variable): Initialize new field. + (free_variable): Destroy new field. + (instantiate_pretty_printer): New function. + (varobj_set_visualizer): Don't instantiate printer. + * python/python-internal.h (objfpy_get_mi_printers, + objfpy_get_cli_printers): Remove. + (objfpy_get_printers): Declare. + (gdbpy_instantiate_printer): Declare. + * python/python.c (find_pretty_printer): Remove is_mi and dictp + arguments. + (_initialize_python): Initialize pretty_printers, not + cli_pretty_printers and mi_pretty_printers. + <_format_children>: Update. Conditionally call 'children'. + (apply_pretty_printer): Update. Instantiate printer. + (apply_val_pretty_printer): Update. Instantiate printer. + (pretty_print_one_value): Rename func argument to printer. Remove + value argument. Update. + (gdbpy_instantiate_printer): New function. + (apply_varobj_pretty_printer): Update. + (gdbpy_get_varobj_pretty_printer): Update. + * python/python-objfile.c (objfile_object): Remove mi_printers, + cli_printers; add printers. + (objfpy_dealloc): Update. + (objfpy_new): Update. + (objfpy_get_printers): Rename from objfpy_get_mi_printers. + Update. + (objfpy_set_printers): Rename from objfpy_set_mi_printers. + Update. + (objfpy_get_cli_printers): Remove. + (objfpy_set_cli_printers): Remove. + (objfile_to_objfile_object): Update. + (objfile_getset): Update. + 2008-11-03 Paul Pluzhnikov * python/python.c (find_pretty_printer): Fix gcc-4.3.1 warnings. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 26c9ed2..9d45150 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2008-11-06 Tom Tromey + + * gdb.texinfo (Pretty Printing): Update. + (GDB/MI Variable Objects): Likewise. + 2008-10-27 Tom Tromey * gdb.texinfo (Pretty Printing): Reword list of predefined display diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 787a438..071c912 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -17951,24 +17951,31 @@ using Python code. This mechanism works for both MI and the CLI. A pretty-printer is an object that implements a specific interface. There is no predefined base class for pretty-printers. -@defop Operation {pretty printer} children (self, val) -This method is used by both the MI and CLI code. When printing a -value, @value{GDBN} will call this method to display the children of -@var{val}, an instance of @code{gdb.Value}. +@defop Operation {pretty printer} __init__ (self, val) +When printing a value, @value{GDBN} constructs an instance of the +pretty-printer. @var{val} is the value to be printed, an instance of +@code{gdb.Value}. +@end defop + +@defop Operation {pretty printer} children (self) +When printing a value, @value{GDBN} will call this method to compute +the children of the value passed to the object's constructor. This method must return an object conforming to the Python iterator protocol. Each element returned by the iterator must be a tuple holding two elements. The first element is the ``name'' of the child; the second element is the child's value. The value can be any Python object which is convertible to a @value{GDBN} value. -@end defop -@defop Operation {pretty printer} display_hint (self, val) -This method is only used by the MI printer. +This method is optional. If it does not exist, @value{GDBN} will act +as though the value has no children. +@end defop -This method must return a string. It will be supplied to the MI -consumer as a @samp{displayhint} attribute of the variable being -printed. +@defop Operation {pretty printer} display_hint (self) +This method must return a string. The CLI may use this to change the +formatting of children of a value. The result will also be supplied +to an MI consumer as a @samp{displayhint} attribute of the variable +being printed. Some display hints are predefined by @value{GDBN}: @@ -17980,10 +17987,9 @@ alternate between keys and values. @end table @end defop -@defop Operation {pretty printer} to_string (self, val) -This method is used by both the MI and CLI code. When printing a -value, @value{GDBN} will call this method to display the string -representation of @var{val}, an instance of @code{gdb.Value}. +@defop Operation {pretty printer} to_string (self) +@value{GDBN} will call this method to display the string +representation of the value passed to the object's constructor. When printing from the CLI, if the @code{to_string} method exists, then @value{GDBN} will prepend its result to the values returned by @@ -17992,13 +17998,15 @@ then @value{GDBN} will prepend its result to the values returned by This method must return a string. @end defop -@subsubsection Selecting CLI Pretty-Printers +@subsubsection Selecting Pretty-Printers -The Python dictionary @code{gdb.cli_pretty_printers} maps regular -expressions (strings) onto pretty-printers. A pretty-printer is -either a function or an object. +The Python dictionary @code{gdb.pretty_printers} maps regular +expressions (strings) onto constructors. A constructor, in this +context, is a function which takes a single @code{gdb.Value} argument +and returns a a pretty-printer conforming to the interface definition +above. -When printing a value, @value{GDBN} first computes the values' +When printing a value, @value{GDBN} first computes the value's canonical type by following typedefs, following a reference type to its referenced type, and removing qualifiers, such as @code{const} or @code{volatile}. The name of this type is then compared to each @@ -18006,46 +18014,23 @@ regular expression. If a regular expression matches, then the corresponding pretty-printer is invoked with a @code{gdb.Value} representing the value to be printed. -If the pretty-printer is a function, the function is called directly. - -If the pretty-printer is an object, the object's methods are called as -described above. - -If the pretty-printer returns a string, it is printed. If it returns any -Python value that is convertible to a @code{gdb.Value}, then that -value is passed to the regular @value{GDBN} type-printing code. - The order in which the regular expressions are tried is not specified. -Here is an example showing how a @code{std::string} might be printed: - -@smallexample -def printstdstring(val): - return val['_M_dataplus']['_M_p'] - -gdb.cli_pretty_printers['^std::basic_string$'] = printstdstring -@end smallexample - -Here is an example of the same printer, using a class: +Here is an example showing how a @code{std::string} printer might be +written: @smallexample class StdStringPrinter: - def to_string(self, val): - return val['_M_dataplus']['_M_p'] - -gdb.cli_pretty_printers['^std::basic_string$'] = StdStringPrinter() -@end smallexample + "Print a std::string" -@subsubsection Selecting MI Pretty-Printers + def __init__(self, val): + self.val = val -MI pretty-printers are selected using a dictionary named -@code{gdb.mi_pretty_printers}. A key in this dictionary should be a -regular expression in string form. A value in this dictionary should -be a constructor which takes no arguments and which returns a new -object of the form described above. + def to_string(self): + return self.val['_M_dataplus']['_M_p'] -@value{GDBN} will consult @code{gdb.mi_pretty_printers} whenever a new -MI variable object is created. +gdb.pretty_printers['^std::basic_string$'] = StdStringPrinter +@end smallexample @node Threads In Python @subsubsection Threads In Python @@ -21821,9 +21806,8 @@ The pre-defined function @code{gdb.get_default_visualizer} may be used to select a visualizer according to the type of the varobj. This is called when a varobj is created, and so ordinarily is not needed. -@code{gdb.get_default_visualizer} looks in a global dictionary named -@code{gdb.mi_pretty_printers}. This works analogously to -@code{gdb.cli_pretty_printers}. +@code{gdb.get_default_visualizer} looks in the global dictionary named +@code{gdb.pretty_printers}. This feature is only available if Python support is enabled. diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 6dff805..672a2fe 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -75,8 +75,7 @@ PyObject *gdb_owned_value_to_value_object (struct value *v); PyObject *type_to_type_object (struct type *); PyObject *objfile_to_objfile_object (struct objfile *); -PyObject *objfpy_get_mi_printers (PyObject *, void *); -PyObject *objfpy_get_cli_printers (PyObject *, void *); +PyObject *objfpy_get_printers (PyObject *, void *); struct block *block_object_to_block (PyObject *obj); struct symbol *symbol_object_to_symbol (PyObject *obj); @@ -130,6 +129,7 @@ int gdbpy_is_string (PyObject *obj); char *apply_varobj_pretty_printer (PyObject *print_obj, struct value *value, struct value **replacement); PyObject *gdbpy_get_varobj_pretty_printer (struct type *type); +PyObject *gdbpy_instantiate_printer (PyObject *cons, struct value *value); extern PyObject *gdbpy_children_cst; extern PyObject *gdbpy_to_string_cst; diff --git a/gdb/python/python-objfile.c b/gdb/python/python-objfile.c index 6b5a7c3..0a942c8 100644 --- a/gdb/python/python-objfile.c +++ b/gdb/python/python-objfile.c @@ -29,9 +29,8 @@ typedef struct /* The corresponding objfile. */ struct objfile *objfile; - /* The pretty-printer dictionaries. */ - PyObject *mi_printers; - PyObject *cli_printers; + /* The pretty-printer dictionary. */ + PyObject *printers; } objfile_object; static PyTypeObject objfile_object_type; @@ -55,8 +54,7 @@ static void objfpy_dealloc (PyObject *o) { objfile_object *self = (objfile_object *) o; - Py_XDECREF (self->mi_printers); - Py_XDECREF (self->cli_printers); + Py_XDECREF (self->printers); self->ob_type->tp_free ((PyObject *) self); } @@ -67,17 +65,9 @@ objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) if (self) { self->objfile = NULL; - /* Initialize in case of early return. */ - self->cli_printers = NULL; - self->mi_printers = PyDict_New (); - if (!self->mi_printers) - { - Py_DECREF (self); - return NULL; - } - self->cli_printers = PyDict_New (); - if (!self->cli_printers) + self->printers = PyDict_New (); + if (!self->printers) { Py_DECREF (self); return NULL; @@ -87,67 +77,34 @@ objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) } PyObject * -objfpy_get_mi_printers (PyObject *o, void *ignore) -{ - objfile_object *self = (objfile_object *) o; - Py_INCREF (self->mi_printers); - return self->mi_printers; -} - -static int -objfpy_set_mi_printers (PyObject *o, PyObject *value, void *ignore) -{ - objfile_object *self = (objfile_object *) o; - if (! value) - { - PyErr_SetString (PyExc_TypeError, - "cannot delete the mi_pretty_printers attribute"); - return -1; - } - - if (! PyDict_Check (value)) - { - PyErr_SetString (PyExc_TypeError, - "the mi_pretty_printers attribute must be a dictionary"); - return -1; - } - - Py_XDECREF (self->mi_printers); - Py_INCREF (value); - self->mi_printers = value; - - return 0; -} - -PyObject * -objfpy_get_cli_printers (PyObject *o, void *ignore) +objfpy_get_printers (PyObject *o, void *ignore) { objfile_object *self = (objfile_object *) o; - Py_INCREF (self->cli_printers); - return self->cli_printers; + Py_INCREF (self->printers); + return self->printers; } static int -objfpy_set_cli_printers (PyObject *o, PyObject *value, void *ignore) +objfpy_set_printers (PyObject *o, PyObject *value, void *ignore) { objfile_object *self = (objfile_object *) o; if (! value) { PyErr_SetString (PyExc_TypeError, - "cannot delete the cli_pretty_printers attribute"); + "cannot delete the pretty_printers attribute"); return -1; } if (! PyDict_Check (value)) { PyErr_SetString (PyExc_TypeError, - "the cli_pretty_printers attribute must be a dictionary"); + "the pretty_printers attribute must be a dictionary"); return -1; } - Py_XDECREF (self->cli_printers); + Py_XDECREF (self->printers); Py_INCREF (value); - self->cli_printers = value; + self->printers = value; return 0; } @@ -181,18 +138,9 @@ objfile_to_objfile_object (struct objfile *objfile) PyObject *dict; object->objfile = objfile; - /* Initialize in case of early return. */ - object->cli_printers = NULL; - - object->mi_printers = PyDict_New (); - if (!object->mi_printers) - { - Py_DECREF (object); - return NULL; - } - object->cli_printers = PyDict_New (); - if (!object->cli_printers) + object->printers = PyDict_New (); + if (!object->printers) { Py_DECREF (object); return NULL; @@ -223,10 +171,8 @@ gdbpy_initialize_objfile (void) static PyGetSetDef objfile_getset[] = { - { "mi_pretty_printers", objfpy_get_mi_printers, objfpy_set_mi_printers, - "MI pretty printers", NULL }, - { "cli_pretty_printers", objfpy_get_cli_printers, objfpy_set_cli_printers, - "CLI pretty printers", NULL }, + { "pretty_printers", objfpy_get_printers, objfpy_set_printers, + "Pretty printers", NULL }, { NULL } }; diff --git a/gdb/python/python.c b/gdb/python/python.c index 5f6a269..d6cea7e 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -676,17 +676,14 @@ search_pp_dictionary (PyObject *dict, char *type_name) return found; } -/* Find the pretty-printing function for TYPE. If no pretty-printer - exists, return NULL. If one exists, return a borrowed reference. - If a printer is found, *DICTP is set to a reference to the - dictionary object; it must be derefed by the caller. DICT_NAME is - the name of the dictionary to search for types. */ +/* Find the pretty-printing constructor function for TYPE. If no + pretty-printer exists, return NULL. If one exists, return a new + reference. */ static PyObject * -find_pretty_printer (struct type *type, PyObject **dictp, int is_mi) +find_pretty_printer (struct type *type) { PyObject *dict, *found = NULL; char *type_name = NULL; - char *dict_name; struct objfile *obj; volatile struct gdb_exception except; @@ -710,11 +707,7 @@ find_pretty_printer (struct type *type, PyObject **dictp, int is_mi) if (!objf) continue; - if (is_mi) - dict = objfpy_get_mi_printers (objf, NULL); - else - dict = objfpy_get_cli_printers (objf, NULL); - + dict = objfpy_get_printers (objf, NULL); found = search_pp_dictionary (dict, type_name); if (found) goto done; @@ -723,11 +716,10 @@ find_pretty_printer (struct type *type, PyObject **dictp, int is_mi) } /* Fetch the global pretty printer dictionary. */ - dict_name = is_mi ? "mi_pretty_printers" : "cli_pretty_printers"; dict = NULL; - if (! PyObject_HasAttrString (gdb_module, dict_name)) + if (! PyObject_HasAttrString (gdb_module, "pretty_printers")) goto done; - dict = PyObject_GetAttrString (gdb_module, dict_name); + dict = PyObject_GetAttrString (gdb_module, "pretty_printers"); if (! dict) goto done; if (! PyDict_Check (dict) || ! PyDict_Size (dict)) @@ -739,57 +731,44 @@ find_pretty_printer (struct type *type, PyObject **dictp, int is_mi) xfree (type_name); if (found) - *dictp = dict; - else - Py_XDECREF (dict); + Py_INCREF (found); + Py_XDECREF (dict); return found; } -/* Pretty-print a single value, VALUE, using the printer function - FUNC. If the function returns a string, an xmalloc()d copy is - returned. Otherwise, if the function returns a value, a *OUT_VALUE - is set to the value, and NULL is returned. On error, *OUT_VALUE is - set to NULL and NULL is returned. If CHILDREN is true, we may also - try to call an object's "children" method and format the output +/* Pretty-print a single value, via the printer object PRINTER. If + the function returns a string, an xmalloc()d copy is returned. + Otherwise, if the function returns a value, a *OUT_VALUE is set to + the value, and NULL is returned. On error, *OUT_VALUE is set to + NULL and NULL is returned. If CHILDREN is true, we may also try to + call an object's "children" method and format the output accordingly. */ static char * -pretty_print_one_value (PyObject *func, struct value *value, - struct value **out_value, int children) +pretty_print_one_value (PyObject *printer, struct value **out_value, + int children) { char *output = NULL; volatile struct gdb_exception except; TRY_CATCH (except, RETURN_MASK_ALL) { - PyObject *val_obj, *result; - - /* FIXME: memory management here. Why are values so - funny? */ - value = value_copy (value); - - val_obj = value_to_value_object (value); + PyObject *result; - /* The function might be an MI-style class, or it might be an - ordinary function. If CHILDREN is true, the existence of - either the to_string or children methods means to call - _format_children. Otherwise, if we have to_string, call it. - As a last resort, call the object as a function. */ + /* If CHILDREN is true, call _format_children. Otherwise, just + try to call the object's to_string method. */ if (children hooks/post-receive -- Repository for Project Archer.