This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [python][patch] PR pyton/11381
- From: Phil Muldoon <pmuldoon at redhat dot com>
- To: tromey at redhat dot com
- Cc: gdb-patches ml <gdb-patches at sourceware dot org>
- Date: Tue, 13 Apr 2010 16:05:16 +0100
- Subject: Re: [python][patch] PR pyton/11381
- References: <4BBE1073.40703@redhat.com> <m3iq80ocdu.fsf@fleche.redhat.com>
On 04/09/2010 04:48 PM, Tom Tromey wrote:
>>>>>> "Phil" == Phil Muldoon <pmuldoon@redhat.com> writes:
> Phil> children should be printed in a pretty-printer. This patch allows the
> Phil> printer's 'to_string' method to return the Python "None". If this is
> Phil> the case, the GDB pretty-printers will print nothing in place of
> Phil> to_string and also alter the preceding text slightly, stripping off
> Phil> leading spaces and the '=" text.
>
> What should happen if to_string returns None but there is no children
> method?
>
> I think we should not worry about corner cases like this, but even so we
> should explicitly decide that.
With this patch if the 'to_string' method returns 'None', and there is no
'children' method, nothing will be output following the standard
"$x = " prefix.
(gdb) p nstype
$2 =
If there is a 'children' method but the 'to_string' returns 'None' you
will just get the children:
(gdb) p nstype
$2 = {
[0] = 7,
[1] = 42
}
I'm not sure what to do in the 'to_string' returns 'None' and the
missing 'children' method above. It's obviously a bogus pretty
printers that outputs nothing at all, and the '$x = ' gets appended
to the stream before the Python pretty-printers assume control. I'm
open to ideas.
> Does the varobj code do something sensible when to_string returns None?
> I think there should be a test for this.
Yes, added.
> Phil> + is_py_none = print_string_repr (printer, hint, stream, recurse, options, language,
> Phil> + gdbarch);
> Phil> + print_children (printer, hint, stream, recurse, options, language, is_py_none);
>
> These lines look like they wrap now.
OK.
Cheers,
Phil
--
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 887547b..104a1ec 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -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
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.
@end defop
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index 454aa5a..5c3757c 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -125,9 +125,12 @@ find_pretty_printer (PyObject *value)
/* Pretty-print a single value, via the printer object PRINTER.
If the function returns a string, a PyObject containing the string
- is returned. Otherwise, if the 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. */
+ is returned. If the function returns Py_NONE that means the pretty
+ printer returned the Python None as a value. Otherwise, if the
+ 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 *
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);
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);
if (PyErr_Occurred ())
@@ -179,8 +183,11 @@ gdbpy_get_display_hint (PyObject *printer)
}
/* Helper for apply_val_pretty_printer which calls to_string and
- formats the result. */
-static void
+ formats the result. If the value returnd is Py_None, nothing is
+ 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,
struct ui_file *stream, int recurse,
const struct value_print_options *options,
@@ -189,52 +196,58 @@ print_string_repr (PyObject *printer, const char *hint,
{
struct value *replacement = NULL;
PyObject *py_str = NULL;
+ int is_py_none = 0;
py_str = pretty_print_one_value (printer, &replacement);
if (py_str)
{
- gdb_byte *output = NULL;
- 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);
+ if (py_str == Py_None)
+ is_py_none = 1;
else
{
- string = python_string_to_target_python_string (py_str);
- if (string)
+ gdb_byte *output = NULL;
+ 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);
- length = PyString_Size (string);
- type = builtin_type (gdbarch)->builtin_char;
+ string = python_string_to_target_python_string (py_str);
+ if (string)
+ {
+ 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
gdbpy_print_stack ();
- }
-
- if (output)
- {
- if (is_lazy || (hint && !strcmp (hint, "string")))
- LA_PRINT_STRING (stream, type, output, length, encoding,
- 0, options);
+ if (string)
+ Py_DECREF (string);
else
- fputs_filtered (output, stream);
- }
- else
- gdbpy_print_stack ();
+ xfree (output);
- if (string)
- Py_DECREF (string);
- else
- xfree (output);
-
- xfree (encoding);
- Py_DECREF (py_str);
+ xfree (encoding);
+ Py_DECREF (py_str);
+ }
}
else if (replacement)
{
@@ -245,6 +258,8 @@ print_string_repr (PyObject *printer, const char *hint,
}
else
gdbpy_print_stack ();
+
+ return is_py_none;
}
static void
@@ -323,12 +338,14 @@ push_dummy_python_frame ()
}
/* 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
print_children (PyObject *printer, const char *hint,
struct ui_file *stream, int recurse,
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;
unsigned int i;
@@ -408,7 +425,13 @@ print_children (PyObject *printer, const char *hint,
2. Arrays. Always print a ",".
3. Other. Always print a ",". */
if (i == 0)
- fputs_filtered (" = {", stream);
+ {
+ if (is_py_none)
+ fputs_filtered ("{", stream);
+ else
+ fputs_filtered (" = {", stream);
+ }
+
else if (! is_map || i % 2 == 0)
fputs_filtered (pretty ? "," : ", ", stream);
@@ -532,7 +555,7 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
char *hint = NULL;
struct cleanup *cleanups;
int result = 0;
-
+ int is_py_none = 0;
cleanups = ensure_python_env (gdbarch, language);
/* Instantiate the printer. */
@@ -557,9 +580,11 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
make_cleanup (free_current_contents, &hint);
/* Print the section */
- print_string_repr (printer, hint, stream, recurse, options, language,
- gdbarch);
- print_children (printer, hint, stream, recurse, options, language);
+ is_py_none = print_string_repr (printer, hint, stream, recurse,
+ options, language, gdbarch);
+ print_children (printer, hint, stream, recurse, options, language,
+ is_py_none);
+
result = 1;
diff --git a/gdb/testsuite/gdb.python/py-mi.exp b/gdb/testsuite/gdb.python/py-mi.exp
index 6589a62..973ff85 100644
--- a/gdb/testsuite/gdb.python/py-mi.exp
+++ b/gdb/testsuite/gdb.python/py-mi.exp
@@ -61,6 +61,16 @@ mi_list_varobj_children container {
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_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_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}
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c
index e1f696f..f461bb1 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.c
+++ b/gdb/testsuite/gdb.python/py-prettyprint.c
@@ -119,6 +119,15 @@ typedef struct string_repr
/* This lets us avoid malloc. */
int array[100];
+int narray[10];
+
+struct justchildren
+{
+ int len;
+ int *elements;
+};
+
+typedef struct justchildren nostring_type;
struct container
{
@@ -196,7 +205,9 @@ main ()
const struct string_repr cstring = { { "const string" } };
/* Clearing by being `static' could invoke an other GDB C++ bug. */
struct nullstr nullstr;
-
+ nostring_type nstype;
+ nstype.elements = narray;
+ nstype.len = 0;
init_ss(&ss, 1, 2);
init_ss(ssa+0, 3, 4);
@@ -249,5 +260,9 @@ main ()
do_nothing ();
#endif
+ nstype.elements[0] = 7;
+ nstype.elements[1] = 42;
+ nstype.len = 2;
+
return 0; /* break to inspect struct and union */
}
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
index 414362b..2c14c59 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/py-prettyprint.exp
@@ -101,6 +101,7 @@ proc run_lang_tests {lang} {
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 nstype" " = {$nl *.0. = 7,$nl *.1. = 42$nl}"
gdb_test "continue" "Program exited normally\."
remote_file host delete ${remote_python_file}
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.py b/gdb/testsuite/gdb.python/py-prettyprint.py
index 979d4ad..44bfc49 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.py
+++ b/gdb/testsuite/gdb.python/py-prettyprint.py
@@ -53,6 +53,33 @@ class ContainerPrinter:
def children(self):
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:
def __init__(self, val):
self.val = val
@@ -190,8 +217,10 @@ def register_pretty_printers ():
# both the C and C++ cases.
pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print
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 ('^container$')] = ContainerPrinter
+ pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter
pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns
pretty_printers_dict[re.compile ('^ns$')] = pp_ns