2010-04-14 Phil Muldoon <pmuldoon@redhat.com>

PR python/11381

	* python/py-prettyprint.c (pretty_print_one_value): Test for
	Py_None.
	(print_string_repr): Test for Py_None.  Set flags accordingly.
	Return value depending on return type.
	(print_children): Take a value indicating whether data was printed
	before this function was called.  Alter output accordingly.
	(apply_val_pretty_printer): Capture return value from
	print_string_repr and pass to print_children.

2010-04-14  Phil Muldoon  <pmuldoon@redhat.com>

	* gdb.python/py-prettyprint.py (NoStringContainerPrinter): New printer.
	* gdb.python/py-prettyprint.c: Add justchildren struct, typedefs.
	* gdb.python/py-prettyprint.exp: New test for to_string returning None.
	* gdb.python/py-mi.exp: New test for to_string returning None.

2010-04-14  Phil Muldoon  <pmuldoon@redhat.com>

	* gdb.texinfo (Pretty Printing): Document behaviour when to_string
	returns None.
This commit is contained in:
Phil Muldoon 2010-04-14 12:02:46 +00:00
parent d594eacc9e
commit 79f283fe85
9 changed files with 180 additions and 47 deletions

View file

@ -1,3 +1,16 @@
2010-04-14 Phil Muldoon <pmuldoon@redhat.com>
PR python/11381
* python/py-prettyprint.c (pretty_print_one_value): Test for
Py_None.
(print_string_repr): Test for Py_None. Set flags accordingly.
Return value depending on return type.
(print_children): Take a value indicating whether data was printed
before this function was called. Alter output accordingly.
(apply_val_pretty_printer): Capture return value from
print_string_repr and pass to print_children.
2010-04-13 Mark Kettenis <kettenis@gnu.org> 2010-04-13 Mark Kettenis <kettenis@gnu.org>
PR corefiles/11481 PR corefiles/11481

View file

@ -1,3 +1,8 @@
2010-04-14 Phil Muldoon <pmuldoon@redhat.com>
* gdb.texinfo (Pretty Printing): Document behaviour when to_string
returns None.
2010-04-09 Stan Shebs <stan@codesourcery.com> 2010-04-09 Stan Shebs <stan@codesourcery.com>
* gdb.texinfo (gdb/mi Tracepoint Commands) <-trace-status>: * gdb.texinfo (gdb/mi Tracepoint Commands) <-trace-status>:

View file

@ -20435,6 +20435,9 @@ the resulting value. Again, this may result in a call to another
pretty-printer. Python scalars (integers, floats, and booleans) and pretty-printer. Python scalars (integers, floats, and booleans) and
strings are convertible to @code{gdb.Value}; other types are not. strings are convertible to @code{gdb.Value}; other types are not.
Finally, if this method returns @code{None} then no further operations
are peformed in this method and nothing is printed.
If the result is not one of these types, an exception is raised. If the result is not one of these types, an exception is raised.
@end defop @end defop

View file

@ -125,9 +125,12 @@ find_pretty_printer (PyObject *value)
/* Pretty-print a single value, via the printer object PRINTER. /* Pretty-print a single value, via the printer object PRINTER.
If the function returns a string, a PyObject containing the string If the function returns a string, a PyObject containing the string
is returned. Otherwise, if the function returns a value, is returned. If the function returns Py_NONE that means the pretty
*OUT_VALUE is set to the value, and NULL is returned. On error, printer returned the Python None as a value. Otherwise, if the
*OUT_VALUE is set to NULL, and NULL is returned. */ function returns a value, *OUT_VALUE is set to the value, and NULL
is returned. On error, *OUT_VALUE is set to NULL, and NULL is
returned. */
static PyObject * static PyObject *
pretty_print_one_value (PyObject *printer, struct value **out_value) pretty_print_one_value (PyObject *printer, struct value **out_value)
{ {
@ -140,7 +143,8 @@ pretty_print_one_value (PyObject *printer, struct value **out_value)
result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL); result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
if (result) if (result)
{ {
if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result)) if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result)
&& result != Py_None)
{ {
*out_value = convert_value_from_python (result); *out_value = convert_value_from_python (result);
if (PyErr_Occurred ()) if (PyErr_Occurred ())
@ -179,8 +183,11 @@ gdbpy_get_display_hint (PyObject *printer)
} }
/* Helper for apply_val_pretty_printer which calls to_string and /* Helper for apply_val_pretty_printer which calls to_string and
formats the result. */ formats the result. If the value returnd is Py_None, nothing is
static void printed and the function returns a 1; in all other cases data is
printed as given by the pretty printer and the function returns 0.
*/
static int
print_string_repr (PyObject *printer, const char *hint, print_string_repr (PyObject *printer, const char *hint,
struct ui_file *stream, int recurse, struct ui_file *stream, int recurse,
const struct value_print_options *options, const struct value_print_options *options,
@ -189,52 +196,58 @@ print_string_repr (PyObject *printer, const char *hint,
{ {
struct value *replacement = NULL; struct value *replacement = NULL;
PyObject *py_str = NULL; PyObject *py_str = NULL;
int is_py_none = 0;
py_str = pretty_print_one_value (printer, &replacement); py_str = pretty_print_one_value (printer, &replacement);
if (py_str) if (py_str)
{ {
gdb_byte *output = NULL; if (py_str == Py_None)
long length; is_py_none = 1;
struct type *type;
char *encoding = NULL;
PyObject *string = NULL;
int is_lazy;
is_lazy = gdbpy_is_lazy_string (py_str);
if (is_lazy)
output = gdbpy_extract_lazy_string (py_str, &type, &length, &encoding);
else else
{ {
string = python_string_to_target_python_string (py_str); gdb_byte *output = NULL;
if (string) long length;
struct type *type;
char *encoding = NULL;
PyObject *string = NULL;
int is_lazy;
is_lazy = gdbpy_is_lazy_string (py_str);
if (is_lazy)
output = gdbpy_extract_lazy_string (py_str, &type, &length, &encoding);
else
{ {
output = PyString_AsString (string); string = python_string_to_target_python_string (py_str);
length = PyString_Size (string); if (string)
type = builtin_type (gdbarch)->builtin_char; {
output = PyString_AsString (string);
length = PyString_Size (string);
type = builtin_type (gdbarch)->builtin_char;
}
else
gdbpy_print_stack ();
}
if (output)
{
if (is_lazy || (hint && !strcmp (hint, "string")))
LA_PRINT_STRING (stream, type, output, length, encoding,
0, options);
else
fputs_filtered (output, stream);
} }
else else
gdbpy_print_stack (); gdbpy_print_stack ();
} if (string)
Py_DECREF (string);
if (output)
{
if (is_lazy || (hint && !strcmp (hint, "string")))
LA_PRINT_STRING (stream, type, output, length, encoding,
0, options);
else else
fputs_filtered (output, stream); xfree (output);
xfree (encoding);
Py_DECREF (py_str);
} }
else
gdbpy_print_stack ();
if (string)
Py_DECREF (string);
else
xfree (output);
xfree (encoding);
Py_DECREF (py_str);
} }
else if (replacement) else if (replacement)
{ {
@ -245,6 +258,8 @@ print_string_repr (PyObject *printer, const char *hint,
} }
else else
gdbpy_print_stack (); gdbpy_print_stack ();
return is_py_none;
} }
static void static void
@ -323,12 +338,14 @@ push_dummy_python_frame ()
} }
/* Helper for apply_val_pretty_printer that formats children of the /* Helper for apply_val_pretty_printer that formats children of the
printer, if any exist. */ printer, if any exist. If is_py_none is true, then nothing has
been printed by to_string, and format output accordingly. */
static void static void
print_children (PyObject *printer, const char *hint, print_children (PyObject *printer, const char *hint,
struct ui_file *stream, int recurse, struct ui_file *stream, int recurse,
const struct value_print_options *options, const struct value_print_options *options,
const struct language_defn *language) const struct language_defn *language,
int is_py_none)
{ {
int is_map, is_array, done_flag, pretty; int is_map, is_array, done_flag, pretty;
unsigned int i; unsigned int i;
@ -408,7 +425,13 @@ print_children (PyObject *printer, const char *hint,
2. Arrays. Always print a ",". 2. Arrays. Always print a ",".
3. Other. Always print a ",". */ 3. Other. Always print a ",". */
if (i == 0) if (i == 0)
fputs_filtered (" = {", stream); {
if (is_py_none)
fputs_filtered ("{", stream);
else
fputs_filtered (" = {", stream);
}
else if (! is_map || i % 2 == 0) else if (! is_map || i % 2 == 0)
fputs_filtered (pretty ? "," : ", ", stream); fputs_filtered (pretty ? "," : ", ", stream);
@ -532,7 +555,7 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
char *hint = NULL; char *hint = NULL;
struct cleanup *cleanups; struct cleanup *cleanups;
int result = 0; int result = 0;
int is_py_none = 0;
cleanups = ensure_python_env (gdbarch, language); cleanups = ensure_python_env (gdbarch, language);
/* Instantiate the printer. */ /* Instantiate the printer. */
@ -557,9 +580,11 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
make_cleanup (free_current_contents, &hint); make_cleanup (free_current_contents, &hint);
/* Print the section */ /* Print the section */
print_string_repr (printer, hint, stream, recurse, options, language, is_py_none = print_string_repr (printer, hint, stream, recurse,
gdbarch); options, language, gdbarch);
print_children (printer, hint, stream, recurse, options, language); print_children (printer, hint, stream, recurse, options, language,
is_py_none);
result = 1; result = 1;

View file

@ -1,3 +1,10 @@
2010-04-14 Phil Muldoon <pmuldoon@redhat.com>
* gdb.python/py-prettyprint.py (NoStringContainerPrinter): New printer.
* gdb.python/py-prettyprint.c: Add justchildren struct, typedefs.
* gdb.python/py-prettyprint.exp: New test for to_string returning None.
* gdb.python/py-mi.exp: New test for to_string returning None.
2010-04-12 Phil Muldoon <pmuldoon@redhat.com> 2010-04-12 Phil Muldoon <pmuldoon@redhat.com>
* gdb.python/py-breakpoint.c: Make result global. * gdb.python/py-breakpoint.c: Make result global.

View file

@ -61,6 +61,16 @@ mi_list_varobj_children container {
mi_delete_varobj container "delete varobj" mi_delete_varobj container "delete varobj"
mi_create_dynamic_varobj nscont nstype \
"create nscont varobj, no pretty-printing"
mi_list_varobj_children nscont {
{ nscont.len len 0 int }
{ nscont.elements elements 1 "int ." }
} "examine nscont children=0, no pretty-printing"
mi_delete_varobj nscont "delete varobj"
mi_gdb_test "-enable-pretty-printing" "" mi_gdb_test "-enable-pretty-printing" ""
mi_create_varobj_checked string string_1 \ mi_create_varobj_checked string string_1 \
@ -239,4 +249,29 @@ mi_continue_to_line \
mi_varobj_update_with_type_change container int 0 "update after type change" mi_varobj_update_with_type_change container int 0 "update after type change"
mi_continue_to_line \
[gdb_get_line_number {break to inspect struct and union} ${testfile}.c] \
"step to outer breakpoint"
mi_create_dynamic_varobj nscont nstype \
"create nstype varobj"
mi_list_varobj_children nscont {
{ {nscont.\[0\]} {\[0\]} 0 int }
{ {nscont.\[1\]} {\[1\]} 0 int }
} "list children after setting update range"
mi_gdb_test "-var-set-visualizer nscont None" \
"\\^done" \
"clear visualizer"
mi_gdb_test "-var-update nscont" \
"\\^done,changelist=\\\[\\\]" \
"varobj update after clearing"
mi_gdb_test "-var-set-visualizer nscont gdb.default_visualizer" \
"\\^done" \
"choose default visualizer"
remote_file host delete ${remote_python_file} remote_file host delete ${remote_python_file}

View file

@ -119,6 +119,15 @@ typedef struct string_repr
/* This lets us avoid malloc. */ /* This lets us avoid malloc. */
int array[100]; int array[100];
int narray[10];
struct justchildren
{
int len;
int *elements;
};
typedef struct justchildren nostring_type;
struct container struct container
{ {
@ -196,7 +205,9 @@ main ()
const struct string_repr cstring = { { "const string" } }; const struct string_repr cstring = { { "const string" } };
/* Clearing by being `static' could invoke an other GDB C++ bug. */ /* Clearing by being `static' could invoke an other GDB C++ bug. */
struct nullstr nullstr; struct nullstr nullstr;
nostring_type nstype;
nstype.elements = narray;
nstype.len = 0;
init_ss(&ss, 1, 2); init_ss(&ss, 1, 2);
init_ss(ssa+0, 3, 4); init_ss(ssa+0, 3, 4);
@ -249,5 +260,9 @@ main ()
do_nothing (); do_nothing ();
#endif #endif
nstype.elements[0] = 7;
nstype.elements[1] = 42;
nstype.len = 2;
return 0; /* break to inspect struct and union */ return 0; /* break to inspect struct and union */
} }

View file

@ -101,6 +101,7 @@ proc run_lang_tests {lang} {
gdb_test "print estring" "\"embedded x\\\\201\\\\202\\\\203\\\\204\"" gdb_test "print estring" "\"embedded x\\\\201\\\\202\\\\203\\\\204\""
gdb_test "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}" gdb_test "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}"
gdb_test "print nstype" " = {$nl *.0. = 7,$nl *.1. = 42$nl}"
gdb_test "continue" "Program exited normally\." gdb_test "continue" "Program exited normally\."
remote_file host delete ${remote_python_file} remote_file host delete ${remote_python_file}

View file

@ -53,6 +53,33 @@ class ContainerPrinter:
def children(self): def children(self):
return self._iterator(self.val['elements'], self.val['len']) return self._iterator(self.val['elements'], self.val['len'])
# Test a printer where to_string is None
class NoStringContainerPrinter:
class _iterator:
def __init__ (self, pointer, len):
self.start = pointer
self.pointer = pointer
self.end = pointer + len
def __iter__(self):
return self
def next(self):
if self.pointer == self.end:
raise StopIteration
result = self.pointer
self.pointer = self.pointer + 1
return ('[%d]' % int (result - self.start), result.dereference())
def __init__(self, val):
self.val = val
def to_string(self):
return None
def children(self):
return self._iterator(self.val['elements'], self.val['len'])
class pp_s: class pp_s:
def __init__(self, val): def __init__(self, val):
self.val = val self.val = val
@ -190,8 +217,10 @@ def register_pretty_printers ():
# both the C and C++ cases. # both the C and C++ cases.
pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print
pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter
pretty_printers_dict[re.compile ('^struct justchildren$')] = NoStringContainerPrinter
pretty_printers_dict[re.compile ('^string_repr$')] = string_print pretty_printers_dict[re.compile ('^string_repr$')] = string_print
pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter
pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns
pretty_printers_dict[re.compile ('^ns$')] = pp_ns pretty_printers_dict[re.compile ('^ns$')] = pp_ns