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]

[python][patch] PR pyton/11381


This patch address PR 11381. Briefly there are cases when only
children should be printed in a pretty-printer.  This patch allows the
printer's 'to_string' method to return the Python "None".  If this is
the case, the GDB pretty-printers will print nothing in place of
to_string and also alter the preceding text slightly, stripping off
leading spaces and the '=" text.

For some reason this patch really looks messy in print_string_repr.
The impact to this function is not great, but because of juggling some
else clauses/re-indenting it generates an ugly and hard to read patch.
Apologies for this, I tried to persuade git to produce something nicer
to no avail!


Test on x86_64 with no regressions.  OK?

Cheers,

Phil

ChangeLog

2010-04-08  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.

Doc ChangeLog

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

	* gdb.texinfo (Pretty Printing): Document behaviour when to_string
	returns None.

2010-04-08  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 fro to_string returning None.

-- 

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index fd8b0bc..cbadec2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -20424,6 +20424,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 performed in this function 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..03858e8 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 returned 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,6 +196,7 @@ 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)
@@ -199,42 +207,46 @@ print_string_repr (PyObject *printer, const char *hint,
       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)
+	  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);
+	    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)
     {
@@ -245,6 +257,8 @@ print_string_repr (PyObject *printer, const char *hint,
     }
   else
     gdbpy_print_stack ();
+
+  return is_py_none;
 }
 
 static void
@@ -323,12 +337,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 +424,12 @@ 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 +553,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 +578,9 @@ 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-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c
index e1f696f..08f58c1 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.c
+++ b/gdb/testsuite/gdb.python/py-prettyprint.c
@@ -109,6 +109,14 @@ substruct_test (void)
   return outer;  
 }
 
+struct justchildren
+{
+  int *elements;
+  int len;
+};
+
+typedef struct justchildren nostring_type;
+
 typedef struct string_repr
 {
   struct whybother
@@ -196,7 +204,10 @@ 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 = array;
+  nstype.len = 0;
+  nstype.len = 2;
 
   init_ss(&ss, 1, 2);
   init_ss(ssa+0, 3, 4);
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
index 414362b..f56af89 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. = 23,$nl *.1. = 72$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


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