public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-pmuldoon-python-backtrace: Add initial support for -stack-list-variables.  Rewrite locals and argument aquisition and prining to account for the combined nature of -stack-list-variables
@ 2012-08-14 15:38 pmuldoon
  0 siblings, 0 replies; only message in thread
From: pmuldoon @ 2012-08-14 15:38 UTC (permalink / raw)
  To: archer-commits

The branch, archer-pmuldoon-python-backtrace has been updated
       via  12f3ffcbc3530fb011af47e03f6dabfb96f42147 (commit)
      from  ee73819ce0a91fd1e20670770445f5a50d7d7ec6 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 12f3ffcbc3530fb011af47e03f6dabfb96f42147
Author: Phil Muldoon <pmuldoon@redhat.com>
Date:   Tue Aug 14 16:37:49 2012 +0100

    Add initial support for -stack-list-variables.  Rewrite locals and
    argument aquisition and prining to account for the combined nature of
    -stack-list-variables

-----------------------------------------------------------------------

Summary of changes:
 gdb/mi/mi-cmd-stack.c        |   44 +++-
 gdb/python/py-framefilter.c  |  563 ++++++++++++++++++++++++------------------
 gdb/python/py-utils.c        |   27 ++
 gdb/python/python-internal.h |    1 +
 4 files changed, 395 insertions(+), 240 deletions(-)

First 500 lines of diff:
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 92ab4c2..f3e1309 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -353,13 +353,49 @@ void
 mi_cmd_stack_list_variables (char *command, char **argv, int argc)
 {
   struct frame_info *frame;
+  int raw_arg = 0;
+  int result = 0;
 
-  if (argc != 1)
-    error (_("Usage: PRINT_VALUES"));
+  if (argc == 2)
+    {
+      int j;
+      /* Find 'raw-frames' at argv[1] if passed as an argument */
+      for (j = 0; j < strlen (argv[1]); j++)
+	argv[1][j] = tolower (argv[1][j]);
 
-  frame = get_selected_frame (NULL);
+      if (subset_compare (argv[1], "raw-frames"))
+	raw_arg = 1;
+    }
 
-  list_args_or_locals (all, parse_print_values (argv[0]), frame);
+  if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg)
+      || (argc == 1 && raw_arg))
+    error (_("-stack-list-arguments: Usage: PRINT_VALUES [RAW-FRAMES]"));
+
+   frame = get_selected_frame (NULL);
+
+   if (! raw_arg && frame_filters)
+     {
+       int count = 1;
+       int arg = atoi (argv[0]);
+
+       result = apply_frame_filter (frame,/* frame */
+				    1, /* print_level */
+				    LOC_AND_ADDRESS, /* print_what */
+				    0, /* print_frame_info */
+				    1, /* print_args */
+				    arg, /* mi_print_args_type */
+				    0, /* cli_print_args_type */
+				    current_uiout, /* out */
+				    1, /* print_locals */
+				    count /* count */);
+     }
+
+   if (! frame_filters || raw_arg || result == PY_BT_ERROR
+       || result == PY_BT_NO_FILTERS)
+     {
+
+       list_args_or_locals (all, parse_print_values (argv[0]), frame);
+     }
 }
 
 /* Print single local or argument.  ARG must be already read in.  For
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index 14217f3..fd6e26e 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -34,11 +34,21 @@
 #ifdef HAVE_PYTHON
 #include "python-internal.h"
 
-static int
-extract_sym_and_value (PyObject *obj, char **name,
-		       struct value **value,
-		       const struct language_defn **language)
+/* Helper function to extract a name, value and language definition
+   from a Python object that conforms SymbolValue interface.  OBJ is
+   the Python object to extract the values from.  **NAME is a
+   pass-through argument where the name of the symbol will be written.
+   **VALUE is a pass-through argument where the value corresponding
+   the to the Symbol will be written, and LANGUAGE is also a
+   pass-through argument denoting the language attributed to the
+   Symbol.  Returns 0 on error with the appropriate Python exception
+   set, and 1 on success.  */
+
+static int extract_sym_and_value (PyObject *obj,
+				  char **name, struct value **value,
+				  const struct language_defn **language)
 {
+
   if (PyObject_HasAttrString (obj, "symbol"))
     {
       PyObject *result = PyObject_CallMethod (obj, "symbol", NULL);
@@ -62,6 +72,7 @@ extract_sym_and_value (PyObject *obj, char **name,
 	  struct symbol *symbol = symbol_object_to_symbol (result);
 
 	  Py_DECREF (result);
+
 	  if (! symbol)
 	    {
 	      PyErr_SetString (PyExc_RuntimeError,
@@ -112,12 +123,16 @@ extract_sym_and_value (PyObject *obj, char **name,
 			 "implemented."));
       return 0;
     }
+
   return 1;
 }
 
+/* Helper function which outputs a type name to a stream.  OUT is the
+   ui-out structure the type name will be output too, and VAL is the
+   value that the type will be extracted from.  Returns 0 on error,
+   with any GDB exceptions converted to a Python exception.  */
 static int
-py_print_type (struct ui_out *out,
-	       struct value *val)
+py_print_type (struct ui_out *out, struct value *val)
 {
   volatile struct gdb_exception except;
 
@@ -140,132 +155,318 @@ py_print_type (struct ui_out *out,
 		       except.message);
       return 0;
     }
-
   return 1;
 }
 
+/* Helper function which outputs a value name to a stream.  OUT is the
+   ui-out structure the value will be output too, and VAL is the value
+   that will be printed.  LANGUAGE is the language_defn that the value
+   will be printed with.  Returns 0 on error, with any GDB exceptions
+   converted to a Python exception.  */
+
 static int
-py_print_locals (PyObject *filter,
-		 struct ui_out *out,
-		 struct value_print_options opts,
-		 int mi_print_type,
-		 int indent)
+py_print_value (struct ui_out *out, struct value *val,
+		const struct language_defn *language)
 {
-  /* In traditional bt full backtraces this is num_tabs (4) * 2 = 8.  It
-     never appears to deviate from this.  */
-  struct cleanup *old_chain = make_cleanup_ui_out_list_begin_end (out,
-								  "locals");
+  volatile struct gdb_exception except;
 
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      struct ui_file *stb;
+      struct cleanup *cleanup;
+      struct value_print_options opts;
 
-  if (PyObject_HasAttrString (filter, "frame_locals"))
+      stb = mem_fileopen ();
+      cleanup = make_cleanup_ui_file_delete (stb);
+      get_user_print_options (&opts);
+      opts.deref_ref = 1;
+      common_val_print (val, stb, 2, &opts, language);
+      ui_out_field_stream (out, "value", stb);
+      do_cleanups (cleanup);
+    }
+  if (except.reason > 0)
     {
-      PyObject *result = PyObject_CallMethod (filter, "frame_locals",
-					      NULL);
+      PyErr_SetString (PyExc_RuntimeError,
+		       except.message);
+      return 0;
+    }
+  return 1;
+}
+
+/* Helper function to call a Python method and extract an iterator
+   from the result, error checking for Python exception and returns
+   that are not iterators.  FILTER is the Python object to call, and
+   FUNC is the name of the method.  Returns a PyObject, or NULL on
+   error with the appropriate exception set.  */
+
+static PyObject *
+get_py_iter_from_func (PyObject *filter, char *func)
+{
+  if (PyObject_HasAttrString (filter, func))
+    {
+      PyObject *result = PyObject_CallMethod (filter, func, NULL);
 
       if (result)
 	{
-	  make_cleanup_py_decref (result);
-
 	  if (result != Py_None)
 	    {
 	      if (! PyIter_Check (result))
 		{
 		  PyErr_SetString (PyExc_RuntimeError,
-				   _("'frame_locals' function must " \
-				     "return  an iterator."));
-		  goto locals_error;
+				   strcat (func, _(" function must "	\
+						   "return an iterator.")));
+		  Py_DECREF (result);
+		  return NULL;
 		}
 	      else
 		{
 		  PyObject *iterator = PyObject_GetIter (result);
-		  PyObject *item;
+
+		  Py_DECREF (result);
 
 		  if (! iterator)
-		    goto locals_error;
+		    return NULL;
+		  else
+		    return iterator;
+		}
+	    }
+	}
+      else
+	return NULL;
+    }
 
-		  make_cleanup_py_decref (iterator);
-		  while ((item = PyIter_Next (iterator)))
-		    {
-		      const struct language_defn *language;
-		      char *sym_name;
-		      struct value *val;
-		      int value_success = 0;
-		      volatile struct gdb_exception except;
-		      struct cleanup *inner_cleanup =
-			make_cleanup (null_cleanup, NULL);
-
-		      value_success = extract_sym_and_value (item, &sym_name,
-							     &val,
-							     &language);
+    Py_RETURN_NONE;
+}
 
-		      Py_DECREF (item);
+static int
+enumerate_args (PyObject *iter,
+		struct ui_out *out,
+		struct value_print_options opts,
+		int mi_print_type,
+		const char *print_args_type,
+		int print_mi_args_flag)
+{
+  PyObject *item;
 
-		      if (! value_success)
-			goto locals_error;
-
-		      if (ui_out_is_mi_like_p (out))
-			{
-			  if (mi_print_type != PRINT_NO_VALUES)
-			    {
-			      inner_cleanup =
-				make_cleanup_ui_out_tuple_begin_end (out,
-								     NULL);
-			    }
-			}
-		      else
-			ui_out_spaces (out, (8 + (indent * 2)));
-
-		      ui_out_field_string (out, "name", sym_name);
-		      xfree (sym_name);
-
-		      if (! ui_out_is_mi_like_p (out))
-			ui_out_text (out, " = ");
-
-		      if (ui_out_is_mi_like_p (out)
-			  && mi_print_type == PRINT_SIMPLE_VALUES)
-			{
-			  if (! py_print_type (out, val))
-			    goto locals_error;
-			}
-
-		      if (! ui_out_is_mi_like_p (out)
-			  || (ui_out_is_mi_like_p (out)
-			      && mi_print_type != PRINT_NO_VALUES))
-			{
-			  struct ui_file *stb;
-			  stb = mem_fileopen ();
-			  make_cleanup_ui_file_delete (stb);
-
-			  TRY_CATCH (except, RETURN_MASK_ALL)
-			    {
-			      get_user_print_options (&opts);
-			      opts.deref_ref = 1;
-			      common_val_print (val, stb, 2, &opts, language);
-			    }
-			  if (except.reason > 0)
-			    {
-			      PyErr_SetString (PyExc_RuntimeError,
-					       except.message);
-			      goto locals_error;
-			    }
-
-			  ui_out_field_stream (out, "value", stb);
-			}
-
-		      ui_out_text (out, "\n");
-		      do_cleanups (inner_cleanup);
+  annotate_frame_args ();
 
-		    }
+  item = PyIter_Next (iter);
+  if (! item && PyErr_Occurred ())
+    goto error;
 
-		  if (! item && PyErr_Occurred())
-		    goto locals_error;
-		}
+  while (item)
+    {
+      const struct language_defn *language;
+      char *sym_name;
+      struct value *val;
+      int value_success = 0;
+      volatile struct gdb_exception except;
+      struct cleanup *inner_cleanup =
+	make_cleanup (null_cleanup, NULL);
+
+      value_success = extract_sym_and_value (item,
+					     &sym_name,
+					     &val,
+					     &language);
+      Py_DECREF (item);
+      item = NULL;
+
+      if (! value_success)
+	goto error;
+
+      if (ui_out_is_mi_like_p (out))
+	{
+	  if(mi_print_type != PRINT_NO_VALUES)
+	    {
+	      inner_cleanup =
+		make_cleanup_ui_out_tuple_begin_end (out,
+						     NULL);
+	    }
+	}
+
+      annotate_arg_begin ();
+      ui_out_field_string (out, "name", sym_name);
+
+      if (! ui_out_is_mi_like_p (out))
+	ui_out_text (out, "=");
+
+      if (print_mi_args_flag)
+	ui_out_field_int (out, "arg", 1);
+
+      annotate_arg_value (value_type (val));
+      opts.deref_ref = 1;
+
+      if (ui_out_is_mi_like_p (out)
+	  && mi_print_type == PRINT_SIMPLE_VALUES)
+	{
+	  py_print_type (out, val);
+	}
+
+      if (! ui_out_is_mi_like_p (out))
+	{
+	  opts.summary = !strcmp (print_args_type, "scalars");
+	}
+
+      if (! ui_out_is_mi_like_p (out)
+	  || (ui_out_is_mi_like_p (out)
+	      && mi_print_type != PRINT_NO_VALUES))
+	{
+	  py_print_value (out, val, language);
+	}
+
+      do_cleanups (inner_cleanup);
+
+      /* Collect the next item from the iterator.  If
+	 this is the last item, we do not print the
+	 ",".  */
+      item = PyIter_Next (iter);
+      if (item)
+	ui_out_text (out, ", ");
+      else
+	if (PyErr_Occurred ())
+	  goto error;
+
+      annotate_arg_end ();
+    }
+
+  return 1;
+
+ error:
+  return 0;
+}
+
+static int
+enumerate_locals (PyObject *iter,
+		 struct ui_out *out,
+		 struct value_print_options opts,
+		 int mi_print_type,
+		 int indent)
+{
+  PyObject *item;
+
+  while ((item = PyIter_Next (iter)))
+    {
+      const struct language_defn *language;
+      char *sym_name;
+      struct value *val;
+      int value_success = 0;
+      volatile struct gdb_exception except;
+      struct cleanup *inner_cleanup =
+	make_cleanup (null_cleanup, NULL);
+
+      value_success = extract_sym_and_value (item, &sym_name,
+					     &val,
+					     &language);
+
+      Py_DECREF (item);
+
+      if (! value_success)
+	goto error;
+
+      if (ui_out_is_mi_like_p (out))
+	{
+	  if (mi_print_type != PRINT_NO_VALUES)
+	    {
+	      inner_cleanup =
+		make_cleanup_ui_out_tuple_begin_end (out,
+						     NULL);
 	    }
 	}
       else
-	goto locals_error;
+	ui_out_spaces (out, (8 + (indent * 2)));
+
+      ui_out_field_string (out, "name", sym_name);
+      xfree (sym_name);
+
+      if (! ui_out_is_mi_like_p (out))
+	ui_out_text (out, " = ");
+
+      if (ui_out_is_mi_like_p (out)
+	  && mi_print_type == PRINT_SIMPLE_VALUES)
+	{
+	  if (! py_print_type (out, val))
+	    goto error;
+	}
+
+      if (! ui_out_is_mi_like_p (out)
+	  || (ui_out_is_mi_like_p (out)
+	      && mi_print_type != PRINT_NO_VALUES))
+	{
+	  py_print_value (out, val, language);
+	}
+
+      ui_out_text (out, "\n");
+      do_cleanups (inner_cleanup);
     }
 
+  if (! item && PyErr_Occurred())
+    goto error;
+
+ done:
+  return 1;
+
+ error:
+  return 0;
+}
+
+static int
+py_mi_print_variables (PyObject *filter, struct ui_out *out,
+		       struct value_print_options opts,
+		       int mi_print_type, const char *print_args_type)
+{
+  struct cleanup *old_chain;
+  PyObject *args_iter;
+  PyObject *locals_iter;
+
+  args_iter = get_py_iter_from_func (filter, "frame_args");
+  old_chain = make_cleanup_py_xdecref (args_iter);
+  if (! args_iter)
+    goto error;
+
+  locals_iter = get_py_iter_from_func (filter, "frame_locals");
+  if (! locals_iter)
+    goto error;
+
+  make_cleanup_py_decref (locals_iter);
+  make_cleanup_ui_out_list_begin_end (out, "variables");
+
+  if (args_iter != Py_None)
+      if (! enumerate_args (args_iter, out, opts, mi_print_type,
+			    print_args_type, 1))
+	goto error;
+
+  if (locals_iter != Py_None)
+    if (! enumerate_locals (locals_iter, out, opts,
+			    mi_print_type, 0))
+      goto error;
+
+  do_cleanups (old_chain);
+  return 1;


hooks/post-receive
--
Repository for Project Archer.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2012-08-14 15:38 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-14 15:38 [SCM] archer-pmuldoon-python-backtrace: Add initial support for -stack-list-variables. Rewrite locals and argument aquisition and prining to account for the combined nature of -stack-list-variables pmuldoon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).