public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands
@ 2013-07-03  1:48 Yao Qi
  2013-07-03  1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
                   ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: Yao Qi @ 2013-07-03  1:48 UTC (permalink / raw)
  To: gdb-patches

Hi,
This patch series add new option '--skip-unavailable' to MI commands
'-stack-list-{locals, arguments, variables}'.  This option is optional,
and when it is used, locals or arguments whose values are not available
are not listed.  It is useful when the MI front-end is not interested in
unavailable values.

The patch 1/2 is a refactor patch, use mi_getopt in
mi_cmd_stack_list_locals and mi_cmd_stack_list_variables, so it is
easier to add new option patch 2/2.  Patch 2/2 is the major part of this
series.

Regression tested on x86_64-linux.

Note that this patch is for MI, but the idea that skipping unavailable
locals and arguments can be applied to CLI too.  We can invent new CLI
commands on top of 'info locals' and 'info args' to display available
locals or arguments.  This piece of work is not included in this
series.

*** BLURB HERE ***

Yao Qi (2):
  Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables
  Add options to skip unavailable locals

 gdb/doc/gdb.texinfo                              |   17 ++-
 gdb/mi/mi-cmd-stack.c                            |  256 ++++++++++++++++------
 gdb/testsuite/gdb.trace/mi-trace-unavailable.exp |    9 +
 gdb/valprint.c                                   |    8 +-
 gdb/valprint.h                                   |    2 +
 gdb/value.c                                      |   20 ++
 gdb/value.h                                      |    4 +
 7 files changed, 246 insertions(+), 70 deletions(-)

-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 2/2] Add options to skip unavailable locals
  2013-07-03  1:48 [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi
@ 2013-07-03  1:48 ` Yao Qi
  2013-07-03  4:14   ` asmwarrior
  2013-07-03 19:22   ` Eli Zaretskii
  2013-07-03  1:48 ` [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables Yao Qi
  2013-07-29  9:33 ` [ping]: [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi
  2 siblings, 2 replies; 26+ messages in thread
From: Yao Qi @ 2013-07-03  1:48 UTC (permalink / raw)
  To: gdb-patches

This is the patch to add new option '--skip-unavailable' to MI
commands '-stack-list-{locals, arguments, variables}'.  This patch
extends list_args_or_locals to add a new parameter 'skip_unavailable',
and don't list locals or arguments if values are unavailable and
'skip_unavailable' is true.

This is inspecting a trace frame (tfind mode), where only a few
locals have been collected.

-stack-list-locals, no switch vs new switch:

 -stack-list-locals --simple-values
 ^done,locals=[{name="array",type="unsigned char [2]"},{name="i",type="int",value="<unavailable>"}]
 -stack-list-locals --skip-unavailable --simple-values
 ^done,locals=[{name="array",type="unsigned char [2]"}]

-stack-list-arguments, no switch vs new switch:

 -stack-list-arguments --simple-values
 ^done,stack-args=[frame={level="0",args=[{name="j",type="int",value="4"},{name="s",type="char *",value="<unavailable>"}]},frame={level="1",args=[]}]
 -stack-list-arguments --skip-unavailable --simple-values
 ^done,stack-args=[frame={level="0",args=[{name="j",type="int",value="4"}]},frame={level="1",args=[]}]

-stack-list-variables, no switch vs new switch:

 -stack-list-variables --simple-values
 ^done,variables=[{name="j",arg="1",type="int",value="4"},{name="s",arg="1",type="char *",value="<unavailable>"},{name="array",type="unsigned char [2]"},{name="i",type="int",value="<unavailable>"}]
 -stack-list-variables --skip-unavailable --simple-values
 ^done,variables=[{name="j",arg="1",type="int",value="4"},{name="array",type="unsigned char [2]"}]

tests are added to test these new options.

gdb:

2013-07-03  Pedro Alves  <pedro@codesourcery.com>
	    Yao Qi  <yao@codesourcery.com>

	* mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype.
	(parse_no_frames_option): Remove.
	(mi_cmd_stack_list_locals): Handle --skip-unavailable.
	(mi_cmd_stack_list_args): Adjust.
	(mi_cmd_stack_list_variables): Handle --skip-unavailable.
	(list_args_or_locals): New parameter 'skip_unavailable'.
	Handle it.
	* valprint.c (scalar_type_p): Rename to ...
	(val_print_scalar_type_p): ... this.  Make extern.
	(val_print, value_check_printable): Adjust.
	* valprint.h (val_print_scalar_type_p): Declare.
	* value.c (value_entirely_unavailable): New function.
	* value.h (value_entirely_unavailable): Declare.

	* NEWS: Mention the new option "--skip-unavailable" to these
	MI commands.

gdb/doc:

2013-07-03  Pedro Alves  <pedro@codesourcery.com>
	    Yao Qi  <yao@codesourcery.com>

	* gdb.texinfo (GDB/MI Stack Manipulation)<-stack-list-locals>:
	Document new --skip-unavailable option.
	<-stack-list-arguments>: Likewise.
	<-stack-list-variables>: Likewise.

gdb/testsuite:

2013-07-03  Yao Qi  <yao@codesourcery.com>

	* gdb.trace/mi-trace-unavailable.exp (test_trace_unavailable):
	Add tests for new option '--skip-unavailable'.
---
 gdb/NEWS                                         |    5 +
 gdb/doc/gdb.texinfo                              |   17 ++-
 gdb/mi/mi-cmd-stack.c                            |  161 ++++++++++++++--------
 gdb/testsuite/gdb.trace/mi-trace-unavailable.exp |    9 ++
 gdb/valprint.c                                   |    8 +-
 gdb/valprint.h                                   |    2 +
 gdb/value.c                                      |   20 +++
 gdb/value.h                                      |    4 +
 8 files changed, 164 insertions(+), 62 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index e469f1e..8309c8b 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -84,6 +84,11 @@ show range-stepping
   ** The new command -trace-frame-collected dumps collected variables,
      computed expressions, tvars, memory and registers in a traceframe.
 
+  ** The commands -stack-list-locals, -stack-list-arguments and
+     -stack-list-variables now accept an optional "--skip-unavailable"
+     option.  When used, only the available locals or arguments are
+     displayed.
+
 * New system-wide configuration scripts
   A GDB installation now provides scripts suitable for use as system-wide
   configuration scripts for the following systems:
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index d75a3d1..790c9d2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -31242,7 +31242,7 @@ For a stack with frame levels 0 through 11:
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-arguments [ --no-frame-filters ] @var{print-values}
+ -stack-list-arguments [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
     [ @var{low-frame} @var{high-frame} ]
 @end smallexample
 
@@ -31262,6 +31262,9 @@ type and value for simple data types, and the name and type for arrays,
 structures and unions.  If the option @code{--no-frame-filters} is
 supplied, then Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, arguments that
+have not been available are not listed.  Partially available objects
+are still displayed, however.
 
 Use of this command to obtain arguments in a single frame is
 deprecated in favor of the @samp{-stack-list-variables} command.
@@ -31446,7 +31449,7 @@ Show a single frame:
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-locals [ --no-frame-filters ] @var{print-values}
+ -stack-list-locals [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
 @end smallexample
 
 Display the local variable names for the selected frame.  If
@@ -31460,6 +31463,10 @@ other data types when the user wishes to explore their values in
 more detail.  If the option @code{--no-frame-filters} is supplied, then
 Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, local variables
+that have not been available are not listed.  Partially available
+objects are still displayed, however.
+
 This command is deprecated in favor of the
 @samp{-stack-list-variables} command.
 
@@ -31490,7 +31497,7 @@ This command is deprecated in favor of the
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-variables [ --no-frame-filters ] @var{print-values}
+ -stack-list-variables [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
 @end smallexample
 
 Display the names of local variables and function arguments for the selected frame.  If
@@ -31501,6 +31508,10 @@ type and value for simple data types, and the name and type for arrays,
 structures and unions.  If the option @code{--no-frame-filters} is
 supplied, then Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, then, local
+variables and arguments that have not been collected are not listed.
+Partially available objects are still displayed, however.
+
 @subsubheading Example
 
 @smallexample
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 3212c03..1c0464d 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -39,9 +39,10 @@
 
 enum what_to_list { locals, arguments, all };
 
-static void list_args_or_locals (enum what_to_list what, 
+static void list_args_or_locals (enum what_to_list what,
 				 enum print_values values,
-				 struct frame_info *fi);
+				 struct frame_info *fi,
+				 int skip_unavailable);
 
 /* True if we want to allow Python-based frame filters.  */
 static int frame_filters = 0;
@@ -54,17 +55,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc)
   frame_filters = 1;
 }
 
-/* Parse the --no-frame-filters option in commands where we cannot use
-   mi_getopt. */
-static int
-parse_no_frames_option (const char *arg)
-{
-  if (arg && (strcmp (arg, "--no-frame-filters") == 0))
-    return 1;
-
-  return 0;
-}
-
 /* Print a list of the stack frames.  Args can be none, in which case
    we want to print the whole backtrace, or a pair of numbers
    specifying the frame numbers at which to start and stop the
@@ -213,6 +203,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
   int oind = 0;
+  int skip_unavailable = 0;
+  int i;
 
   if (argc > 1)
     {
@@ -221,11 +213,13 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
       char **new_argv = xmalloc ((argc - 1) * sizeof (char *));
       enum opt
       {
-	NO_FRAME_FILTERS
+	NO_FRAME_FILTERS,
+	SKIP_UNAVAILABLE,
       };
       static const struct mi_opt opts[] =
 	{
 	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
 	  { 0, 0, 0 }
 	};
 
@@ -249,6 +243,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
 	    {
 	    case NO_FRAME_FILTERS:
 	      raw_arg = oind;
+	    case SKIP_UNAVAILABLE:
+	      skip_unavailable = 1;
 	      break;
 	    }
 	}
@@ -258,7 +254,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   /* After the last option is parsed, there should be only
      'print-values'.  */
   if (argc - oind != 1)
-    error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES"));
+    error (_("-stack-list-locals: Usage: [--no-frame-filters] "
+	     "[--skip-unavailable] PRINT_VALUES"));
 
   frame = get_selected_frame (NULL);
   print_value = mi_parse_print_values (argv[oind]);
@@ -275,7 +272,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
       if "--no-frame-filters" has been specified from the command.  */
    if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
      {
-       list_args_or_locals (locals, print_value, frame);
+       list_args_or_locals (locals, print_value, frame,
+			    skip_unavailable);
      }
 }
 
@@ -295,18 +293,39 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
   struct ui_out *uiout = current_uiout;
   int raw_arg = 0;
   enum py_bt_status result = PY_BT_ERROR;
+  int skip_unavailable = 0;
+  int oind = 0;
 
-  if (argc > 0)
-    raw_arg = parse_no_frames_option (argv[0]);
+  /* We can't use mi_getopt here, because the number of options is not
+     determined.  */
+  for (oind = 0; oind < argc; oind++)
+    {
+      int found = 0;
 
-  if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg))
+      if (strcmp (argv[oind], "--no-frame-filters") == 0)
+	{
+	  raw_arg = oind + 1;
+	  found = 1;
+	}
+      else if (strcmp (argv[oind], "--skip-unavailable") == 0)
+	{
+	  skip_unavailable = 1;
+	  found = 1;
+	}
+
+      if (!found)
+	break;
+    }
+
+  if (argc - oind != 1 && argc - oind != 3)
     error (_("-stack-list-arguments: Usage: " \
-	     "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
+	     "[--no-frame-filters] [--skip-unavailable] "
+	     "PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
 
-  if (argc >= 3)
+  if (argc - oind == 3)
     {
-      frame_low = atoi (argv[1 + raw_arg]);
-      frame_high = atoi (argv[2 + raw_arg]);
+      frame_low = atoi (argv[1 + oind]);
+      frame_high = atoi (argv[2 + oind]);
     }
   else
     {
@@ -316,7 +335,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
       frame_high = -1;
     }
 
-  print_values = mi_parse_print_values (argv[raw_arg]);
+  print_values = mi_parse_print_values (argv[oind]);
 
   /* Let's position fi on the frame at which to start the
      display. Could be the innermost frame if the whole stack needs
@@ -362,7 +381,8 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
 	  QUIT;
 	  cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
 	  ui_out_field_int (uiout, "level", i);
-	  list_args_or_locals (arguments, print_values, fi);
+	  list_args_or_locals (arguments, print_values, fi,
+			       skip_unavailable);
 	  do_cleanups (cleanup_frame);
 	}
     }
@@ -382,6 +402,7 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
   int oind = 0;
+  int skip_unavailable = 0;
 
   if (argc > 1)
     {
@@ -390,11 +411,13 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
       char **new_argv = xmalloc ((argc - 1) * sizeof (char *));
       enum opt
       {
-	NO_FRAME_FILTERS
+	NO_FRAME_FILTERS,
+	SKIP_UNAVAILABLE,
       };
       static const struct mi_opt opts[] =
 	{
 	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
 	  { 0, 0, 0 }
 	};
       cleanup = make_cleanup (xfree, new_argv);
@@ -418,6 +441,9 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
 	    case NO_FRAME_FILTERS:
 	      raw_arg = oind;
 	      break;
+	    case SKIP_UNAVAILABLE:
+	      skip_unavailable = 1;
+	      break;
 	    }
 	}
       do_cleanups (cleanup);
@@ -426,8 +452,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   /* After the last option is parsed, there should be only
      'print-values'.  */
   if (argc - oind != 1)
-    error (_("-stack-list-variables: Usage: " \
-	     "[--no-frame-filters] PRINT_VALUES"));
+    error (_("-stack-list-variables: Usage: [--no-frame-filters] " \
+	     "[--skip-unavailable] PRINT_VALUES"));
 
    frame = get_selected_frame (NULL);
    print_value = mi_parse_print_values (argv[oind]);
@@ -444,7 +470,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
       if "--no-frame-filters" has been specified from the command.  */
    if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
      {
-       list_args_or_locals (all, print_value, frame);
+       list_args_or_locals (all, print_value, frame,
+			    skip_unavailable);
      }
 }
 
@@ -525,11 +552,12 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
 /* Print a list of the locals or the arguments for the currently
    selected frame.  If the argument passed is 0, printonly the names
    of the variables, if an argument of 1 is passed, print the values
-   as well.  */
+   as well.  If SKIP_UNAVAILABLE is true, print the arguments or local
+   variables whose values are available.  */
 
 static void
 list_args_or_locals (enum what_to_list what, enum print_values values,
-		     struct frame_info *fi)
+		     struct frame_info *fi, int skip_unavailable)
 {
   struct block *block;
   struct symbol *sym;
@@ -564,6 +592,7 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
       ALL_BLOCK_SYMBOLS (block, iter, sym)
 	{
           int print_me = 0;
+	  struct value *val = NULL;
 
 	  switch (SYMBOL_CLASS (sym))
 	    {
@@ -597,7 +626,6 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
 	  if (print_me)
 	    {
 	      struct symbol *sym2;
-	      struct frame_arg arg, entryarg;
 
 	      if (SYMBOL_IS_ARGUMENT (sym))
 		sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
@@ -607,33 +635,56 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
 		sym2 = sym;
 	      gdb_assert (sym2 != NULL);
 
-	      memset (&arg, 0, sizeof (arg));
-	      arg.sym = sym2;
-	      arg.entry_kind = print_entry_values_no;
-	      memset (&entryarg, 0, sizeof (entryarg));
-	      entryarg.sym = sym2;
-	      entryarg.entry_kind = print_entry_values_no;
-
-	      switch (values)
+	      /* Need to read the value before being able to determine
+		 whether its unavailable.  */
+	      if (values == PRINT_ALL_VALUES
+		  || values == PRINT_SIMPLE_VALUES
+		  || skip_unavailable)
+		val = read_var_value (sym2, fi);
+
+	      if (skip_unavailable
+		  && (value_entirely_unavailable (val)
+		      /* A scalar object that does not have all bits
+			 available is also considered unavailable,
+			 because all bits contribute to its
+			 representation.  */
+		      || (val_print_scalar_type_p (value_type (val))
+			  && !value_bytes_available (val,
+						     value_embedded_offset (val),
+						     TYPE_LENGTH (value_type (val))))))
+		;
+	      else
 		{
-		case PRINT_SIMPLE_VALUES:
-		  type = check_typedef (sym2->type);
-		  if (TYPE_CODE (type) != TYPE_CODE_ARRAY
-		      && TYPE_CODE (type) != TYPE_CODE_STRUCT
-		      && TYPE_CODE (type) != TYPE_CODE_UNION)
+		  struct frame_arg arg, entryarg;
+
+		  memset (&arg, 0, sizeof (arg));
+		  arg.sym = sym2;
+		  arg.entry_kind = print_entry_values_no;
+		  memset (&entryarg, 0, sizeof (entryarg));
+		  entryarg.sym = sym2;
+		  entryarg.entry_kind = print_entry_values_no;
+
+		  switch (values)
 		    {
-		case PRINT_ALL_VALUES:
-		      read_frame_arg (sym2, fi, &arg, &entryarg);
+		    case PRINT_SIMPLE_VALUES:
+		      type = check_typedef (sym2->type);
+		      if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+			  && TYPE_CODE (type) != TYPE_CODE_STRUCT
+			  && TYPE_CODE (type) != TYPE_CODE_UNION)
+			{
+			case PRINT_ALL_VALUES:
+			  read_frame_arg (sym2, fi, &arg, &entryarg);
+			}
+		      break;
 		    }
-		  break;
-		}
 
-	      if (arg.entry_kind != print_entry_values_only)
-		list_arg_or_local (&arg, what, values);
-	      if (entryarg.entry_kind != print_entry_values_no)
-		list_arg_or_local (&entryarg, what, values);
-	      xfree (arg.error);
-	      xfree (entryarg.error);
+		  if (arg.entry_kind != print_entry_values_only)
+		    list_arg_or_local (&arg, what, values);
+		  if (entryarg.entry_kind != print_entry_values_no)
+		    list_arg_or_local (&entryarg, what, values);
+		  xfree (arg.error);
+		  xfree (entryarg.error);
+		}
 	    }
 	}
 
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index 42f6e32..f147899 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -93,16 +93,25 @@ proc test_trace_unavailable { data_source } {
 	mi_gdb_test "-stack-list-locals --simple-values" \
 	    ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \
 	    "-stack-list-locals --simple-values"
+	mi_gdb_test "-stack-list-locals --skip-unavailable --simple-values" \
+	    ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \
+	    "-stack-list-locals --skip-unavailable --simple-values"
 
 	# Test MI command '-stack-list-arguments'.
 	mi_gdb_test "-stack-list-arguments --simple-values" \
 	    ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\},\{name=\"s\",type=\"char \\\*\",value=\"<unavailable>\"\}\\\]\},.*\}.*" \
 	    "-stack-list-arguments --simple-values"
+	mi_gdb_test "-stack-list-arguments --skip-unavailable --simple-values" \
+	    ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\}\\\]\},.*\}.*" \
+	    "-stack-list-arguments --skip-unavailable --simple-values"
 
 	# Test MI command '-stack-list-variables'.
 	mi_gdb_test "-stack-list-variables --simple-values" \
 	    ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"s\",arg=\"1\",type=\"char \\\*\",value=\"<unavailable>\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \
 	    "-stack-list-variables --simple-values"
+	mi_gdb_test "-stack-list-variables --skip-unavailable --simple-values" \
+	    ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \
+	    "-stack-list-variables --skip-unavailable --simple-values"
 
 	mi_gdb_test "-trace-find frame-number 1" \
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
diff --git a/gdb/valprint.c b/gdb/valprint.c
index bc21f4f..2368ea8 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -272,8 +272,8 @@ show_symbol_print (struct ui_file *file, int from_tty,
    we want to print scalar arguments, but not aggregate arguments.
    This function distinguishes between the two.  */
 
-static int
-scalar_type_p (struct type *type)
+int
+val_print_scalar_type_p (struct type *type)
 {
   CHECK_TYPEDEF (type);
   while (TYPE_CODE (type) == TYPE_CODE_REF)
@@ -767,7 +767,7 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 
   /* Handle summary mode.  If the value is a scalar, print it;
      otherwise, print an ellipsis.  */
-  if (options->summary && !scalar_type_p (type))
+  if (options->summary && !val_print_scalar_type_p (type))
     {
       fprintf_filtered (stream, "...");
       return;
@@ -799,7 +799,7 @@ value_check_printable (struct value *val, struct ui_file *stream,
 
   if (value_entirely_optimized_out (val))
     {
-      if (options->summary && !scalar_type_p (value_type (val)))
+      if (options->summary && !val_print_scalar_type_p (value_type (val)))
 	fprintf_filtered (stream, "...");
       else
 	val_print_optimized_out (stream);
diff --git a/gdb/valprint.h b/gdb/valprint.h
index 7baef2f..eeb0cc4 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -209,4 +209,6 @@ extern void generic_printstr (struct ui_file *stream, struct type *type,
 
 extern void output_command_const (const char *args, int from_tty);
 
+extern int val_print_scalar_type_p (struct type *type);
+
 #endif
diff --git a/gdb/value.c b/gdb/value.c
index fae8b98..a1b9742 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -352,6 +352,26 @@ value_entirely_available (struct value *value)
   return 0;
 }
 
+int
+value_entirely_unavailable (struct value *value)
+{
+  /* We can only tell whether the whole value is available when we try
+     to read it.  */
+  if (value->lazy)
+    value_fetch_lazy (value);
+
+  if (VEC_length (range_s, value->unavailable) == 1)
+    {
+      struct range *t = VEC_index (range_s, value->unavailable, 0);
+
+      if (t->offset == 0
+	  && t->length == TYPE_LENGTH (value_enclosing_type (value)))
+	return 1;
+    }
+
+  return 0;
+}
+
 void
 mark_value_bytes_unavailable (struct value *value, int offset, int length)
 {
diff --git a/gdb/value.h b/gdb/value.h
index 8a66aa4..c224f10 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -429,6 +429,10 @@ extern int value_bytes_available (const struct value *value,
    whole object is unavailable.  */
 extern int value_entirely_available (struct value *value);
 
+/* Like value_entirely_available, but return false if any byte in the
+   whole object is available.  */
+extern int value_entirely_unavailable (struct value *value);
+
 /* Mark VALUE's content bytes starting at OFFSET and extending for
    LENGTH bytes as unavailable.  */
 
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables
  2013-07-03  1:48 [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi
  2013-07-03  1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
@ 2013-07-03  1:48 ` Yao Qi
  2013-07-29 18:17   ` Pedro Alves
  2013-07-29  9:33 ` [ping]: [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi
  2 siblings, 1 reply; 26+ messages in thread
From: Yao Qi @ 2013-07-03  1:48 UTC (permalink / raw)
  To: gdb-patches

Hi,
During the review of frame filter MI patch, Tom pointed that it is better
to use mi_getopt to simplify option parsing.  Unfortunately, the code
doesn't do it.  Since I am trying to add another option to commands
'-stack-list-XXXX', I'd like to have a try to use mi_getopt.

For command '-stack-list-locals' and '-stack-list-variables',
the PRINT_VALUES may confuse option parsing by mi_getopt, so in this
patch, we copy the argv except PRINT_VALUES to a new vector, and parse
the new vector by mi_getopt.

gdb:

2013-07-03  Yao Qi  <yao@codesourcery.com>

	* mi/mi-cmd-stack.c (mi_cmd_stack_list_locals): Don't call
	parse_no_frames_option.  Copy ARGV to new_argv except PRINT_VALUES.
	Parse new_argv by mi_getopt.
	(mi_cmd_stack_list_variables): Likewise.
---
 gdb/mi/mi-cmd-stack.c |   99 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 89 insertions(+), 10 deletions(-)

diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 4b21015..3212c03 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -212,16 +212,56 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   int raw_arg = 0;
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
+  int oind = 0;
 
-  if (argc > 0)
-    raw_arg = parse_no_frames_option (argv[0]);
+  if (argc > 1)
+    {
+      struct cleanup *cleanup;
+      int i;
+      char **new_argv = xmalloc ((argc - 1) * sizeof (char *));
+      enum opt
+      {
+	NO_FRAME_FILTERS
+      };
+      static const struct mi_opt opts[] =
+	{
+	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  { 0, 0, 0 }
+	};
+
+      cleanup = make_cleanup (xfree, new_argv);
+
+      for (i = 0; i < argc - 1; i++)
+	{
+	  new_argv[i] = xstrdup (argv[i]);
+	  make_cleanup (xfree, new_argv[i]);
+	}
+
+      while (1)
+	{
+	  char *oarg;
+	  /* Don't parse 'print-values' as an option.  */
+	  int opt = mi_getopt ("-stack-list-locals", argc - 1, new_argv,
+			       opts, &oind, &oarg);
+	  if (opt < 0)
+	    break;
+	  switch ((enum opt) opt)
+	    {
+	    case NO_FRAME_FILTERS:
+	      raw_arg = oind;
+	      break;
+	    }
+	}
+      do_cleanups (cleanup);
+    }
 
-  if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg)
-      || (argc == 1 && raw_arg))
+  /* After the last option is parsed, there should be only
+     'print-values'.  */
+  if (argc - oind != 1)
     error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES"));
 
   frame = get_selected_frame (NULL);
-  print_value = mi_parse_print_values (argv[raw_arg]);
+  print_value = mi_parse_print_values (argv[oind]);
 
    if (! raw_arg && frame_filters)
      {
@@ -341,17 +381,56 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   int raw_arg = 0;
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
+  int oind = 0;
 
-  if (argc > 0)
-    raw_arg = parse_no_frames_option (argv[0]);
+  if (argc > 1)
+    {
+      struct cleanup *cleanup;
+      int i;
+      char **new_argv = xmalloc ((argc - 1) * sizeof (char *));
+      enum opt
+      {
+	NO_FRAME_FILTERS
+      };
+      static const struct mi_opt opts[] =
+	{
+	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  { 0, 0, 0 }
+	};
+      cleanup = make_cleanup (xfree, new_argv);
+
+      for (i = 0; i < argc - 1; i++)
+	{
+	  new_argv[i] = xstrdup (argv[i]);
+	  make_cleanup (xfree, new_argv[i]);
+	}
+
+      while (1)
+	{
+	  char *oarg;
+	  /* Don't parse 'print-values' as an option.  */
+	  int opt = mi_getopt ("-stack-list-variables", argc - 1,
+			       new_argv, opts, &oind, &oarg);
+	  if (opt < 0)
+	    break;
+	  switch ((enum opt) opt)
+	    {
+	    case NO_FRAME_FILTERS:
+	      raw_arg = oind;
+	      break;
+	    }
+	}
+      do_cleanups (cleanup);
+    }
 
-  if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg)
-      || (argc == 1 && raw_arg))
+  /* After the last option is parsed, there should be only
+     'print-values'.  */
+  if (argc - oind != 1)
     error (_("-stack-list-variables: Usage: " \
 	     "[--no-frame-filters] PRINT_VALUES"));
 
    frame = get_selected_frame (NULL);
-   print_value = mi_parse_print_values (argv[raw_arg]);
+   print_value = mi_parse_print_values (argv[oind]);
 
    if (! raw_arg && frame_filters)
      {
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] Add options to skip unavailable locals
  2013-07-03  1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
@ 2013-07-03  4:14   ` asmwarrior
  2013-07-03  5:21     ` Yao Qi
  2013-07-03 19:22   ` Eli Zaretskii
  1 sibling, 1 reply; 26+ messages in thread
From: asmwarrior @ 2013-07-03  4:14 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

For me, when I firstly see this word, an "unavaliable locals" means those local variables which does not constructed.
E.g.:
void f(void)
{
    ClassA  a;
    some statements; // when your are here, "b" is not constructed.
    ClassB b;
}

But I believe you mean(under GDB) the variable which does not have enough info to print.

Yuanhui Zhang

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] Add options to skip unavailable locals
  2013-07-03  4:14   ` asmwarrior
@ 2013-07-03  5:21     ` Yao Qi
  0 siblings, 0 replies; 26+ messages in thread
From: Yao Qi @ 2013-07-03  5:21 UTC (permalink / raw)
  To: asmwarrior; +Cc: gdb-patches

On 07/03/2013 12:20 PM, asmwarrior wrote:
> For me, when I firstly see this word, an "unavaliable locals" means those local variables which does not constructed.
> E.g.:
> void f(void)
> {
>      ClassA  a;
>      some statements; // when your are here, "b" is not constructed.
>      ClassB b;
> }
>
> But I believe you mean(under GDB) the variable which does not have enough info to print.

Right, under the context of GDB, "unavailable locals" means "locals 
whose value are unavailable".  Probably, the subject of this mail should 
be "Add options to skip locals or arguments whose values are unavailable".

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] Add options to skip unavailable locals
  2013-07-03  1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
  2013-07-03  4:14   ` asmwarrior
@ 2013-07-03 19:22   ` Eli Zaretskii
  2013-07-22  1:38     ` Yao Qi
  1 sibling, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2013-07-03 19:22 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

> From: Yao Qi <yao@codesourcery.com>
> Date: Wed, 3 Jul 2013 09:48:26 +0800
> 
> This is the patch to add new option '--skip-unavailable' to MI
> commands '-stack-list-{locals, arguments, variables}'.  This patch
> extends list_args_or_locals to add a new parameter 'skip_unavailable',
> and don't list locals or arguments if values are unavailable and
> 'skip_unavailable' is true.

Thanks.

> +  ** The commands -stack-list-locals, -stack-list-arguments and
> +     -stack-list-variables now accept an optional "--skip-unavailable"
> +     option.  When used, only the available locals or arguments are
> +     displayed.

"optional option" doesn't sound right.  I think dropping the
"optional" part is all you need.

> +If the @code{--skip-unavailable} option is specified, arguments that
> +have not been available are not listed.  Partially available objects
   ^^^^^^^^^^^^^^^^^^^^^^^
"are not available".

And why "objects" instead of "arguments"?

> +If the @code{--skip-unavailable} option is specified, local variables
> +that have not been available are not listed.  Partially available
> +objects are still displayed, however.

Likewise, on both accounts.  There are other places with the same
problems.

> +If the @code{--skip-unavailable} option is specified, then, local
                                                         ^^^^^
This "then" and the comma after it should be deleted.

OK with those changes.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] Add options to skip unavailable locals
  2013-07-03 19:22   ` Eli Zaretskii
@ 2013-07-22  1:38     ` Yao Qi
  2013-08-01 12:33       ` Pedro Alves
  0 siblings, 1 reply; 26+ messages in thread
From: Yao Qi @ 2013-07-22  1:38 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On 07/04/2013 03:21 AM, Eli Zaretskii wrote:
>> +  ** The commands -stack-list-locals, -stack-list-arguments and
>> >+     -stack-list-variables now accept an optional "--skip-unavailable"
>> >+     option.  When used, only the available locals or arguments are
>> >+     displayed.
> "optional option" doesn't sound right.  I think dropping the
> "optional" part is all you need.
> 
>> >+If the @code{--skip-unavailable} option is specified, arguments that
>> >+have not been available are not listed.  Partially available objects
>     ^^^^^^^^^^^^^^^^^^^^^^^
> "are not available".
> 
> And why "objects" instead of "arguments"?
> 
>> >+If the @code{--skip-unavailable} option is specified, local variables
>> >+that have not been available are not listed.  Partially available
>> >+objects are still displayed, however.
> Likewise, on both accounts.  There are other places with the same
> problems.
> 
>> >+If the @code{--skip-unavailable} option is specified, then, local
>                                                           ^^^^^
> This "then" and the comma after it should be deleted.
> 
> OK with those changes.

Eli,
Thanks for the review.  The updated patch addresses all your comments
on doc bits.

Ping for the review to the rest of patches.

-- 
Yao (齐尧)

gdb:

2013-07-22  Pedro Alves  <pedro@codesourcery.com>
	    Yao Qi  <yao@codesourcery.com>

	* mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype.
	(parse_no_frames_option): Remove.
	(mi_cmd_stack_list_locals): Handle --skip-unavailable.
	(mi_cmd_stack_list_args): Adjust.
	(mi_cmd_stack_list_variables): Handle --skip-unavailable.
	(list_args_or_locals): New parameter 'skip_unavailable'.
	Handle it.
	* valprint.c (scalar_type_p): Rename to ...
	(val_print_scalar_type_p): ... this.  Make extern.
	(val_print, value_check_printable): Adjust.
	* valprint.h (val_print_scalar_type_p): Declare.
	* value.c (value_entirely_unavailable): New function.
	* value.h (value_entirely_unavailable): Declare.

	* NEWS: Mention the new option "--skip-unavailable" to these
	MI commands.

gdb/doc:

2013-07-22  Pedro Alves  <pedro@codesourcery.com>
	    Yao Qi  <yao@codesourcery.com>

	* gdb.texinfo (GDB/MI Stack Manipulation)<-stack-list-locals>:
	Document new --skip-unavailable option.
	<-stack-list-variables>: Document new --skip-unavailable option.

gdb/testsuite:

2013-07-22  Yao Qi  <yao@codesourcery.com>

	* gdb.trace/mi-trace-unavailable.exp (test_trace_unavailable):
	Add tests for new option '--skip-unavailable'.
---
 gdb/NEWS                                         |    4 +
 gdb/doc/gdb.texinfo                              |   17 ++-
 gdb/mi/mi-cmd-stack.c                            |  161 ++++++++++++++--------
 gdb/testsuite/gdb.trace/mi-trace-unavailable.exp |    9 ++
 gdb/valprint.c                                   |    8 +-
 gdb/valprint.h                                   |    2 +
 gdb/value.c                                      |   20 +++
 gdb/value.h                                      |    4 +
 8 files changed, 163 insertions(+), 62 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index a4238d0..342a244 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -89,6 +89,10 @@ show range-stepping
   ** The new command -trace-frame-collected dumps collected variables,
      computed expressions, tvars, memory and registers in a traceframe.
 
+  ** The commands -stack-list-locals, -stack-list-arguments and
+     -stack-list-variables now accept an option "--skip-unavailable".
+     When used, only the available locals or arguments are displayed.
+
 * New system-wide configuration scripts
   A GDB installation now provides scripts suitable for use as system-wide
   configuration scripts for the following systems:
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4caeea5..4d45548 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -31244,7 +31244,7 @@ For a stack with frame levels 0 through 11:
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-arguments [ --no-frame-filters ] @var{print-values}
+ -stack-list-arguments [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
     [ @var{low-frame} @var{high-frame} ]
 @end smallexample
 
@@ -31264,6 +31264,9 @@ type and value for simple data types, and the name and type for arrays,
 structures and unions.  If the option @code{--no-frame-filters} is
 supplied, then Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, arguments that
+are not available are not listed.  Partially available arguments
+are still displayed, however.
 
 Use of this command to obtain arguments in a single frame is
 deprecated in favor of the @samp{-stack-list-variables} command.
@@ -31448,7 +31451,7 @@ Show a single frame:
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-locals [ --no-frame-filters ] @var{print-values}
+ -stack-list-locals [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
 @end smallexample
 
 Display the local variable names for the selected frame.  If
@@ -31462,6 +31465,10 @@ other data types when the user wishes to explore their values in
 more detail.  If the option @code{--no-frame-filters} is supplied, then
 Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, local variables
+that are not available are not listed.  Partially available locals
+variables are still displayed, however.
+
 This command is deprecated in favor of the
 @samp{-stack-list-variables} command.
 
@@ -31492,7 +31499,7 @@ This command is deprecated in favor of the
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-variables [ --no-frame-filters ] @var{print-values}
+ -stack-list-variables [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
 @end smallexample
 
 Display the names of local variables and function arguments for the selected frame.  If
@@ -31503,6 +31510,10 @@ type and value for simple data types, and the name and type for arrays,
 structures and unions.  If the option @code{--no-frame-filters} is
 supplied, then Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, local variables
+and arguments that are not collected are not listed.  Partially
+available arguments and local variables are still displayed, however.
+
 @subsubheading Example
 
 @smallexample
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 5a81bcd..0d565e5 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -39,9 +39,10 @@
 
 enum what_to_list { locals, arguments, all };
 
-static void list_args_or_locals (enum what_to_list what, 
+static void list_args_or_locals (enum what_to_list what,
 				 enum print_values values,
-				 struct frame_info *fi);
+				 struct frame_info *fi,
+				 int skip_unavailable);
 
 /* True if we want to allow Python-based frame filters.  */
 static int frame_filters = 0;
@@ -54,17 +55,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc)
   frame_filters = 1;
 }
 
-/* Parse the --no-frame-filters option in commands where we cannot use
-   mi_getopt. */
-static int
-parse_no_frames_option (const char *arg)
-{
-  if (arg && (strcmp (arg, "--no-frame-filters") == 0))
-    return 1;
-
-  return 0;
-}
-
 /* Print a list of the stack frames.  Args can be none, in which case
    we want to print the whole backtrace, or a pair of numbers
    specifying the frame numbers at which to start and stop the
@@ -213,6 +203,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
   int oind = 0;
+  int skip_unavailable = 0;
+  int i;
 
   if (argc > 1)
     {
@@ -221,11 +213,13 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
       char **new_argv = xmalloc ((argc - 1) * sizeof (char *));
       enum opt
       {
-	NO_FRAME_FILTERS
+	NO_FRAME_FILTERS,
+	SKIP_UNAVAILABLE,
       };
       static const struct mi_opt opts[] =
 	{
 	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
 	  { 0, 0, 0 }
 	};
 
@@ -249,6 +243,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
 	    {
 	    case NO_FRAME_FILTERS:
 	      raw_arg = oind;
+	    case SKIP_UNAVAILABLE:
+	      skip_unavailable = 1;
 	      break;
 	    }
 	}
@@ -258,7 +254,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   /* After the last option is parsed, there should be only
      'print-values'.  */
   if (argc - oind != 1)
-    error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES"));
+    error (_("-stack-list-locals: Usage: [--no-frame-filters] "
+	     "[--skip-unavailable] PRINT_VALUES"));
 
   frame = get_selected_frame (NULL);
   print_value = mi_parse_print_values (argv[oind]);
@@ -275,7 +272,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
       if "--no-frame-filters" has been specified from the command.  */
    if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
      {
-       list_args_or_locals (locals, print_value, frame);
+       list_args_or_locals (locals, print_value, frame,
+			    skip_unavailable);
      }
 }
 
@@ -295,18 +293,39 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
   struct ui_out *uiout = current_uiout;
   int raw_arg = 0;
   enum py_bt_status result = PY_BT_ERROR;
+  int skip_unavailable = 0;
+  int oind = 0;
 
-  if (argc > 0)
-    raw_arg = parse_no_frames_option (argv[0]);
+  /* We can't use mi_getopt here, because the number of options is not
+     determined.  */
+  for (oind = 0; oind < argc; oind++)
+    {
+      int found = 0;
 
-  if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg))
+      if (strcmp (argv[oind], "--no-frame-filters") == 0)
+	{
+	  raw_arg = oind + 1;
+	  found = 1;
+	}
+      else if (strcmp (argv[oind], "--skip-unavailable") == 0)
+	{
+	  skip_unavailable = 1;
+	  found = 1;
+	}
+
+      if (!found)
+	break;
+    }
+
+  if (argc - oind != 1 && argc - oind != 3)
     error (_("-stack-list-arguments: Usage: " \
-	     "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
+	     "[--no-frame-filters] [--skip-unavailable] "
+	     "PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
 
-  if (argc >= 3)
+  if (argc - oind == 3)
     {
-      frame_low = atoi (argv[1 + raw_arg]);
-      frame_high = atoi (argv[2 + raw_arg]);
+      frame_low = atoi (argv[1 + oind]);
+      frame_high = atoi (argv[2 + oind]);
     }
   else
     {
@@ -316,7 +335,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
       frame_high = -1;
     }
 
-  print_values = mi_parse_print_values (argv[raw_arg]);
+  print_values = mi_parse_print_values (argv[oind]);
 
   /* Let's position fi on the frame at which to start the
      display. Could be the innermost frame if the whole stack needs
@@ -362,7 +381,8 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
 	  QUIT;
 	  cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
 	  ui_out_field_int (uiout, "level", i);
-	  list_args_or_locals (arguments, print_values, fi);
+	  list_args_or_locals (arguments, print_values, fi,
+			       skip_unavailable);
 	  do_cleanups (cleanup_frame);
 	}
     }
@@ -382,6 +402,7 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
   int oind = 0;
+  int skip_unavailable = 0;
 
   if (argc > 1)
     {
@@ -390,11 +411,13 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
       char **new_argv = xmalloc ((argc - 1) * sizeof (char *));
       enum opt
       {
-	NO_FRAME_FILTERS
+	NO_FRAME_FILTERS,
+	SKIP_UNAVAILABLE,
       };
       static const struct mi_opt opts[] =
 	{
 	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
 	  { 0, 0, 0 }
 	};
       cleanup = make_cleanup (xfree, new_argv);
@@ -418,6 +441,9 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
 	    case NO_FRAME_FILTERS:
 	      raw_arg = oind;
 	      break;
+	    case SKIP_UNAVAILABLE:
+	      skip_unavailable = 1;
+	      break;
 	    }
 	}
       do_cleanups (cleanup);
@@ -426,8 +452,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   /* After the last option is parsed, there should be only
      'print-values'.  */
   if (argc - oind != 1)
-    error (_("-stack-list-variables: Usage: " \
-	     "[--no-frame-filters] PRINT_VALUES"));
+    error (_("-stack-list-variables: Usage: [--no-frame-filters] " \
+	     "[--skip-unavailable] PRINT_VALUES"));
 
    frame = get_selected_frame (NULL);
    print_value = mi_parse_print_values (argv[oind]);
@@ -444,7 +470,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
       if "--no-frame-filters" has been specified from the command.  */
    if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
      {
-       list_args_or_locals (all, print_value, frame);
+       list_args_or_locals (all, print_value, frame,
+			    skip_unavailable);
      }
 }
 
@@ -525,11 +552,12 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
 /* Print a list of the locals or the arguments for the currently
    selected frame.  If the argument passed is 0, printonly the names
    of the variables, if an argument of 1 is passed, print the values
-   as well.  */
+   as well.  If SKIP_UNAVAILABLE is true, print the arguments or local
+   variables whose values are available.  */
 
 static void
 list_args_or_locals (enum what_to_list what, enum print_values values,
-		     struct frame_info *fi)
+		     struct frame_info *fi, int skip_unavailable)
 {
   struct block *block;
   struct symbol *sym;
@@ -564,6 +592,7 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
       ALL_BLOCK_SYMBOLS (block, iter, sym)
 	{
           int print_me = 0;
+	  struct value *val = NULL;
 
 	  switch (SYMBOL_CLASS (sym))
 	    {
@@ -597,7 +626,6 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
 	  if (print_me)
 	    {
 	      struct symbol *sym2;
-	      struct frame_arg arg, entryarg;
 
 	      if (SYMBOL_IS_ARGUMENT (sym))
 		sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
@@ -607,33 +635,56 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
 		sym2 = sym;
 	      gdb_assert (sym2 != NULL);
 
-	      memset (&arg, 0, sizeof (arg));
-	      arg.sym = sym2;
-	      arg.entry_kind = print_entry_values_no;
-	      memset (&entryarg, 0, sizeof (entryarg));
-	      entryarg.sym = sym2;
-	      entryarg.entry_kind = print_entry_values_no;
-
-	      switch (values)
+	      /* Need to read the value before being able to determine
+		 whether its unavailable.  */
+	      if (values == PRINT_ALL_VALUES
+		  || values == PRINT_SIMPLE_VALUES
+		  || skip_unavailable)
+		val = read_var_value (sym2, fi);
+
+	      if (skip_unavailable
+		  && (value_entirely_unavailable (val)
+		      /* A scalar object that does not have all bits
+			 available is also considered unavailable,
+			 because all bits contribute to its
+			 representation.  */
+		      || (val_print_scalar_type_p (value_type (val))
+			  && !value_bytes_available (val,
+						     value_embedded_offset (val),
+						     TYPE_LENGTH (value_type (val))))))
+		;
+	      else
 		{
-		case PRINT_SIMPLE_VALUES:
-		  type = check_typedef (sym2->type);
-		  if (TYPE_CODE (type) != TYPE_CODE_ARRAY
-		      && TYPE_CODE (type) != TYPE_CODE_STRUCT
-		      && TYPE_CODE (type) != TYPE_CODE_UNION)
+		  struct frame_arg arg, entryarg;
+
+		  memset (&arg, 0, sizeof (arg));
+		  arg.sym = sym2;
+		  arg.entry_kind = print_entry_values_no;
+		  memset (&entryarg, 0, sizeof (entryarg));
+		  entryarg.sym = sym2;
+		  entryarg.entry_kind = print_entry_values_no;
+
+		  switch (values)
 		    {
-		case PRINT_ALL_VALUES:
-		      read_frame_arg (sym2, fi, &arg, &entryarg);
+		    case PRINT_SIMPLE_VALUES:
+		      type = check_typedef (sym2->type);
+		      if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+			  && TYPE_CODE (type) != TYPE_CODE_STRUCT
+			  && TYPE_CODE (type) != TYPE_CODE_UNION)
+			{
+			case PRINT_ALL_VALUES:
+			  read_frame_arg (sym2, fi, &arg, &entryarg);
+			}
+		      break;
 		    }
-		  break;
-		}
 
-	      if (arg.entry_kind != print_entry_values_only)
-		list_arg_or_local (&arg, what, values);
-	      if (entryarg.entry_kind != print_entry_values_no)
-		list_arg_or_local (&entryarg, what, values);
-	      xfree (arg.error);
-	      xfree (entryarg.error);
+		  if (arg.entry_kind != print_entry_values_only)
+		    list_arg_or_local (&arg, what, values);
+		  if (entryarg.entry_kind != print_entry_values_no)
+		    list_arg_or_local (&entryarg, what, values);
+		  xfree (arg.error);
+		  xfree (entryarg.error);
+		}
 	    }
 	}
 
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index 42f6e32..f147899 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -93,16 +93,25 @@ proc test_trace_unavailable { data_source } {
 	mi_gdb_test "-stack-list-locals --simple-values" \
 	    ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \
 	    "-stack-list-locals --simple-values"
+	mi_gdb_test "-stack-list-locals --skip-unavailable --simple-values" \
+	    ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \
+	    "-stack-list-locals --skip-unavailable --simple-values"
 
 	# Test MI command '-stack-list-arguments'.
 	mi_gdb_test "-stack-list-arguments --simple-values" \
 	    ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\},\{name=\"s\",type=\"char \\\*\",value=\"<unavailable>\"\}\\\]\},.*\}.*" \
 	    "-stack-list-arguments --simple-values"
+	mi_gdb_test "-stack-list-arguments --skip-unavailable --simple-values" \
+	    ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\}\\\]\},.*\}.*" \
+	    "-stack-list-arguments --skip-unavailable --simple-values"
 
 	# Test MI command '-stack-list-variables'.
 	mi_gdb_test "-stack-list-variables --simple-values" \
 	    ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"s\",arg=\"1\",type=\"char \\\*\",value=\"<unavailable>\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \
 	    "-stack-list-variables --simple-values"
+	mi_gdb_test "-stack-list-variables --skip-unavailable --simple-values" \
+	    ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \
+	    "-stack-list-variables --skip-unavailable --simple-values"
 
 	mi_gdb_test "-trace-find frame-number 1" \
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 753ae34..0f6d65e 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -275,8 +275,8 @@ show_symbol_print (struct ui_file *file, int from_tty,
    we want to print scalar arguments, but not aggregate arguments.
    This function distinguishes between the two.  */
 
-static int
-scalar_type_p (struct type *type)
+int
+val_print_scalar_type_p (struct type *type)
 {
   CHECK_TYPEDEF (type);
   while (TYPE_CODE (type) == TYPE_CODE_REF)
@@ -770,7 +770,7 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 
   /* Handle summary mode.  If the value is a scalar, print it;
      otherwise, print an ellipsis.  */
-  if (options->summary && !scalar_type_p (type))
+  if (options->summary && !val_print_scalar_type_p (type))
     {
       fprintf_filtered (stream, "...");
       return;
@@ -802,7 +802,7 @@ value_check_printable (struct value *val, struct ui_file *stream,
 
   if (value_entirely_optimized_out (val))
     {
-      if (options->summary && !scalar_type_p (value_type (val)))
+      if (options->summary && !val_print_scalar_type_p (value_type (val)))
 	fprintf_filtered (stream, "...");
       else
 	val_print_optimized_out (stream);
diff --git a/gdb/valprint.h b/gdb/valprint.h
index 2959098..e7073b6 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -211,4 +211,6 @@ extern void generic_printstr (struct ui_file *stream, struct type *type,
 
 extern void output_command_const (const char *args, int from_tty);
 
+extern int val_print_scalar_type_p (struct type *type);
+
 #endif
diff --git a/gdb/value.c b/gdb/value.c
index 04f325f..54d4232 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -353,6 +353,26 @@ value_entirely_available (struct value *value)
   return 0;
 }
 
+int
+value_entirely_unavailable (struct value *value)
+{
+  /* We can only tell whether the whole value is available when we try
+     to read it.  */
+  if (value->lazy)
+    value_fetch_lazy (value);
+
+  if (VEC_length (range_s, value->unavailable) == 1)
+    {
+      struct range *t = VEC_index (range_s, value->unavailable, 0);
+
+      if (t->offset == 0
+	  && t->length == TYPE_LENGTH (value_enclosing_type (value)))
+	return 1;
+    }
+
+  return 0;
+}
+
 void
 mark_value_bytes_unavailable (struct value *value, int offset, int length)
 {
diff --git a/gdb/value.h b/gdb/value.h
index 5e00c89..5197df9 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -435,6 +435,10 @@ extern int value_bytes_available (const struct value *value,
    whole object is unavailable.  */
 extern int value_entirely_available (struct value *value);
 
+/* Like value_entirely_available, but return false if any byte in the
+   whole object is available.  */
+extern int value_entirely_unavailable (struct value *value);
+
 /* Mark VALUE's content bytes starting at OFFSET and extending for
    LENGTH bytes as unavailable.  */
 
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [ping]: [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands
  2013-07-03  1:48 [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi
  2013-07-03  1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
  2013-07-03  1:48 ` [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables Yao Qi
@ 2013-07-29  9:33 ` Yao Qi
  2 siblings, 0 replies; 26+ messages in thread
From: Yao Qi @ 2013-07-29  9:33 UTC (permalink / raw)
  To: gdb-patches

On 07/03/2013 09:48 AM, Yao Qi wrote:
> Hi,
> This patch series add new option '--skip-unavailable' to MI commands
> '-stack-list-{locals, arguments, variables}'.  This option is optional,
> and when it is used, locals or arguments whose values are not available
> are not listed.  It is useful when the MI front-end is not interested in
> unavailable values.
>
> The patch 1/2 is a refactor patch, use mi_getopt in
> mi_cmd_stack_list_locals and mi_cmd_stack_list_variables, so it is
> easier to add new option patch 2/2.  Patch 2/2 is the major part of this
> series.
>
> Regression tested on x86_64-linux.
>
> Note that this patch is for MI, but the idea that skipping unavailable
> locals and arguments can be applied to CLI too.  We can invent new CLI
> commands on top of 'info locals' and 'info args' to display available
> locals or arguments.  This piece of work is not included in this
> series.

Ping.  http://sourceware.org/ml/gdb-patches/2013-07/msg00101.html

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables
  2013-07-03  1:48 ` [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables Yao Qi
@ 2013-07-29 18:17   ` Pedro Alves
  2013-07-31  7:01     ` Yao Qi
  0 siblings, 1 reply; 26+ messages in thread
From: Pedro Alves @ 2013-07-29 18:17 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 07/03/2013 02:48 AM, Yao Qi wrote:
> Hi,
> During the review of frame filter MI patch, Tom pointed that it is better
> to use mi_getopt to simplify option parsing.  Unfortunately, the code
> doesn't do it.  Since I am trying to add another option to commands
> '-stack-list-XXXX', I'd like to have a try to use mi_getopt.
> 
> For command '-stack-list-locals' and '-stack-list-variables',
> the PRINT_VALUES may confuse option parsing by mi_getopt, 

[to clarify,] because it throws error on unknown options, and
PRINT_VALUES may look like an option (--no-values, --simple-values,
etc.), or not (0, 1, etc.).

> so in this
> patch, we copy the argv except PRINT_VALUES to a new vector, and parse
> the new vector by mi_getopt.

Please help me understand the patch.  Why do we need to copy
the arg vector?  Isn't it the same to do:

	  /* Don't parse 'print-values' as an option.  */
	  int opt = mi_getopt ("-stack-list-locals", argc - 1, argv,
			       opts, &oind, &oarg);

?

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables
  2013-07-29 18:17   ` Pedro Alves
@ 2013-07-31  7:01     ` Yao Qi
  2013-07-31 12:23       ` Pedro Alves
  0 siblings, 1 reply; 26+ messages in thread
From: Yao Qi @ 2013-07-31  7:01 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 07/30/2013 02:17 AM, Pedro Alves wrote:
> Please help me understand the patch.  Why do we need to copy
> the arg vector?  Isn't it the same to do:
> 
> 	  /* Don't parse 'print-values' as an option.  */
> 	  int opt = mi_getopt ("-stack-list-locals", argc - 1, argv,
> 			       opts, &oind, &oarg);
> 
> ?

There was something wrong in mi_getopt (an internal error,
IIRC) when I call mi_getopt with 'argc - 1', however, I
can't reproduce it now.  Probably because my tree was dirty
then.  I update the patch to avoid copying the arg vector.
Patch 2/2 still apply.

-- 
Yao (齐尧)

gdb:

2013-07-31  Yao Qi  <yao@codesourcery.com>

	* mi/mi-cmd-stack.c (mi_cmd_stack_list_locals): Parse argv by
	mi_getopt.
	(mi_cmd_stack_list_variables): Likewise.
---
 gdb/mi/mi-cmd-stack.c |   79 ++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 1f1068c..70ff0b6 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -212,16 +212,46 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   int raw_arg = 0;
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
+  int oind = 0;
 
-  if (argc > 0)
-    raw_arg = parse_no_frames_option (argv[0]);
+  if (argc > 1)
+    {
+      int i;
+      enum opt
+      {
+	NO_FRAME_FILTERS
+      };
+      static const struct mi_opt opts[] =
+	{
+	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  { 0, 0, 0 }
+	};
+
+      while (1)
+	{
+	  char *oarg;
+	  /* Don't parse 'print-values' as an option.  */
+	  int opt = mi_getopt ("-stack-list-locals", argc - 1, argv,
+			       opts, &oind, &oarg);
+
+	  if (opt < 0)
+	    break;
+	  switch ((enum opt) opt)
+	    {
+	    case NO_FRAME_FILTERS:
+	      raw_arg = oind;
+	      break;
+	    }
+	}
+    }
 
-  if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg)
-      || (argc == 1 && raw_arg))
+  /* After the last option is parsed, there should be only
+     'print-values'.  */
+  if (argc - oind != 1)
     error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES"));
 
   frame = get_selected_frame (NULL);
-  print_value = mi_parse_print_values (argv[raw_arg]);
+  print_value = mi_parse_print_values (argv[oind]);
 
    if (! raw_arg && frame_filters)
      {
@@ -341,17 +371,46 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   int raw_arg = 0;
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
+  int oind = 0;
 
-  if (argc > 0)
-    raw_arg = parse_no_frames_option (argv[0]);
+  if (argc > 1)
+    {
+      int i;
+      enum opt
+      {
+	NO_FRAME_FILTERS
+      };
+      static const struct mi_opt opts[] =
+	{
+	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  { 0, 0, 0 }
+	};
+
+      while (1)
+	{
+	  char *oarg;
+	  /* Don't parse 'print-values' as an option.  */
+	  int opt = mi_getopt ("-stack-list-variables", argc - 1,
+			       argv, opts, &oind, &oarg);
+	  if (opt < 0)
+	    break;
+	  switch ((enum opt) opt)
+	    {
+	    case NO_FRAME_FILTERS:
+	      raw_arg = oind;
+	      break;
+	    }
+	}
+    }
 
-  if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg)
-      || (argc == 1 && raw_arg))
+  /* After the last option is parsed, there should be only
+     'print-values'.  */
+  if (argc - oind != 1)
     error (_("-stack-list-variables: Usage: " \
 	     "[--no-frame-filters] PRINT_VALUES"));
 
    frame = get_selected_frame (NULL);
-   print_value = mi_parse_print_values (argv[raw_arg]);
+   print_value = mi_parse_print_values (argv[oind]);
 
    if (! raw_arg && frame_filters)
      {
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables
  2013-07-31  7:01     ` Yao Qi
@ 2013-07-31 12:23       ` Pedro Alves
  2013-08-01  6:45         ` Yao Qi
  0 siblings, 1 reply; 26+ messages in thread
From: Pedro Alves @ 2013-07-31 12:23 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 07/31/2013 08:00 AM, Yao Qi wrote:
> 2013-07-31  Yao Qi  <yao@codesourcery.com>
> 
> 	* mi/mi-cmd-stack.c (mi_cmd_stack_list_locals): Parse argv by
> 	mi_getopt.

s/by/with/

> 	(mi_cmd_stack_list_variables): Likewise.

OK.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables
  2013-07-31 12:23       ` Pedro Alves
@ 2013-08-01  6:45         ` Yao Qi
  0 siblings, 0 replies; 26+ messages in thread
From: Yao Qi @ 2013-08-01  6:45 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 07/31/2013 08:22 PM, Pedro Alves wrote:
> s/by/with/
>
>> >	(mi_cmd_stack_list_variables): Likewise.
> OK.

Thanks for the review.  Changelog is fixed and patch is committed to cvs.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] Add options to skip unavailable locals
  2013-07-22  1:38     ` Yao Qi
@ 2013-08-01 12:33       ` Pedro Alves
  2013-08-01 13:59         ` Yao Qi
  2013-08-25  3:43         ` [PATCH 0/2 v2] " Yao Qi
  0 siblings, 2 replies; 26+ messages in thread
From: Pedro Alves @ 2013-08-01 12:33 UTC (permalink / raw)
  To: Yao Qi; +Cc: Eli Zaretskii, gdb-patches

On 07/22/2013 02:37 AM, Yao Qi wrote:

> 2013-07-22  Pedro Alves  <pedro@codesourcery.com>
> 	    Yao Qi  <yao@codesourcery.com>
> 
> 	* mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype.
> 	(parse_no_frames_option): Remove.
> 	(mi_cmd_stack_list_locals): Handle --skip-unavailable.
> 	(mi_cmd_stack_list_args): Adjust.
> 	(mi_cmd_stack_list_variables): Handle --skip-unavailable.
> 	(list_args_or_locals): New parameter 'skip_unavailable'.
> 	Handle it.
> 	* valprint.c (scalar_type_p): Rename to ...
> 	(val_print_scalar_type_p): ... this.  Make extern.
> 	(val_print, value_check_printable): Adjust.
> 	* valprint.h (val_print_scalar_type_p): Declare.
> 	* value.c (value_entirely_unavailable): New function.
> 	* value.h (value_entirely_unavailable): Declare.
> 
> 	* NEWS: Mention the new option "--skip-unavailable" to these
> 	MI commands.

Hmm, this "these" reads out of nowhere.  "Which these?"

> 
> gdb/doc:
> 
> 2013-07-22  Pedro Alves  <pedro@codesourcery.com>
> 	    Yao Qi  <yao@codesourcery.com>
> 
> 	* gdb.texinfo (GDB/MI Stack Manipulation)<-stack-list-locals>:

Space before "<".

> 	Document new --skip-unavailable option.
> 	<-stack-list-variables>: Document new --skip-unavailable option.
> 

> +If the @code{--skip-unavailable} option is specified, local variables
> +that are not available are not listed.  Partially available locals
> +variables are still displayed, however.

s/available locals variables/available local variables/


> +If the @code{--skip-unavailable} option is specified, local variables
> +and arguments that are not collected are not listed.

This still says "that are not collected".  I think it should say
"that that are not available", like the other bits (and similarly
to the adjustment done in other patches, IIRC).

> @@ -295,18 +293,39 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
>    struct ui_out *uiout = current_uiout;
>    int raw_arg = 0;
>    enum py_bt_status result = PY_BT_ERROR;
> +  int skip_unavailable = 0;
> +  int oind = 0;
>  
> -  if (argc > 0)
> -    raw_arg = parse_no_frames_option (argv[0]);
> +  /* We can't use mi_getopt here, because the number of options is not
> +     determined.  */

Hmm.  Isn't that easy to fix though?  We'd just need an mi_getopt
variant that doesn't error out when it sees an unknown option, but
instead returns that option's position (similarly to getopt).  It's
then the caller's responsibility to parse the rest of the option
string.

> +  for (oind = 0; oind < argc; oind++)
> +    {
> +      int found = 0;
>  
> -  if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg))
> +      if (strcmp (argv[oind], "--no-frame-filters") == 0)
> +	{
> +	  raw_arg = oind + 1;
> +	  found = 1;
> +	}
> +      else if (strcmp (argv[oind], "--skip-unavailable") == 0)
> +	{
> +	  skip_unavailable = 1;
> +	  found = 1;
> +	}
> +
> +      if (!found)
> +	break;
> +    }
> +
> +  if (argc - oind != 1 && argc - oind != 3)
>      error (_("-stack-list-arguments: Usage: " \
> -	     "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
> +	     "[--no-frame-filters] [--skip-unavailable] "
> +	     "PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
>  
> -  if (argc >= 3)
> +  if (argc - oind == 3)
>      {
> -      frame_low = atoi (argv[1 + raw_arg]);
> -      frame_high = atoi (argv[2 + raw_arg]);
> +      frame_low = atoi (argv[1 + oind]);
> +      frame_high = atoi (argv[2 + oind]);
>      }
>    else
>      {
> @@ -316,7 +335,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
>        frame_high = -1;
>      }
>  


> @@ -597,7 +626,6 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
>  	  if (print_me)
>  	    {
>  	      struct symbol *sym2;
> -	      struct frame_arg arg, entryarg;
>  
>  	      if (SYMBOL_IS_ARGUMENT (sym))
>  		sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
> @@ -607,33 +635,56 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
>  		sym2 = sym;
>  	      gdb_assert (sym2 != NULL);
>  
> -	      memset (&arg, 0, sizeof (arg));
> -	      arg.sym = sym2;
> -	      arg.entry_kind = print_entry_values_no;
> -	      memset (&entryarg, 0, sizeof (entryarg));
> -	      entryarg.sym = sym2;
> -	      entryarg.entry_kind = print_entry_values_no;
> -
> -	      switch (values)
> +	      /* Need to read the value before being able to determine
> +		 whether its unavailable.  */
> +	      if (values == PRINT_ALL_VALUES
> +		  || values == PRINT_SIMPLE_VALUES
> +		  || skip_unavailable)
> +		val = read_var_value (sym2, fi);
> +
> +	      if (skip_unavailable
> +		  && (value_entirely_unavailable (val)
> +		      /* A scalar object that does not have all bits
> +			 available is also considered unavailable,
> +			 because all bits contribute to its
> +			 representation.  */
> +		      || (val_print_scalar_type_p (value_type (val))
> +			  && !value_bytes_available (val,
> +						     value_embedded_offset (val),
> +						     TYPE_LENGTH (value_type (val))))))
> +		;
> +	      else

I don't think this has been updated right for entry values.  With
entry values, we now have _two_ values to account for.  I think
we need to do this once for each of the regular arg and the
entry arg?

>  		{
> -		case PRINT_SIMPLE_VALUES:
> -		  type = check_typedef (sym2->type);
> -		  if (TYPE_CODE (type) != TYPE_CODE_ARRAY
> -		      && TYPE_CODE (type) != TYPE_CODE_STRUCT
> -		      && TYPE_CODE (type) != TYPE_CODE_UNION)
> +		  struct frame_arg arg, entryarg;
> +
> +		  memset (&arg, 0, sizeof (arg));
> +		  arg.sym = sym2;
> +		  arg.entry_kind = print_entry_values_no;
> +		  memset (&entryarg, 0, sizeof (entryarg));
> +		  entryarg.sym = sym2;
> +		  entryarg.entry_kind = print_entry_values_no;
> +
> +		  switch (values)
>  		    {
> -		case PRINT_ALL_VALUES:
> -		      read_frame_arg (sym2, fi, &arg, &entryarg);
> +		    case PRINT_SIMPLE_VALUES:
> +		      type = check_typedef (sym2->type);
> +		      if (TYPE_CODE (type) != TYPE_CODE_ARRAY
> +			  && TYPE_CODE (type) != TYPE_CODE_STRUCT
> +			  && TYPE_CODE (type) != TYPE_CODE_UNION)
> +			{
> +			case PRINT_ALL_VALUES:
> +			  read_frame_arg (sym2, fi, &arg, &entryarg);
> +			}
> +		      break;
>  		    }
> -		  break;
> -		}
>  
> -	      if (arg.entry_kind != print_entry_values_only)
> -		list_arg_or_local (&arg, what, values);
> -	      if (entryarg.entry_kind != print_entry_values_no)
> -		list_arg_or_local (&entryarg, what, values);
> -	      xfree (arg.error);
> -	      xfree (entryarg.error);
> +		  if (arg.entry_kind != print_entry_values_only)
> +		    list_arg_or_local (&arg, what, values);
> +		  if (entryarg.entry_kind != print_entry_values_no)
> +		    list_arg_or_local (&entryarg, what, values);
> +		  xfree (arg.error);
> +		  xfree (entryarg.error);
> +		}
>  	    }
>  	}
>  

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] Add options to skip unavailable locals
  2013-08-01 12:33       ` Pedro Alves
@ 2013-08-01 13:59         ` Yao Qi
  2013-08-01 14:47           ` Pedro Alves
  2013-08-25  3:43         ` [PATCH 0/2 v2] " Yao Qi
  1 sibling, 1 reply; 26+ messages in thread
From: Yao Qi @ 2013-08-01 13:59 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Eli Zaretskii, gdb-patches

On 08/01/2013 08:33 PM, Pedro Alves wrote:
>> +	      if (skip_unavailable
>> >+		  && (value_entirely_unavailable (val)
>> >+		      /* A scalar object that does not have all bits
>> >+			 available is also considered unavailable,
>> >+			 because all bits contribute to its
>> >+			 representation.  */
>> >+		      || (val_print_scalar_type_p (value_type (val))
>> >+			  && !value_bytes_available (val,
>> >+						     value_embedded_offset (val),
>> >+						     TYPE_LENGTH (value_type (val))))))
>> >+		;
>> >+	      else
> I don't think this has been updated right for entry values.  With
> entry values, we now have_two_  values to account for.  I think
> we need to do this once for each of the regular arg and the
> entry arg?
>

OK, will update the patch to handle both regular arg and entry value.

Is it possible that one is available and the other is not?  If yes, 
when option '--skip-unavailable' is used, some thing we have to think about,

1. if regular arg is available but entry is unavailable, like this,

 
{name="j",type="int",value="4"},{name="j@entry",type="int",value="<unavailable>"}

what is the expected output?  how about displaying regular arg only as 
it is available? like:

   {name="j",type="int",value="4"}

2. if entry is available but regular arg is not, like this,

 
{name="j",type="int",value="<unavailable>"},{name="j@entry",type="int",value="4"}

what is the expected output? how about displaying entry value only as it 
is available? like:

   {name="j@entry",type="int",value="4"}

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] Add options to skip unavailable locals
  2013-08-01 13:59         ` Yao Qi
@ 2013-08-01 14:47           ` Pedro Alves
  0 siblings, 0 replies; 26+ messages in thread
From: Pedro Alves @ 2013-08-01 14:47 UTC (permalink / raw)
  To: Yao Qi; +Cc: Eli Zaretskii, gdb-patches

On 08/01/2013 02:59 PM, Yao Qi wrote:
> On 08/01/2013 08:33 PM, Pedro Alves wrote:

>> I don't think this has been updated right for entry values.  With
>> entry values, we now have_two_  values to account for.  I think
>> we need to do this once for each of the regular arg and the
>> entry arg?
>>
> 
> OK, will update the patch to handle both regular arg and entry value.
> 
> Is it possible that one is available and the other is not?  

Sure.  The debug info just tells us where to fetch the entry
value from (registers, memory, etc.) just like the regular arg.
So it'll depend on which chunks of memory/registers have
been collected.

> If yes, 
> when option '--skip-unavailable' is used, some thing we have to think about,
> 
> 1. if regular arg is available but entry is unavailable, like this,
> 
>  
> {name="j",type="int",value="4"},{name="j@entry",type="int",value="<unavailable>"}
> 
> what is the expected output?  how about displaying regular arg only as 
> it is available? like:
> 
>    {name="j",type="int",value="4"}
> 
> 2. if entry is available but regular arg is not, like this,
> 
>  
> {name="j",type="int",value="<unavailable>"},{name="j@entry",type="int",value="4"}
> 
> what is the expected output? how about displaying entry value only as it 
> is available? like:
> 
>    {name="j@entry",type="int",value="4"}
> 

Yes, that's what I'd expect.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/2] Use mi_getopt_silent
  2013-08-25  3:43         ` [PATCH 0/2 v2] " Yao Qi
@ 2013-08-25  3:43           ` Yao Qi
  2013-08-26  8:58             ` Agovic, Sanimir
  2013-08-26 16:22             ` Pedro Alves
  2013-08-25  3:43           ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
  1 sibling, 2 replies; 26+ messages in thread
From: Yao Qi @ 2013-08-25  3:43 UTC (permalink / raw)
  To: gdb-patches

This patch is to add a new function mi_getopt_silent, which returns -1
silently (without throwing error) when unknown option is met, and use
this function to parse options for command '-stack-list-arguments'.

It makes easier to add a new option in patch 2/2.
gdb:

2013-08-24  Yao Qi  <yao@codesourcery.com>

	* mi/mi-cmd-stack.c (parse_no_frames_option): Remove.
	(mi_cmd_stack_list_args): Use mi_getopt_silent to handle
	options.
	* mi/mi-getopt.c (mi_getopt): Remove.
	(mi_getopt_1): Renamed from mi_getopt.  Add one parameter
	'error_on_unknown'.
	(mi_getopt): Call mi_getopt_1.
	(mi_getopt_silent): New.
	* mi/mi-getopt.h (mi_getopt_silent): Declare.
---
 gdb/mi/mi-cmd-stack.c |   50 ++++++++++++++++++++++++++++++------------------
 gdb/mi/mi-getopt.c    |   35 ++++++++++++++++++++++++++++-----
 gdb/mi/mi-getopt.h    |    8 +++++-
 3 files changed, 66 insertions(+), 27 deletions(-)

diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index e542fc1..b280e7d 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -54,17 +54,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc)
   frame_filters = 1;
 }
 
-/* Parse the --no-frame-filters option in commands where we cannot use
-   mi_getopt. */
-static int
-parse_no_frames_option (const char *arg)
-{
-  if (arg && (strcmp (arg, "--no-frame-filters") == 0))
-    return 1;
-
-  return 0;
-}
-
 /* Print a list of the stack frames.  Args can be none, in which case
    we want to print the whole backtrace, or a pair of numbers
    specifying the frame numbers at which to start and stop the
@@ -284,19 +273,42 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
   enum print_values print_values;
   struct ui_out *uiout = current_uiout;
   int raw_arg = 0;
+  int oind = 0;
   enum py_bt_status result = PY_BT_ERROR;
+  enum opt
+  {
+    NO_FRAME_FILTERS,
+  };
+  static const struct mi_opt opts[] =
+    {
+      {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+      { 0, 0, 0 }
+    };
 
-  if (argc > 0)
-    raw_arg = parse_no_frames_option (argv[0]);
+  while (1)
+    {
+      char *oarg;
+      int opt = mi_getopt_silent ("-stack-list-args", argc, argv, opts,
+				  &oind, &oarg);
+
+      if (opt < 0)
+	break;
+      switch ((enum opt) opt)
+	{
+	case NO_FRAME_FILTERS:
+	  raw_arg = oind;
+	  break;
+	}
+    }
 
-  if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg))
-    error (_("-stack-list-arguments: Usage: " \
+  if (argc - oind != 1 && argc - oind != 3)
+    error (_("-stack-list-arguments: Usage: "	\
 	     "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
 
-  if (argc >= 3)
+  if (argc - oind == 3)
     {
-      frame_low = atoi (argv[1 + raw_arg]);
-      frame_high = atoi (argv[2 + raw_arg]);
+      frame_low = atoi (argv[1 + oind]);
+      frame_high = atoi (argv[2 + oind]);
     }
   else
     {
@@ -306,7 +318,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
       frame_high = -1;
     }
 
-  print_values = mi_parse_print_values (argv[raw_arg]);
+  print_values = mi_parse_print_values (argv[oind]);
 
   /* Let's position fi on the frame at which to start the
      display. Could be the innermost frame if the whole stack needs
diff --git a/gdb/mi/mi-getopt.c b/gdb/mi/mi-getopt.c
index a1e2ccc..0255d22 100644
--- a/gdb/mi/mi-getopt.c
+++ b/gdb/mi/mi-getopt.c
@@ -21,11 +21,14 @@
 #include "mi-getopt.h"
 #include "gdb_string.h"
 
-int
-mi_getopt (const char *prefix,
-	   int argc, char **argv,
-	   const struct mi_opt *opts,
-	   int *oind, char **oarg)
+/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h.
+   When there is an unknown option, if ERROR_ON_UNKNOWN is true, it
+   throws an error, otherwise return -1.  */
+
+static int
+mi_getopt_1 (const char *prefix, int argc, char **argv,
+	     const struct mi_opt *opts, int *oind, char **oarg,
+	     int error_on_unknown)
 {
   char *arg;
   const struct mi_opt *opt;
@@ -71,7 +74,27 @@ mi_getopt (const char *prefix,
 	  return opt->index;
 	}
     }
-  error (_("%s: Unknown option ``%s''"), prefix, arg + 1);
+
+  if (error_on_unknown)
+    error (_("%s: Unknown option ``%s''"), prefix, arg + 1);
+  else
+    return -1;
+}
+
+int
+mi_getopt (const char *prefix,
+	   int argc, char **argv,
+	   const struct mi_opt *opts,
+	   int *oind, char **oarg)
+{
+  return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 1);
+}
+
+int
+mi_getopt_silent (const char *prefix, int argc, char **argv,
+		  const struct mi_opt *opts, int *oind, char **oarg)
+{
+  return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 0);
 }
 
 int 
diff --git a/gdb/mi/mi-getopt.h b/gdb/mi/mi-getopt.h
index 9600353..cabe488 100644
--- a/gdb/mi/mi-getopt.h
+++ b/gdb/mi/mi-getopt.h
@@ -46,11 +46,15 @@ struct mi_opt
    If ARGV[OPTIND] is not an option, -1 is returned and OPTIND updated
    to specify the non-option argument.  OPTARG is set to NULL.
 
-   mi_getopt() calls ``error("%s: Unknown option %c", prefix,
-   option)'' if an unknown option is encountered.  */
+   If an unknown option is encountered, mi_getopt() calls
+   ``error("%s: Unknown option %c", prefix, option)'' and mi_getopt_silent
+   returns -1.  */
 
 extern int mi_getopt (const char *prefix, int argc, char **argv,
 		      const struct mi_opt *opt, int *optind, char **optarg);
+extern int mi_getopt_silent (const char *prefix, int argc, char **argv,
+			     const struct mi_opt *opts, int *oind,
+			     char **oarg);
 
 /* mi_valid_noargs determines if ARGC/ARGV are a valid set of
    parameters to satisfy an MI function that is not supposed to
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 2/2] Add options to skip unavailable locals
  2013-08-25  3:43         ` [PATCH 0/2 v2] " Yao Qi
  2013-08-25  3:43           ` [PATCH 1/2] Use mi_getopt_silent Yao Qi
@ 2013-08-25  3:43           ` Yao Qi
  2013-08-26 16:40             ` Pedro Alves
  1 sibling, 1 reply; 26+ messages in thread
From: Yao Qi @ 2013-08-25  3:43 UTC (permalink / raw)
  To: gdb-patches

V2: Add a new parameter 'skip_unavailable' in function
    list_arg_or_local, and return early if ARG is unavailable and
    SKIP_UNAVAILABLE is true.

This is the patch to add new option '--skip-unavailable' to MI
commands '-stack-list-{locals, arguments, variables}'.  This patch
extends list_args_or_locals to add a new parameter 'skip_unavailable',
and don't list locals or arguments if values are unavailable and
'skip_unavailable' is true.

This is inspecting a trace frame (tfind mode), where only a few
locals have been collected.

-stack-list-locals, no switch vs new switch:

 -stack-list-locals --simple-values
 ^done,locals=[{name="array",type="unsigned char [2]"},{name="i",type="int",value="<unavailable>"}]
 -stack-list-locals --skip-unavailable --simple-values
 ^done,locals=[{name="array",type="unsigned char [2]"}]

-stack-list-arguments, no switch vs new switch:

 -stack-list-arguments --simple-values
 ^done,stack-args=[frame={level="0",args=[{name="j",type="int",value="4"},{name="s",type="char *",value="<unavailable>"}]},frame={level="1",args=[]}]
 -stack-list-arguments --skip-unavailable --simple-values
 ^done,stack-args=[frame={level="0",args=[{name="j",type="int",value="4"}]},frame={level="1",args=[]}]

-stack-list-variables, no switch vs new switch:

 -stack-list-variables --simple-values
 ^done,variables=[{name="j",arg="1",type="int",value="4"},{name="s",arg="1",type="char *",value="<unavailable>"},{name="array",type="unsigned char [2]"},{name="i",type="int",value="<unavailable>"}]
 -stack-list-variables --skip-unavailable --simple-values
 ^done,variables=[{name="j",arg="1",type="int",value="4"},{name="array",type="unsigned char [2]"}]

tests are added to test these new options.

Doc bits were reviewed by Eli
<http://sourceware.org/ml/gdb-patches/2013-07/msg00154.html> and all
comments were addressed.

gdb:

2013-08-24  Pedro Alves  <pedro@codesourcery.com>
	    Yao Qi  <yao@codesourcery.com>

	* mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype.
	(parse_no_frames_option): Remove.
	(mi_cmd_stack_list_locals): Handle --skip-unavailable.
	(mi_cmd_stack_list_args): Adjust.
	(mi_cmd_stack_list_variables): Handle --skip-unavailable.
	(list_arg_or_local): Add new parameter 'skip_unavailable'.  Return
	early if SKIP_UNAVAILABLE is true and ARG->val is unavailable.
	Caller update.
	(list_args_or_locals): New parameter 'skip_unavailable'.
	Handle it.
	* valprint.c (scalar_type_p): Rename to ...
	(val_print_scalar_type_p): ... this.  Make extern.
	(val_print, value_check_printable): Adjust.
	* valprint.h (val_print_scalar_type_p): Declare.
	* value.c (value_entirely_unavailable): New function.
	* value.h (value_entirely_unavailable): Declare.

	* NEWS: Mention the new option "--skip-unavailable" to MI
	commands '-stack-list-locals' '-stack-list-arguments' and
	'-stack-list-variables'.

gdb/doc:

2013-08-24  Pedro Alves  <pedro@codesourcery.com>
	    Yao Qi  <yao@codesourcery.com>

	* gdb.texinfo (GDB/MI Stack Manipulation) <-stack-list-locals>:
	Document new --skip-unavailable option.
	<-stack-list-variables>: Document new --skip-unavailable option.

gdb/testsuite:

2013-08-24  Yao Qi  <yao@codesourcery.com>

	* gdb.trace/entry-values.exp: Test unavailable entry value is
	not shown when option '--skip-unavailable' is specified.
	* gdb.trace/mi-trace-unavailable.exp (test_trace_unavailable):
	Add tests for new option '--skip-unavailable'.
---
 gdb/NEWS                                         |    4 +
 gdb/doc/gdb.texinfo                              |   17 ++++-
 gdb/mi/mi-cmd-stack.c                            |   77 ++++++++++++++++------
 gdb/testsuite/gdb.trace/entry-values.exp         |    5 ++
 gdb/testsuite/gdb.trace/mi-trace-unavailable.exp |    9 +++
 gdb/valprint.c                                   |    8 +-
 gdb/valprint.h                                   |    2 +
 gdb/value.c                                      |   20 ++++++
 gdb/value.h                                      |    4 +
 9 files changed, 119 insertions(+), 27 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index f246ee1..f47eba5 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -91,6 +91,10 @@ show range-stepping
   ** The new command -trace-frame-collected dumps collected variables,
      computed expressions, tvars, memory and registers in a traceframe.
 
+  ** The commands -stack-list-locals, -stack-list-arguments and
+     -stack-list-variables now accept an option "--skip-unavailable".
+     When used, only the available locals or arguments are displayed.
+
 * New system-wide configuration scripts
   A GDB installation now provides scripts suitable for use as system-wide
   configuration scripts for the following systems:
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6d5dec4..7ec3dfb 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -31249,7 +31249,7 @@ For a stack with frame levels 0 through 11:
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-arguments [ --no-frame-filters ] @var{print-values}
+ -stack-list-arguments [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
     [ @var{low-frame} @var{high-frame} ]
 @end smallexample
 
@@ -31269,6 +31269,9 @@ type and value for simple data types, and the name and type for arrays,
 structures and unions.  If the option @code{--no-frame-filters} is
 supplied, then Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, arguments that
+are not available are not listed.  Partially available arguments
+are still displayed, however.
 
 Use of this command to obtain arguments in a single frame is
 deprecated in favor of the @samp{-stack-list-variables} command.
@@ -31453,7 +31456,7 @@ Show a single frame:
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-locals [ --no-frame-filters ] @var{print-values}
+ -stack-list-locals [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
 @end smallexample
 
 Display the local variable names for the selected frame.  If
@@ -31467,6 +31470,10 @@ other data types when the user wishes to explore their values in
 more detail.  If the option @code{--no-frame-filters} is supplied, then
 Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, local variables
+that are not available are not listed.  Partially available local
+variables are still displayed, however.
+
 This command is deprecated in favor of the
 @samp{-stack-list-variables} command.
 
@@ -31497,7 +31504,7 @@ This command is deprecated in favor of the
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-variables [ --no-frame-filters ] @var{print-values}
+ -stack-list-variables [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
 @end smallexample
 
 Display the names of local variables and function arguments for the selected frame.  If
@@ -31508,6 +31515,10 @@ type and value for simple data types, and the name and type for arrays,
 structures and unions.  If the option @code{--no-frame-filters} is
 supplied, then Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, local variables
+and arguments that are not available are not listed.  Partially
+available arguments and local variables are still displayed, however.
+
 @subsubheading Example
 
 @smallexample
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index b280e7d..6b6b8dc 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -39,9 +39,10 @@
 
 enum what_to_list { locals, arguments, all };
 
-static void list_args_or_locals (enum what_to_list what, 
+static void list_args_or_locals (enum what_to_list what,
 				 enum print_values values,
-				 struct frame_info *fi);
+				 struct frame_info *fi,
+				 int skip_unavailable);
 
 /* True if we want to allow Python-based frame filters.  */
 static int frame_filters = 0;
@@ -202,17 +203,21 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
   int oind = 0;
+  int skip_unavailable = 0;
+  int i;
 
   if (argc > 1)
     {
       int i;
       enum opt
       {
-	NO_FRAME_FILTERS
+	NO_FRAME_FILTERS,
+	SKIP_UNAVAILABLE,
       };
       static const struct mi_opt opts[] =
 	{
 	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
 	  { 0, 0, 0 }
 	};
 
@@ -229,6 +234,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
 	    {
 	    case NO_FRAME_FILTERS:
 	      raw_arg = oind;
+	    case SKIP_UNAVAILABLE:
+	      skip_unavailable = 1;
 	      break;
 	    }
 	}
@@ -237,7 +244,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   /* After the last option is parsed, there should be only
      'print-values'.  */
   if (argc - oind != 1)
-    error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES"));
+    error (_("-stack-list-locals: Usage: [--no-frame-filters] "
+	     "[--skip-unavailable] PRINT_VALUES"));
 
   frame = get_selected_frame (NULL);
   print_value = mi_parse_print_values (argv[oind]);
@@ -254,7 +262,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
       if "--no-frame-filters" has been specified from the command.  */
    if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
      {
-       list_args_or_locals (locals, print_value, frame);
+       list_args_or_locals (locals, print_value, frame,
+			    skip_unavailable);
      }
 }
 
@@ -274,14 +283,17 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
   struct ui_out *uiout = current_uiout;
   int raw_arg = 0;
   int oind = 0;
+  int skip_unavailable = 0;
   enum py_bt_status result = PY_BT_ERROR;
   enum opt
   {
     NO_FRAME_FILTERS,
+    SKIP_UNAVAILABLE,
   };
   static const struct mi_opt opts[] =
     {
       {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+      {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
       { 0, 0, 0 }
     };
 
@@ -298,12 +310,16 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
 	case NO_FRAME_FILTERS:
 	  raw_arg = oind;
 	  break;
+	case SKIP_UNAVAILABLE:
+	  skip_unavailable = 1;
+	  break;
 	}
     }
 
   if (argc - oind != 1 && argc - oind != 3)
     error (_("-stack-list-arguments: Usage: "	\
-	     "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
+	     "[--no-frame-filters] [--skip-unavailable] "
+	     "PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
 
   if (argc - oind == 3)
     {
@@ -364,7 +380,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
 	  QUIT;
 	  cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
 	  ui_out_field_int (uiout, "level", i);
-	  list_args_or_locals (arguments, print_values, fi);
+	  list_args_or_locals (arguments, print_values, fi, skip_unavailable);
 	  do_cleanups (cleanup_frame);
 	}
     }
@@ -384,17 +400,20 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
   int oind = 0;
+  int skip_unavailable = 0;
 
   if (argc > 1)
     {
       int i;
       enum opt
       {
-	NO_FRAME_FILTERS
+	NO_FRAME_FILTERS,
+	SKIP_UNAVAILABLE,
       };
       static const struct mi_opt opts[] =
 	{
 	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
 	  { 0, 0, 0 }
 	};
 
@@ -411,6 +430,9 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
 	    case NO_FRAME_FILTERS:
 	      raw_arg = oind;
 	      break;
+	    case SKIP_UNAVAILABLE:
+	      skip_unavailable = 1;
+	      break;
 	    }
 	}
     }
@@ -418,8 +440,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   /* After the last option is parsed, there should be only
      'print-values'.  */
   if (argc - oind != 1)
-    error (_("-stack-list-variables: Usage: " \
-	     "[--no-frame-filters] PRINT_VALUES"));
+    error (_("-stack-list-variables: Usage: [--no-frame-filters] " \
+	     "[--skip-unavailable] PRINT_VALUES"));
 
    frame = get_selected_frame (NULL);
    print_value = mi_parse_print_values (argv[oind]);
@@ -436,7 +458,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
       if "--no-frame-filters" has been specified from the command.  */
    if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
      {
-       list_args_or_locals (all, print_value, frame);
+       list_args_or_locals (all, print_value, frame,
+			    skip_unavailable);
      }
 }
 
@@ -444,19 +467,17 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
    WHAT and VALUES see list_args_or_locals.
 
    Errors are printed as if they would be the parameter value.  Use
-   zeroed ARG iff it should not be printed according to VALUES.  */
+   zeroed ARG iff it should not be printed according to VALUES.  If
+   SKIP_UNAVAILABLE is true, print ARG if it is available.  */
 
 static void
 list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
-		   enum print_values values)
+		   enum print_values values, int skip_unavailable)
 {
   struct cleanup *old_chain;
   struct ui_out *uiout = current_uiout;
   struct ui_file *stb;
 
-  stb = mem_fileopen ();
-  old_chain = make_cleanup_ui_file_delete (stb);
-
   gdb_assert (!arg->val || !arg->error);
   gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL
 	       && arg->error == NULL)
@@ -467,6 +488,20 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
 	      || (arg->entry_kind == print_entry_values_only
 	          && (arg->val || arg->error)));
 
+  if (skip_unavailable && arg->val != NULL
+      && (value_entirely_unavailable (arg->val)
+	  /* A scalar object that does not have all bits available is
+	     also considered unavailable, because all bits contribute
+	     to its representation.  */
+	  || (val_print_scalar_type_p (value_type (arg->val))
+	      && !value_bytes_available (arg->val,
+					 value_embedded_offset (arg->val),
+					 TYPE_LENGTH (value_type (arg->val))))))
+    return;
+
+  stb = mem_fileopen ();
+  old_chain = make_cleanup_ui_file_delete (stb);
+
   if (values != PRINT_NO_VALUES || what == all)
     make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
 
@@ -516,11 +551,13 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
 
 /* Print a list of the objects for the frame FI in a certain form,
    which is determined by VALUES.  The objects can be locals,
-   arguments or both, which is determined by WHAT.  */
+   arguments or both, which is determined by WHAT.  If SKIP_UNAVAILABLE
+   is true, print the arguments or local variables whose values are
+   available.  */
 
 static void
 list_args_or_locals (enum what_to_list what, enum print_values values,
-		     struct frame_info *fi)
+		     struct frame_info *fi, int skip_unavailable)
 {
   struct block *block;
   struct symbol *sym;
@@ -623,9 +660,9 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
 		}
 
 	      if (arg.entry_kind != print_entry_values_only)
-		list_arg_or_local (&arg, what, values);
+		list_arg_or_local (&arg, what, values, skip_unavailable);
 	      if (entryarg.entry_kind != print_entry_values_no)
-		list_arg_or_local (&entryarg, what, values);
+		list_arg_or_local (&entryarg, what, values, skip_unavailable);
 	      xfree (arg.error);
 	      xfree (entryarg.error);
 	    }
diff --git a/gdb/testsuite/gdb.trace/entry-values.exp b/gdb/testsuite/gdb.trace/entry-values.exp
index bb62e5d..85306ad 100644
--- a/gdb/testsuite/gdb.trace/entry-values.exp
+++ b/gdb/testsuite/gdb.trace/entry-values.exp
@@ -276,4 +276,9 @@ gdb_test "tfind" "Found trace frame 0, .*" "tfind start"
 # Since 'global2' is not collected, j@entry is expected to be 'unavailable'.
 gdb_test "bt 1" "#0 .* foo \\(i=\[-\]?$decimal, i@entry=2, j=\[-\]?$decimal, j@entry=<unavailable>\\).*"
 
+# Test that unavailable "j@entry" is not shown when command option
+# --skip-unavailable is used.
+gdb_test "interpreter-exec mi \"-stack-list-arguments --skip-unavailable --simple-values\"" \
+    "\r\n\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"i\",type=\"int\",value=\".*\"},{name=\"i@entry\",type=\"int\",value=\"2\"},{name=\"j\",type=\"int\",value=\".*\"}\\\]},frame=.*\\\].*"
+
 gdb_test "tfind" "Target failed to find requested trace frame\..*"
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index d96ec8b..c69891b 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -106,16 +106,25 @@ proc test_trace_unavailable { data_source } {
 	mi_gdb_test "-stack-list-locals --simple-values" \
 	    ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \
 	    "-stack-list-locals --simple-values"
+	mi_gdb_test "-stack-list-locals --skip-unavailable --simple-values" \
+	    ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \
+	    "-stack-list-locals --skip-unavailable --simple-values"
 
 	# Test MI command '-stack-list-arguments'.
 	mi_gdb_test "-stack-list-arguments --simple-values" \
 	    ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\},\{name=\"s\",type=\"char \\\*\",value=\"<unavailable>\"\}\\\]\},.*\}.*" \
 	    "-stack-list-arguments --simple-values"
+	mi_gdb_test "-stack-list-arguments --skip-unavailable --simple-values" \
+	    ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\}\\\]\},.*\}.*" \
+	    "-stack-list-arguments --skip-unavailable --simple-values"
 
 	# Test MI command '-stack-list-variables'.
 	mi_gdb_test "-stack-list-variables --simple-values" \
 	    ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"s\",arg=\"1\",type=\"char \\\*\",value=\"<unavailable>\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \
 	    "-stack-list-variables --simple-values"
+	mi_gdb_test "-stack-list-variables --skip-unavailable --simple-values" \
+	    ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \
+	    "-stack-list-variables --skip-unavailable --simple-values"
 
 	mi_gdb_test "-trace-find frame-number 1" \
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 753ae34..0f6d65e 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -275,8 +275,8 @@ show_symbol_print (struct ui_file *file, int from_tty,
    we want to print scalar arguments, but not aggregate arguments.
    This function distinguishes between the two.  */
 
-static int
-scalar_type_p (struct type *type)
+int
+val_print_scalar_type_p (struct type *type)
 {
   CHECK_TYPEDEF (type);
   while (TYPE_CODE (type) == TYPE_CODE_REF)
@@ -770,7 +770,7 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 
   /* Handle summary mode.  If the value is a scalar, print it;
      otherwise, print an ellipsis.  */
-  if (options->summary && !scalar_type_p (type))
+  if (options->summary && !val_print_scalar_type_p (type))
     {
       fprintf_filtered (stream, "...");
       return;
@@ -802,7 +802,7 @@ value_check_printable (struct value *val, struct ui_file *stream,
 
   if (value_entirely_optimized_out (val))
     {
-      if (options->summary && !scalar_type_p (value_type (val)))
+      if (options->summary && !val_print_scalar_type_p (value_type (val)))
 	fprintf_filtered (stream, "...");
       else
 	val_print_optimized_out (stream);
diff --git a/gdb/valprint.h b/gdb/valprint.h
index 2959098..e7073b6 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -211,4 +211,6 @@ extern void generic_printstr (struct ui_file *stream, struct type *type,
 
 extern void output_command_const (const char *args, int from_tty);
 
+extern int val_print_scalar_type_p (struct type *type);
+
 #endif
diff --git a/gdb/value.c b/gdb/value.c
index 09ab1bb..d96c07b 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -353,6 +353,26 @@ value_entirely_available (struct value *value)
   return 0;
 }
 
+int
+value_entirely_unavailable (struct value *value)
+{
+  /* We can only tell whether the whole value is available when we try
+     to read it.  */
+  if (value->lazy)
+    value_fetch_lazy (value);
+
+  if (VEC_length (range_s, value->unavailable) == 1)
+    {
+      struct range *t = VEC_index (range_s, value->unavailable, 0);
+
+      if (t->offset == 0
+	  && t->length == TYPE_LENGTH (value_enclosing_type (value)))
+	return 1;
+    }
+
+  return 0;
+}
+
 void
 mark_value_bytes_unavailable (struct value *value, int offset, int length)
 {
diff --git a/gdb/value.h b/gdb/value.h
index bef193c..f03cf76 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -435,6 +435,10 @@ extern int value_bytes_available (const struct value *value,
    whole object is unavailable.  */
 extern int value_entirely_available (struct value *value);
 
+/* Like value_entirely_available, but return false if any byte in the
+   whole object is available.  */
+extern int value_entirely_unavailable (struct value *value);
+
 /* Mark VALUE's content bytes starting at OFFSET and extending for
    LENGTH bytes as unavailable.  */
 
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 0/2 v2] Add options to skip unavailable locals
  2013-08-01 12:33       ` Pedro Alves
  2013-08-01 13:59         ` Yao Qi
@ 2013-08-25  3:43         ` Yao Qi
  2013-08-25  3:43           ` [PATCH 1/2] Use mi_getopt_silent Yao Qi
  2013-08-25  3:43           ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
  1 sibling, 2 replies; 26+ messages in thread
From: Yao Qi @ 2013-08-25  3:43 UTC (permalink / raw)
  To: gdb-patches

Hi,
In the review to '[PATCH 2/2] Add options to skip unavailable locals',
Pedro pointed out two things here
<http://sourceware.org/ml/gdb-patches/2013-08/msg00019.html>

On 08/01/2013 08:33 PM, Pedro Alves wrote:>> @@ -295,18 +293,39 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
>> >    struct ui_out *uiout = current_uiout;
>> >    int raw_arg = 0;
>> >    enum py_bt_status result = PY_BT_ERROR;
>> >+  int skip_unavailable = 0;
>> >+  int oind = 0;
>> >  
>> >-  if (argc > 0)
>> >-    raw_arg = parse_no_frames_option (argv[0]);
>> >+  /* We can't use mi_getopt here, because the number of options is not
>> >+     determined.  */
> Hmm.  Isn't that easy to fix though?  We'd just need an mi_getopt
> variant that doesn't error out when it sees an unknown option, but
> instead returns that option's position (similarly to getopt).  It's
> then the caller's responsibility to parse the rest of the option
> string.

I add a variant mi_getopt_silent in patch 1/2 and use it here.

>> >@@ -597,7 +626,6 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
>> >  	  if (print_me)
>> >  	    {
>> >  	      struct symbol *sym2;
>> >-	      struct frame_arg arg, entryarg;
>> >  
>> >  	      if (SYMBOL_IS_ARGUMENT (sym))
>> >  		sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
>> >@@ -607,33 +635,56 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
>> >  		sym2 = sym;
>> >  	      gdb_assert (sym2 != NULL);
>> >  
>> >-	      memset (&arg, 0, sizeof (arg));
>> >-	      arg.sym = sym2;
>> >-	      arg.entry_kind = print_entry_values_no;
>> >-	      memset (&entryarg, 0, sizeof (entryarg));
>> >-	      entryarg.sym = sym2;
>> >-	      entryarg.entry_kind = print_entry_values_no;
>> >-
>> >-	      switch (values)
>> >+	      /* Need to read the value before being able to determine
>> >+		 whether its unavailable.  */
>> >+	      if (values == PRINT_ALL_VALUES
>> >+		  || values == PRINT_SIMPLE_VALUES
>> >+		  || skip_unavailable)
>> >+		val = read_var_value (sym2, fi);
>> >+
>> >+	      if (skip_unavailable
>> >+		  && (value_entirely_unavailable (val)
>> >+		      /* A scalar object that does not have all bits
>> >+			 available is also considered unavailable,
>> >+			 because all bits contribute to its
>> >+			 representation.  */
>> >+		      || (val_print_scalar_type_p (value_type (val))
>> >+			  && !value_bytes_available (val,
>> >+						     value_embedded_offset (val),
>> >+						     TYPE_LENGTH (value_type (val))))))
>> >+		;
>> >+	      else
> I don't think this has been updated right for entry values.  With
> entry values, we now have_two_  values to account for.  I think
> we need to do this once for each of the regular arg and the
> entry arg?
> 

Patch 2/2 is updated to handle entry values by adding a parameter
'skip_unavailable' in function list_arg_or_local.

Other comments on changelog and doc are addressed too.  Regression
tested on x86_64-linux both native and gdbserver.

*** BLURB HERE ***

Yao Qi (2):
  Use mi_getopt_silent
  Add options to skip unavailable locals

 gdb/NEWS                                         |    4 +
 gdb/doc/gdb.texinfo                              |   17 +++-
 gdb/mi/mi-cmd-stack.c                            |  127 +++++++++++++++-------
 gdb/mi/mi-getopt.c                               |   35 +++++-
 gdb/mi/mi-getopt.h                               |    8 +-
 gdb/testsuite/gdb.trace/entry-values.exp         |    5 +
 gdb/testsuite/gdb.trace/mi-trace-unavailable.exp |    9 ++
 gdb/valprint.c                                   |    8 +-
 gdb/valprint.h                                   |    2 +
 gdb/value.c                                      |   20 ++++
 gdb/value.h                                      |    4 +
 11 files changed, 185 insertions(+), 54 deletions(-)

-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH 1/2] Use mi_getopt_silent
  2013-08-25  3:43           ` [PATCH 1/2] Use mi_getopt_silent Yao Qi
@ 2013-08-26  8:58             ` Agovic, Sanimir
  2013-08-26 10:18               ` Yao Qi
  2013-08-26 16:22             ` Pedro Alves
  1 sibling, 1 reply; 26+ messages in thread
From: Agovic, Sanimir @ 2013-08-26  8:58 UTC (permalink / raw)
  To: 'Yao Qi'; +Cc: gdb-patches

Hello Yao,

I`d rather catch the exception in mi_cmd_stack_list_args to prevent the 
error to bubble up to upper layers. This requires the use of 
throw_error (NOT_FOUND_ERROR, ...) instead of error (...) in mi_getopt
to catch the right exception (*) and re-throw otherwise.
Due to the poor exception handling in gdb this may lead to some boilerplate
code. On the other side it keeps the interface simple & consistent 
e.g. (*) in the patch below mi_getopt_silent may still be verbose/throw.

-Sanimir

> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-owner@sourceware.org] On Behalf
> Of Yao Qi
> Sent: Sunday, August 25, 2013 05:42 AM
> To: gdb-patches@sourceware.org
> Subject: [PATCH 1/2] Use mi_getopt_silent
> 
> This patch is to add a new function mi_getopt_silent, which returns -1
> silently (without throwing error) when unknown option is met, and use
> this function to parse options for command '-stack-list-arguments'.
> 
> It makes easier to add a new option in patch 2/2.
> gdb:
> 
> 2013-08-24  Yao Qi  <yao@codesourcery.com>
> 
> 	* mi/mi-cmd-stack.c (parse_no_frames_option): Remove.
> 	(mi_cmd_stack_list_args): Use mi_getopt_silent to handle
> 	options.	
> 	* mi/mi-getopt.c (mi_getopt): Remove.
> 	(mi_getopt_1): Renamed from mi_getopt.  Add one parameter
> 	'error_on_unknown'.
> 	(mi_getopt): Call mi_getopt_1.
> 	(mi_getopt_silent): New.
> 	* mi/mi-getopt.h (mi_getopt_silent): Declare.
> ---
>  gdb/mi/mi-cmd-stack.c |   50 ++++++++++++++++++++++++++++++------------------
>  gdb/mi/mi-getopt.c    |   35 ++++++++++++++++++++++++++++-----
>  gdb/mi/mi-getopt.h    |    8 +++++-
>  3 files changed, 66 insertions(+), 27 deletions(-)
> 
> diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
> index e542fc1..b280e7d 100644
> --- a/gdb/mi/mi-cmd-stack.c
> +++ b/gdb/mi/mi-cmd-stack.c
> @@ -54,17 +54,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc)
>    frame_filters = 1;
>  }
> 
> -/* Parse the --no-frame-filters option in commands where we cannot use
> -   mi_getopt. */
> -static int
> -parse_no_frames_option (const char *arg)
> -{
> -  if (arg && (strcmp (arg, "--no-frame-filters") == 0))
> -    return 1;
> -
> -  return 0;
> -}
> -
>  /* Print a list of the stack frames.  Args can be none, in which case
>     we want to print the whole backtrace, or a pair of numbers
>     specifying the frame numbers at which to start and stop the
> @@ -284,19 +273,42 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
>    enum print_values print_values;
>    struct ui_out *uiout = current_uiout;
>    int raw_arg = 0;
> +  int oind = 0;
>    enum py_bt_status result = PY_BT_ERROR;
> +  enum opt
> +  {
> +    NO_FRAME_FILTERS,
> +  };
> +  static const struct mi_opt opts[] =
> +    {
> +      {"-no-frame-filters", NO_FRAME_FILTERS, 0},
> +      { 0, 0, 0 }
> +    };
> 
> -  if (argc > 0)
> -    raw_arg = parse_no_frames_option (argv[0]);
> +  while (1)
> +    {
> +      char *oarg;
> +      int opt = mi_getopt_silent ("-stack-list-args", argc, argv, opts,
> +				  &oind, &oarg);
> +
> +      if (opt < 0)
> +	break;
> +      switch ((enum opt) opt)
> +	{
> +	case NO_FRAME_FILTERS:
> +	  raw_arg = oind;
> +	  break;
> +	}
> +    }
> 
> -  if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg))
> -    error (_("-stack-list-arguments: Usage: " \
> +  if (argc - oind != 1 && argc - oind != 3)
> +    error (_("-stack-list-arguments: Usage: "	\
>  	     "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
> 
> -  if (argc >= 3)
> +  if (argc - oind == 3)
>      {
> -      frame_low = atoi (argv[1 + raw_arg]);
> -      frame_high = atoi (argv[2 + raw_arg]);
> +      frame_low = atoi (argv[1 + oind]);
> +      frame_high = atoi (argv[2 + oind]);
>      }
>    else
>      {
> @@ -306,7 +318,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
>        frame_high = -1;
>      }
> 
> -  print_values = mi_parse_print_values (argv[raw_arg]);
> +  print_values = mi_parse_print_values (argv[oind]);
> 
>    /* Let's position fi on the frame at which to start the
>       display. Could be the innermost frame if the whole stack needs
> diff --git a/gdb/mi/mi-getopt.c b/gdb/mi/mi-getopt.c
> index a1e2ccc..0255d22 100644
> --- a/gdb/mi/mi-getopt.c
> +++ b/gdb/mi/mi-getopt.c
> @@ -21,11 +21,14 @@
>  #include "mi-getopt.h"
>  #include "gdb_string.h"
> 
> -int
> -mi_getopt (const char *prefix,
> -	   int argc, char **argv,
> -	   const struct mi_opt *opts,
> -	   int *oind, char **oarg)
> +/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h.
> +   When there is an unknown option, if ERROR_ON_UNKNOWN is true, it
> +   throws an error, otherwise return -1.  */
> +
> +static int
> +mi_getopt_1 (const char *prefix, int argc, char **argv,
> +	     const struct mi_opt *opts, int *oind, char **oarg,
> +	     int error_on_unknown)
>  {
>    char *arg;
>    const struct mi_opt *opt;
> @@ -71,7 +74,27 @@ mi_getopt (const char *prefix,
>  	  return opt->index;
>  	}
>      }
> -  error (_("%s: Unknown option ``%s''"), prefix, arg + 1);
> +
> +  if (error_on_unknown)
> +    error (_("%s: Unknown option ``%s''"), prefix, arg + 1);
> +  else
> +    return -1;
> +}
> +
> +int
> +mi_getopt (const char *prefix,
> +	   int argc, char **argv,
> +	   const struct mi_opt *opts,
> +	   int *oind, char **oarg)
> +{
> +  return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 1);
> +}
> +
> +int
> +mi_getopt_silent (const char *prefix, int argc, char **argv,
> +		  const struct mi_opt *opts, int *oind, char **oarg)
> +{
> +  return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 0);
>  }
> 
>  int
> diff --git a/gdb/mi/mi-getopt.h b/gdb/mi/mi-getopt.h
> index 9600353..cabe488 100644
> --- a/gdb/mi/mi-getopt.h
> +++ b/gdb/mi/mi-getopt.h
> @@ -46,11 +46,15 @@ struct mi_opt
>     If ARGV[OPTIND] is not an option, -1 is returned and OPTIND updated
>     to specify the non-option argument.  OPTARG is set to NULL.
> 
> -   mi_getopt() calls ``error("%s: Unknown option %c", prefix,
> -   option)'' if an unknown option is encountered.  */
> +   If an unknown option is encountered, mi_getopt() calls
> +   ``error("%s: Unknown option %c", prefix, option)'' and mi_getopt_silent
> +   returns -1.  */
> 
>  extern int mi_getopt (const char *prefix, int argc, char **argv,
>  		      const struct mi_opt *opt, int *optind, char **optarg);
> +extern int mi_getopt_silent (const char *prefix, int argc, char **argv,
> +			     const struct mi_opt *opts, int *oind,
> +			     char **oarg);
> 
>  /* mi_valid_noargs determines if ARGC/ARGV are a valid set of
>     parameters to satisfy an MI function that is not supposed to
> --
> 1.7.7.6

Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] Use mi_getopt_silent
  2013-08-26  8:58             ` Agovic, Sanimir
@ 2013-08-26 10:18               ` Yao Qi
  2013-08-26 16:01                 ` Pedro Alves
  0 siblings, 1 reply; 26+ messages in thread
From: Yao Qi @ 2013-08-26 10:18 UTC (permalink / raw)
  To: Agovic, Sanimir; +Cc: gdb-patches

On 08/26/2013 04:58 PM, Agovic, Sanimir wrote:
> I`d rather catch the exception in mi_cmd_stack_list_args to prevent the
> error to bubble up to upper layers. This requires the use of
> throw_error (NOT_FOUND_ERROR, ...) instead of error (...) in mi_getopt
> to catch the right exception (*) and re-throw otherwise.

Sanimir, thanks for your comments.

I am not inclined to use exception here because exception handling in
GDB is poor.  On the other hand, I don't like using exception to
control the program flow.  In some commands, there is no unknown
options, and in other commands, there may be unknown options.  Both of
them are expected.  In the former, GDB can throw an error, and in the
later, GDB can silently return -1.

> Due to the poor exception handling in gdb this may lead to some boilerplate
> code. On the other side it keeps the interface simple & consistent
> e.g. (*) in the patch below mi_getopt_silent may still be verbose/throw.

Yes, mi_getopt_silent may throw error when the argument of an option is
missing, because it is wrong.  "silent" here is only for unknown
options, which is expected in some commands.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] Use mi_getopt_silent
  2013-08-26 10:18               ` Yao Qi
@ 2013-08-26 16:01                 ` Pedro Alves
  0 siblings, 0 replies; 26+ messages in thread
From: Pedro Alves @ 2013-08-26 16:01 UTC (permalink / raw)
  To: Yao Qi; +Cc: Agovic, Sanimir, gdb-patches

On 08/26/2013 11:16 AM, Yao Qi wrote:
> On 08/26/2013 04:58 PM, Agovic, Sanimir wrote:
>> I`d rather catch the exception in mi_cmd_stack_list_args to prevent the
>> error to bubble up to upper layers. This requires the use of
>> throw_error (NOT_FOUND_ERROR, ...) instead of error (...) in mi_getopt
>> to catch the right exception (*) and re-throw otherwise.
> 
> Sanimir, thanks for your comments.
> 
> I am not inclined to use exception here because exception handling in
> GDB is poor.  On the other hand, I don't like using exception to
> control the program flow.  In some commands, there is no unknown
> options, and in other commands, there may be unknown options.  Both of
> them are expected.  In the former, GDB can throw an error, and in the
> later, GDB can silently return -1.

Agreed.  Sometimes it's hard to avoid going the throw + swallow-error
route, but in this case it's trivial.

>> Due to the poor exception handling in gdb this may lead to some boilerplate
>> code. On the other side it keeps the interface simple & consistent
>> e.g. (*) in the patch below mi_getopt_silent may still be verbose/throw.
> 
> Yes, mi_getopt_silent may throw error when the argument of an option is
> missing, because it is wrong.  "silent" here is only for unknown
> options, which is expected in some commands.

Maybe it's just "silent" that's the confusing term to use.  Maybe
mi_getopt_unknown or even something longer would make it less
confusing.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] Use mi_getopt_silent
  2013-08-25  3:43           ` [PATCH 1/2] Use mi_getopt_silent Yao Qi
  2013-08-26  8:58             ` Agovic, Sanimir
@ 2013-08-26 16:22             ` Pedro Alves
  2013-08-27  3:30               ` Yao Qi
  1 sibling, 1 reply; 26+ messages in thread
From: Pedro Alves @ 2013-08-26 16:22 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 08/25/2013 04:42 AM, Yao Qi wrote:
> This patch is to add a new function mi_getopt_silent, which returns -1
> silently (without throwing error) when unknown option is met, and use
> this function to parse options for command '-stack-list-arguments'.
> 
> It makes easier to add a new option in patch 2/2.

Thanks!  This is OK.  A few minor suggestions below.

> 2013-08-24  Yao Qi  <yao@codesourcery.com>
> 
> 	* mi/mi-cmd-stack.c (parse_no_frames_option): Remove.
> 	(mi_cmd_stack_list_args): Use mi_getopt_silent to handle
> 	options.
> 	* mi/mi-getopt.c (mi_getopt): Remove.

This "remove" got me confused, and made think it was a
ChangeLog mistake.

> 	(mi_getopt_1): Renamed from mi_getopt.  Add one parameter
> 	'error_on_unknown'.
> 	(mi_getopt): Call mi_getopt_1.
> 	(mi_getopt_silent): New.

Here's what I suggest:

 	* mi/mi-getopt.c (mi_getopt): Rename to ...
 	(mi_getopt_1): ... this.  Add parameter 'error_on_unknown'.
 	(mi_getopt): Reimplement as wrapper around mi_getopt_1.
 	(mi_getopt_silent): New function.

> 	* mi/mi-getopt.h (mi_getopt_silent): Declare.



> --- a/gdb/mi/mi-getopt.c
> +++ b/gdb/mi/mi-getopt.c
> @@ -21,11 +21,14 @@
>  #include "mi-getopt.h"
>  #include "gdb_string.h"
>  
> -int
> -mi_getopt (const char *prefix,
> -	   int argc, char **argv,
> -	   const struct mi_opt *opts,
> -	   int *oind, char **oarg)
> +/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h.
> +   When there is an unknown option, if ERROR_ON_UNKNOWN is true, it
> +   throws an error, otherwise return -1.  */

("throws" -> "returns").  I'd suggest:

   If an unknown option is encountered, if ERROR_ON_UNKNOWN is true,
   throw an error, otherwise return -1.  */

> +
> +static int
> +mi_getopt_1 (const char *prefix, int argc, char **argv,
> +	     const struct mi_opt *opts, int *oind, char **oarg,
> +	     int error_on_unknown)
>  {

>  
>  int 
> diff --git a/gdb/mi/mi-getopt.h b/gdb/mi/mi-getopt.h
> index 9600353..cabe488 100644
> --- a/gdb/mi/mi-getopt.h
> +++ b/gdb/mi/mi-getopt.h
> @@ -46,11 +46,15 @@ struct mi_opt
>     If ARGV[OPTIND] is not an option, -1 is returned and OPTIND updated
>     to specify the non-option argument.  OPTARG is set to NULL.
>  
> -   mi_getopt() calls ``error("%s: Unknown option %c", prefix,
> -   option)'' if an unknown option is encountered.  */
> +   If an unknown option is encountered, mi_getopt() calls
> +   ``error("%s: Unknown option %c", prefix, option)'' and mi_getopt_silent
> +   returns -1.  */

I'd suggest s/and/while/.

>  
>  extern int mi_getopt (const char *prefix, int argc, char **argv,
>  		      const struct mi_opt *opt, int *optind, char **optarg);
> +extern int mi_getopt_silent (const char *prefix, int argc, char **argv,
> +			     const struct mi_opt *opts, int *oind,
> +			     char **oarg);

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] Add options to skip unavailable locals
  2013-08-25  3:43           ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
@ 2013-08-26 16:40             ` Pedro Alves
  2013-08-27  5:22               ` Yao Qi
  0 siblings, 1 reply; 26+ messages in thread
From: Pedro Alves @ 2013-08-26 16:40 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Looks good to me.  A few tiny-tiny suggestions below:

> 	* NEWS: Mention the new option "--skip-unavailable" to MI
> 	commands '-stack-list-locals' '-stack-list-arguments' and
                                     ^
Missing comma.

> 	'-stack-list-variables'.



>     Errors are printed as if they would be the parameter value.  Use
> -   zeroed ARG iff it should not be printed according to VALUES.  */
> +   zeroed ARG iff it should not be printed according to VALUES.  If
> +   SKIP_UNAVAILABLE is true, print ARG if it is available.  */

"is true, only print ARG"

> 
>  static void
>  list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
> -		   enum print_values values)
> +		   enum print_values values, int skip_unavailable)
>  {



>  /* Print a list of the objects for the frame FI in a certain form,
>     which is determined by VALUES.  The objects can be locals,
> -   arguments or both, which is determined by WHAT.  */
> +   arguments or both, which is determined by WHAT.  If SKIP_UNAVAILABLE
> +   is true, print the arguments or local variables whose values are
> +   available.  */

"is true, only print the"

>
>  static void
>  list_args_or_locals (enum what_to_list what, enum print_values values,
> -		     struct frame_info *fi)
> +		     struct frame_info *fi, int skip_unavailable)
>  {
>    struct block *block;

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] Use mi_getopt_silent
  2013-08-26 16:22             ` Pedro Alves
@ 2013-08-27  3:30               ` Yao Qi
  2013-08-27 11:43                 ` Pedro Alves
  0 siblings, 1 reply; 26+ messages in thread
From: Yao Qi @ 2013-08-27  3:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 08/27/2013 12:22 AM, Pedro Alves wrote:
> Here's what I suggest:
> 
>   	* mi/mi-getopt.c (mi_getopt): Rename to ...
>   	(mi_getopt_1): ... this.  Add parameter 'error_on_unknown'.
>   	(mi_getopt): Reimplement as wrapper around mi_getopt_1.
>   	(mi_getopt_silent): New function.
> 

OK.

>> >	* mi/mi-getopt.h (mi_getopt_silent): Declare.
> 
> 
>> >--- a/gdb/mi/mi-getopt.c
>> >+++ b/gdb/mi/mi-getopt.c
>> >@@ -21,11 +21,14 @@
>> >  #include "mi-getopt.h"
>> >  #include "gdb_string.h"
>> >  
>> >-int
>> >-mi_getopt (const char *prefix,
>> >-	   int argc, char **argv,
>> >-	   const struct mi_opt *opts,
>> >-	   int *oind, char **oarg)
>> >+/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h.
>> >+   When there is an unknown option, if ERROR_ON_UNKNOWN is true, it
>> >+   throws an error, otherwise return -1.  */
> ("throws" -> "returns").  I'd suggest:
> 

I assume you meant "return" -> "returns" here.

>     If an unknown option is encountered, if ERROR_ON_UNKNOWN is true,
>     throw an error, otherwise return -1.  */
> 

Anyway, copy this into the patch.  I also rename mi_getopt_silent to
mi_getopt_allow_unknown.  Patch below is what I committed.

-- 
Yao (齐尧)

gdb:

2013-08-27  Yao Qi  <yao@codesourcery.com>

	* mi/mi-cmd-stack.c (parse_no_frames_option): Remove.
	(mi_cmd_stack_list_args): Use mi_getopt_allow_unknown to
	handle options.
	* mi/mi-getopt.c (mi_getopt): Rename to ...
	(mi_getopt_1): ... this.  Add parameter 'error_on_unknown'.
	(mi_getopt): Reimplement as wrapper around mi_getopt_1.
	(mi_getopt_allow_unknown): New function.
	* mi/mi-getopt.h (mi_getopt_allow_unknown): Declare.
---
 gdb/mi/mi-cmd-stack.c |   50 ++++++++++++++++++++++++++++++------------------
 gdb/mi/mi-getopt.c    |   35 ++++++++++++++++++++++++++++-----
 gdb/mi/mi-getopt.h    |    8 +++++-
 3 files changed, 66 insertions(+), 27 deletions(-)

diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index e542fc1..2df97e2 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -54,17 +54,6 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc)
   frame_filters = 1;
 }
 
-/* Parse the --no-frame-filters option in commands where we cannot use
-   mi_getopt. */
-static int
-parse_no_frames_option (const char *arg)
-{
-  if (arg && (strcmp (arg, "--no-frame-filters") == 0))
-    return 1;
-
-  return 0;
-}
-
 /* Print a list of the stack frames.  Args can be none, in which case
    we want to print the whole backtrace, or a pair of numbers
    specifying the frame numbers at which to start and stop the
@@ -284,19 +273,42 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
   enum print_values print_values;
   struct ui_out *uiout = current_uiout;
   int raw_arg = 0;
+  int oind = 0;
   enum py_bt_status result = PY_BT_ERROR;
+  enum opt
+  {
+    NO_FRAME_FILTERS,
+  };
+  static const struct mi_opt opts[] =
+    {
+      {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+      { 0, 0, 0 }
+    };
 
-  if (argc > 0)
-    raw_arg = parse_no_frames_option (argv[0]);
+  while (1)
+    {
+      char *oarg;
+      int opt = mi_getopt_allow_unknown ("-stack-list-args", argc, argv,
+					 opts, &oind, &oarg);
+
+      if (opt < 0)
+	break;
+      switch ((enum opt) opt)
+	{
+	case NO_FRAME_FILTERS:
+	  raw_arg = oind;
+	  break;
+	}
+    }
 
-  if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg))
-    error (_("-stack-list-arguments: Usage: " \
+  if (argc - oind != 1 && argc - oind != 3)
+    error (_("-stack-list-arguments: Usage: "	\
 	     "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
 
-  if (argc >= 3)
+  if (argc - oind == 3)
     {
-      frame_low = atoi (argv[1 + raw_arg]);
-      frame_high = atoi (argv[2 + raw_arg]);
+      frame_low = atoi (argv[1 + oind]);
+      frame_high = atoi (argv[2 + oind]);
     }
   else
     {
@@ -306,7 +318,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
       frame_high = -1;
     }
 
-  print_values = mi_parse_print_values (argv[raw_arg]);
+  print_values = mi_parse_print_values (argv[oind]);
 
   /* Let's position fi on the frame at which to start the
      display. Could be the innermost frame if the whole stack needs
diff --git a/gdb/mi/mi-getopt.c b/gdb/mi/mi-getopt.c
index a1e2ccc..f207249 100644
--- a/gdb/mi/mi-getopt.c
+++ b/gdb/mi/mi-getopt.c
@@ -21,11 +21,14 @@
 #include "mi-getopt.h"
 #include "gdb_string.h"
 
-int
-mi_getopt (const char *prefix,
-	   int argc, char **argv,
-	   const struct mi_opt *opts,
-	   int *oind, char **oarg)
+/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h.
+   When there is an unknown option, if ERROR_ON_UNKNOWN is true,
+   throw an error, otherwise return -1.  */
+
+static int
+mi_getopt_1 (const char *prefix, int argc, char **argv,
+	     const struct mi_opt *opts, int *oind, char **oarg,
+	     int error_on_unknown)
 {
   char *arg;
   const struct mi_opt *opt;
@@ -71,7 +74,27 @@ mi_getopt (const char *prefix,
 	  return opt->index;
 	}
     }
-  error (_("%s: Unknown option ``%s''"), prefix, arg + 1);
+
+  if (error_on_unknown)
+    error (_("%s: Unknown option ``%s''"), prefix, arg + 1);
+  else
+    return -1;
+}
+
+int
+mi_getopt (const char *prefix,
+	   int argc, char **argv,
+	   const struct mi_opt *opts,
+	   int *oind, char **oarg)
+{
+  return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 1);
+}
+
+int
+mi_getopt_allow_unknown (const char *prefix, int argc, char **argv,
+			 const struct mi_opt *opts, int *oind, char **oarg)
+{
+  return mi_getopt_1 (prefix, argc, argv, opts, oind, oarg, 0);
 }
 
 int 
diff --git a/gdb/mi/mi-getopt.h b/gdb/mi/mi-getopt.h
index 9600353..7db0bf4 100644
--- a/gdb/mi/mi-getopt.h
+++ b/gdb/mi/mi-getopt.h
@@ -46,11 +46,15 @@ struct mi_opt
    If ARGV[OPTIND] is not an option, -1 is returned and OPTIND updated
    to specify the non-option argument.  OPTARG is set to NULL.
 
-   mi_getopt() calls ``error("%s: Unknown option %c", prefix,
-   option)'' if an unknown option is encountered.  */
+   If an unknown option is encountered, mi_getopt() calls
+   ``error("%s: Unknown option %c", prefix, option)'' while
+   mi_getopt_allow_unknown returns -1.  */
 
 extern int mi_getopt (const char *prefix, int argc, char **argv,
 		      const struct mi_opt *opt, int *optind, char **optarg);
+extern int mi_getopt_allow_unknown (const char *prefix, int argc,
+				    char **argv, const struct mi_opt *opts,
+				    int *oind, char **oarg);
 
 /* mi_valid_noargs determines if ARGC/ARGV are a valid set of
    parameters to satisfy an MI function that is not supposed to
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/2] Add options to skip unavailable locals
  2013-08-26 16:40             ` Pedro Alves
@ 2013-08-27  5:22               ` Yao Qi
  0 siblings, 0 replies; 26+ messages in thread
From: Yao Qi @ 2013-08-27  5:22 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 08/27/2013 12:40 AM, Pedro Alves wrote:
> Looks good to me.  A few tiny-tiny suggestions below:
> 
>> >	* NEWS: Mention the new option "--skip-unavailable" to MI
>> >	commands '-stack-list-locals' '-stack-list-arguments' and
>                                       ^
> Missing comma.
> 

Added.

>> >	'-stack-list-variables'.
> 
> 
>> >     Errors are printed as if they would be the parameter value.  Use
>> >-   zeroed ARG iff it should not be printed according to VALUES.  */
>> >+   zeroed ARG iff it should not be printed according to VALUES.  If
>> >+   SKIP_UNAVAILABLE is true, print ARG if it is available.  */
> "is true, only print ARG"
> 

"only" is added here...

>> >
>> >  static void
>> >  list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
>> >-		   enum print_values values)
>> >+		   enum print_values values, int skip_unavailable)
>> >  {
> 
> 
>> >  /* Print a list of the objects for the frame FI in a certain form,
>> >     which is determined by VALUES.  The objects can be locals,
>> >-   arguments or both, which is determined by WHAT.  */
>> >+   arguments or both, which is determined by WHAT.  If SKIP_UNAVAILABLE
>> >+   is true, print the arguments or local variables whose values are
>> >+   available.  */
> "is true, only print the"
> 

and here.

Thanks for the review, Pedro.  Patch below is what I committed.

-- 
Yao (齐尧)

gdb:

2013-08-27  Pedro Alves  <pedro@codesourcery.com>
	    Yao Qi  <yao@codesourcery.com>

	* mi/mi-cmd-stack.c (list_args_or_locals): Adjust prototype.
	(parse_no_frames_option): Remove.
	(mi_cmd_stack_list_locals): Handle --skip-unavailable.
	(mi_cmd_stack_list_args): Adjust.
	(mi_cmd_stack_list_variables): Handle --skip-unavailable.
	(list_arg_or_local): Add new parameter 'skip_unavailable'.  Return
	early if SKIP_UNAVAILABLE is true and ARG->val is unavailable.
	Caller update.
	(list_args_or_locals): New parameter 'skip_unavailable'.
	Handle it.
	* valprint.c (scalar_type_p): Rename to ...
	(val_print_scalar_type_p): ... this.  Make extern.
	(val_print, value_check_printable): Adjust.
	* valprint.h (val_print_scalar_type_p): Declare.
	* value.c (value_entirely_unavailable): New function.
	* value.h (value_entirely_unavailable): Declare.

	* NEWS: Mention the new option "--skip-unavailable" to MI
	commands '-stack-list-locals', '-stack-list-arguments' and
	'-stack-list-variables'.

gdb/doc:

2013-08-27  Pedro Alves  <pedro@codesourcery.com>
	    Yao Qi  <yao@codesourcery.com>

	* gdb.texinfo (GDB/MI Stack Manipulation) <-stack-list-locals>:
	Document new --skip-unavailable option.
	<-stack-list-variables>: Document new --skip-unavailable option.

gdb/testsuite:

2013-08-27  Yao Qi  <yao@codesourcery.com>

	* gdb.trace/entry-values.exp: Test unavailable entry value is
	not shown when option '--skip-unavailable' is specified.
	* gdb.trace/mi-trace-unavailable.exp (test_trace_unavailable):
	Add tests for new option '--skip-unavailable'.
---
 gdb/NEWS                                         |    4 +
 gdb/doc/gdb.texinfo                              |   17 ++++-
 gdb/mi/mi-cmd-stack.c                            |   77 ++++++++++++++++------
 gdb/testsuite/gdb.trace/entry-values.exp         |    5 ++
 gdb/testsuite/gdb.trace/mi-trace-unavailable.exp |    9 +++
 gdb/valprint.c                                   |    8 +-
 gdb/valprint.h                                   |    2 +
 gdb/value.c                                      |   20 ++++++
 gdb/value.h                                      |    4 +
 9 files changed, 119 insertions(+), 27 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 75016c1..ca8baea 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -93,6 +93,10 @@ show range-stepping
   ** The new command -trace-frame-collected dumps collected variables,
      computed expressions, tvars, memory and registers in a traceframe.
 
+  ** The commands -stack-list-locals, -stack-list-arguments and
+     -stack-list-variables now accept an option "--skip-unavailable".
+     When used, only the available locals or arguments are displayed.
+
 * New system-wide configuration scripts
   A GDB installation now provides scripts suitable for use as system-wide
   configuration scripts for the following systems:
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c88ee65..21250fe 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -31249,7 +31249,7 @@ For a stack with frame levels 0 through 11:
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-arguments [ --no-frame-filters ] @var{print-values}
+ -stack-list-arguments [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
     [ @var{low-frame} @var{high-frame} ]
 @end smallexample
 
@@ -31269,6 +31269,9 @@ type and value for simple data types, and the name and type for arrays,
 structures and unions.  If the option @code{--no-frame-filters} is
 supplied, then Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, arguments that
+are not available are not listed.  Partially available arguments
+are still displayed, however.
 
 Use of this command to obtain arguments in a single frame is
 deprecated in favor of the @samp{-stack-list-variables} command.
@@ -31453,7 +31456,7 @@ Show a single frame:
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-locals [ --no-frame-filters ] @var{print-values}
+ -stack-list-locals [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
 @end smallexample
 
 Display the local variable names for the selected frame.  If
@@ -31467,6 +31470,10 @@ other data types when the user wishes to explore their values in
 more detail.  If the option @code{--no-frame-filters} is supplied, then
 Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, local variables
+that are not available are not listed.  Partially available local
+variables are still displayed, however.
+
 This command is deprecated in favor of the
 @samp{-stack-list-variables} command.
 
@@ -31497,7 +31504,7 @@ This command is deprecated in favor of the
 @subsubheading Synopsis
 
 @smallexample
- -stack-list-variables [ --no-frame-filters ] @var{print-values}
+ -stack-list-variables [ --no-frame-filters ] [ --skip-unavailable ] @var{print-values}
 @end smallexample
 
 Display the names of local variables and function arguments for the selected frame.  If
@@ -31508,6 +31515,10 @@ type and value for simple data types, and the name and type for arrays,
 structures and unions.  If the option @code{--no-frame-filters} is
 supplied, then Python frame filters will not be executed.
 
+If the @code{--skip-unavailable} option is specified, local variables
+and arguments that are not available are not listed.  Partially
+available arguments and local variables are still displayed, however.
+
 @subsubheading Example
 
 @smallexample
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 2df97e2..7bf9ab8 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -39,9 +39,10 @@
 
 enum what_to_list { locals, arguments, all };
 
-static void list_args_or_locals (enum what_to_list what, 
+static void list_args_or_locals (enum what_to_list what,
 				 enum print_values values,
-				 struct frame_info *fi);
+				 struct frame_info *fi,
+				 int skip_unavailable);
 
 /* True if we want to allow Python-based frame filters.  */
 static int frame_filters = 0;
@@ -202,17 +203,21 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
   int oind = 0;
+  int skip_unavailable = 0;
+  int i;
 
   if (argc > 1)
     {
       int i;
       enum opt
       {
-	NO_FRAME_FILTERS
+	NO_FRAME_FILTERS,
+	SKIP_UNAVAILABLE,
       };
       static const struct mi_opt opts[] =
 	{
 	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
 	  { 0, 0, 0 }
 	};
 
@@ -229,6 +234,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
 	    {
 	    case NO_FRAME_FILTERS:
 	      raw_arg = oind;
+	    case SKIP_UNAVAILABLE:
+	      skip_unavailable = 1;
 	      break;
 	    }
 	}
@@ -237,7 +244,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
   /* After the last option is parsed, there should be only
      'print-values'.  */
   if (argc - oind != 1)
-    error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES"));
+    error (_("-stack-list-locals: Usage: [--no-frame-filters] "
+	     "[--skip-unavailable] PRINT_VALUES"));
 
   frame = get_selected_frame (NULL);
   print_value = mi_parse_print_values (argv[oind]);
@@ -254,7 +262,8 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
       if "--no-frame-filters" has been specified from the command.  */
    if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
      {
-       list_args_or_locals (locals, print_value, frame);
+       list_args_or_locals (locals, print_value, frame,
+			    skip_unavailable);
      }
 }
 
@@ -274,14 +283,17 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
   struct ui_out *uiout = current_uiout;
   int raw_arg = 0;
   int oind = 0;
+  int skip_unavailable = 0;
   enum py_bt_status result = PY_BT_ERROR;
   enum opt
   {
     NO_FRAME_FILTERS,
+    SKIP_UNAVAILABLE,
   };
   static const struct mi_opt opts[] =
     {
       {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+      {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
       { 0, 0, 0 }
     };
 
@@ -298,12 +310,16 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
 	case NO_FRAME_FILTERS:
 	  raw_arg = oind;
 	  break;
+	case SKIP_UNAVAILABLE:
+	  skip_unavailable = 1;
+	  break;
 	}
     }
 
   if (argc - oind != 1 && argc - oind != 3)
     error (_("-stack-list-arguments: Usage: "	\
-	     "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
+	     "[--no-frame-filters] [--skip-unavailable] "
+	     "PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
 
   if (argc - oind == 3)
     {
@@ -364,7 +380,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
 	  QUIT;
 	  cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
 	  ui_out_field_int (uiout, "level", i);
-	  list_args_or_locals (arguments, print_values, fi);
+	  list_args_or_locals (arguments, print_values, fi, skip_unavailable);
 	  do_cleanups (cleanup_frame);
 	}
     }
@@ -384,17 +400,20 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   enum py_bt_status result = PY_BT_ERROR;
   int print_value;
   int oind = 0;
+  int skip_unavailable = 0;
 
   if (argc > 1)
     {
       int i;
       enum opt
       {
-	NO_FRAME_FILTERS
+	NO_FRAME_FILTERS,
+	SKIP_UNAVAILABLE,
       };
       static const struct mi_opt opts[] =
 	{
 	  {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+	  {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
 	  { 0, 0, 0 }
 	};
 
@@ -411,6 +430,9 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
 	    case NO_FRAME_FILTERS:
 	      raw_arg = oind;
 	      break;
+	    case SKIP_UNAVAILABLE:
+	      skip_unavailable = 1;
+	      break;
 	    }
 	}
     }
@@ -418,8 +440,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   /* After the last option is parsed, there should be only
      'print-values'.  */
   if (argc - oind != 1)
-    error (_("-stack-list-variables: Usage: " \
-	     "[--no-frame-filters] PRINT_VALUES"));
+    error (_("-stack-list-variables: Usage: [--no-frame-filters] " \
+	     "[--skip-unavailable] PRINT_VALUES"));
 
    frame = get_selected_frame (NULL);
    print_value = mi_parse_print_values (argv[oind]);
@@ -436,7 +458,8 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
       if "--no-frame-filters" has been specified from the command.  */
    if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
      {
-       list_args_or_locals (all, print_value, frame);
+       list_args_or_locals (all, print_value, frame,
+			    skip_unavailable);
      }
 }
 
@@ -444,19 +467,17 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
    WHAT and VALUES see list_args_or_locals.
 
    Errors are printed as if they would be the parameter value.  Use
-   zeroed ARG iff it should not be printed according to VALUES.  */
+   zeroed ARG iff it should not be printed according to VALUES.  If
+   SKIP_UNAVAILABLE is true, only print ARG if it is available.  */
 
 static void
 list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
-		   enum print_values values)
+		   enum print_values values, int skip_unavailable)
 {
   struct cleanup *old_chain;
   struct ui_out *uiout = current_uiout;
   struct ui_file *stb;
 
-  stb = mem_fileopen ();
-  old_chain = make_cleanup_ui_file_delete (stb);
-
   gdb_assert (!arg->val || !arg->error);
   gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL
 	       && arg->error == NULL)
@@ -467,6 +488,20 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
 	      || (arg->entry_kind == print_entry_values_only
 	          && (arg->val || arg->error)));
 
+  if (skip_unavailable && arg->val != NULL
+      && (value_entirely_unavailable (arg->val)
+	  /* A scalar object that does not have all bits available is
+	     also considered unavailable, because all bits contribute
+	     to its representation.  */
+	  || (val_print_scalar_type_p (value_type (arg->val))
+	      && !value_bytes_available (arg->val,
+					 value_embedded_offset (arg->val),
+					 TYPE_LENGTH (value_type (arg->val))))))
+    return;
+
+  stb = mem_fileopen ();
+  old_chain = make_cleanup_ui_file_delete (stb);
+
   if (values != PRINT_NO_VALUES || what == all)
     make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
 
@@ -516,11 +551,13 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
 
 /* Print a list of the objects for the frame FI in a certain form,
    which is determined by VALUES.  The objects can be locals,
-   arguments or both, which is determined by WHAT.  */
+   arguments or both, which is determined by WHAT.  If SKIP_UNAVAILABLE
+   is true, only print the arguments or local variables whose values
+   are available.  */
 
 static void
 list_args_or_locals (enum what_to_list what, enum print_values values,
-		     struct frame_info *fi)
+		     struct frame_info *fi, int skip_unavailable)
 {
   struct block *block;
   struct symbol *sym;
@@ -623,9 +660,9 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
 		}
 
 	      if (arg.entry_kind != print_entry_values_only)
-		list_arg_or_local (&arg, what, values);
+		list_arg_or_local (&arg, what, values, skip_unavailable);
 	      if (entryarg.entry_kind != print_entry_values_no)
-		list_arg_or_local (&entryarg, what, values);
+		list_arg_or_local (&entryarg, what, values, skip_unavailable);
 	      xfree (arg.error);
 	      xfree (entryarg.error);
 	    }
diff --git a/gdb/testsuite/gdb.trace/entry-values.exp b/gdb/testsuite/gdb.trace/entry-values.exp
index bb62e5d..85306ad 100644
--- a/gdb/testsuite/gdb.trace/entry-values.exp
+++ b/gdb/testsuite/gdb.trace/entry-values.exp
@@ -276,4 +276,9 @@ gdb_test "tfind" "Found trace frame 0, .*" "tfind start"
 # Since 'global2' is not collected, j@entry is expected to be 'unavailable'.
 gdb_test "bt 1" "#0 .* foo \\(i=\[-\]?$decimal, i@entry=2, j=\[-\]?$decimal, j@entry=<unavailable>\\).*"
 
+# Test that unavailable "j@entry" is not shown when command option
+# --skip-unavailable is used.
+gdb_test "interpreter-exec mi \"-stack-list-arguments --skip-unavailable --simple-values\"" \
+    "\r\n\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"i\",type=\"int\",value=\".*\"},{name=\"i@entry\",type=\"int\",value=\"2\"},{name=\"j\",type=\"int\",value=\".*\"}\\\]},frame=.*\\\].*"
+
 gdb_test "tfind" "Target failed to find requested trace frame\..*"
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index d96ec8b..c69891b 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -106,16 +106,25 @@ proc test_trace_unavailable { data_source } {
 	mi_gdb_test "-stack-list-locals --simple-values" \
 	    ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \
 	    "-stack-list-locals --simple-values"
+	mi_gdb_test "-stack-list-locals --skip-unavailable --simple-values" \
+	    ".*\\^done,locals=\\\[\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \
+	    "-stack-list-locals --skip-unavailable --simple-values"
 
 	# Test MI command '-stack-list-arguments'.
 	mi_gdb_test "-stack-list-arguments --simple-values" \
 	    ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\},\{name=\"s\",type=\"char \\\*\",value=\"<unavailable>\"\}\\\]\},.*\}.*" \
 	    "-stack-list-arguments --simple-values"
+	mi_gdb_test "-stack-list-arguments --skip-unavailable --simple-values" \
+	    ".*\\^done,stack-args=\\\[frame=\{level=\"0\",args=\\\[\{name=\"j\",type=\"int\",value=\"4\"\}\\\]\},.*\}.*" \
+	    "-stack-list-arguments --skip-unavailable --simple-values"
 
 	# Test MI command '-stack-list-variables'.
 	mi_gdb_test "-stack-list-variables --simple-values" \
 	    ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"s\",arg=\"1\",type=\"char \\\*\",value=\"<unavailable>\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\},\{name=\"i\",type=\"int\",value=\"<unavailable>\"\}\\\]" \
 	    "-stack-list-variables --simple-values"
+	mi_gdb_test "-stack-list-variables --skip-unavailable --simple-values" \
+	    ".*\\^done,variables=\\\[\{name=\"j\",arg=\"1\",type=\"int\",value=\"4\"\},\{name=\"array\",type=\"unsigned char \\\[2\\\]\"\}\\\]" \
+	    "-stack-list-variables --skip-unavailable --simple-values"
 
 	mi_gdb_test "-trace-find frame-number 1" \
 	    ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 753ae34..0f6d65e 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -275,8 +275,8 @@ show_symbol_print (struct ui_file *file, int from_tty,
    we want to print scalar arguments, but not aggregate arguments.
    This function distinguishes between the two.  */
 
-static int
-scalar_type_p (struct type *type)
+int
+val_print_scalar_type_p (struct type *type)
 {
   CHECK_TYPEDEF (type);
   while (TYPE_CODE (type) == TYPE_CODE_REF)
@@ -770,7 +770,7 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 
   /* Handle summary mode.  If the value is a scalar, print it;
      otherwise, print an ellipsis.  */
-  if (options->summary && !scalar_type_p (type))
+  if (options->summary && !val_print_scalar_type_p (type))
     {
       fprintf_filtered (stream, "...");
       return;
@@ -802,7 +802,7 @@ value_check_printable (struct value *val, struct ui_file *stream,
 
   if (value_entirely_optimized_out (val))
     {
-      if (options->summary && !scalar_type_p (value_type (val)))
+      if (options->summary && !val_print_scalar_type_p (value_type (val)))
 	fprintf_filtered (stream, "...");
       else
 	val_print_optimized_out (stream);
diff --git a/gdb/valprint.h b/gdb/valprint.h
index 2959098..e7073b6 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -211,4 +211,6 @@ extern void generic_printstr (struct ui_file *stream, struct type *type,
 
 extern void output_command_const (const char *args, int from_tty);
 
+extern int val_print_scalar_type_p (struct type *type);
+
 #endif
diff --git a/gdb/value.c b/gdb/value.c
index 09ab1bb..d96c07b 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -353,6 +353,26 @@ value_entirely_available (struct value *value)
   return 0;
 }
 
+int
+value_entirely_unavailable (struct value *value)
+{
+  /* We can only tell whether the whole value is available when we try
+     to read it.  */
+  if (value->lazy)
+    value_fetch_lazy (value);
+
+  if (VEC_length (range_s, value->unavailable) == 1)
+    {
+      struct range *t = VEC_index (range_s, value->unavailable, 0);
+
+      if (t->offset == 0
+	  && t->length == TYPE_LENGTH (value_enclosing_type (value)))
+	return 1;
+    }
+
+  return 0;
+}
+
 void
 mark_value_bytes_unavailable (struct value *value, int offset, int length)
 {
diff --git a/gdb/value.h b/gdb/value.h
index bef193c..f03cf76 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -435,6 +435,10 @@ extern int value_bytes_available (const struct value *value,
    whole object is unavailable.  */
 extern int value_entirely_available (struct value *value);
 
+/* Like value_entirely_available, but return false if any byte in the
+   whole object is available.  */
+extern int value_entirely_unavailable (struct value *value);
+
 /* Mark VALUE's content bytes starting at OFFSET and extending for
    LENGTH bytes as unavailable.  */
 
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/2] Use mi_getopt_silent
  2013-08-27  3:30               ` Yao Qi
@ 2013-08-27 11:43                 ` Pedro Alves
  0 siblings, 0 replies; 26+ messages in thread
From: Pedro Alves @ 2013-08-27 11:43 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 08/27/2013 04:28 AM, Yao Qi wrote:
> On 08/27/2013 12:22 AM, Pedro Alves wrote:
>>>> -int
>>>> -mi_getopt (const char *prefix,
>>>> -	   int argc, char **argv,
>>>> -	   const struct mi_opt *opts,
>>>> -	   int *oind, char **oarg)
>>>> +/* See comments about mi_getopt and mi_getopt_silent in mi-getopt.h.
>>>> +   When there is an unknown option, if ERROR_ON_UNKNOWN is true, it
>>>> +   throws an error, otherwise return -1.  */
>> ("throws" -> "returns").  I'd suggest:
>>
> 
> I assume you meant "return" -> "returns" here.

Yeah, specifically, I meant, you have "it throws", so it should be
"it returns", as the subject is still "it".

> I also rename mi_getopt_silent to mi_getopt_allow_unknown.

Excellent!  I like that.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2013-08-27 11:43 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-03  1:48 [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi
2013-07-03  1:48 ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
2013-07-03  4:14   ` asmwarrior
2013-07-03  5:21     ` Yao Qi
2013-07-03 19:22   ` Eli Zaretskii
2013-07-22  1:38     ` Yao Qi
2013-08-01 12:33       ` Pedro Alves
2013-08-01 13:59         ` Yao Qi
2013-08-01 14:47           ` Pedro Alves
2013-08-25  3:43         ` [PATCH 0/2 v2] " Yao Qi
2013-08-25  3:43           ` [PATCH 1/2] Use mi_getopt_silent Yao Qi
2013-08-26  8:58             ` Agovic, Sanimir
2013-08-26 10:18               ` Yao Qi
2013-08-26 16:01                 ` Pedro Alves
2013-08-26 16:22             ` Pedro Alves
2013-08-27  3:30               ` Yao Qi
2013-08-27 11:43                 ` Pedro Alves
2013-08-25  3:43           ` [PATCH 2/2] Add options to skip unavailable locals Yao Qi
2013-08-26 16:40             ` Pedro Alves
2013-08-27  5:22               ` Yao Qi
2013-07-03  1:48 ` [PATCH 1/2] Use mi_getopt in mi_cmd_stack_list_locals and mi_cmd_stack_list_variables Yao Qi
2013-07-29 18:17   ` Pedro Alves
2013-07-31  7:01     ` Yao Qi
2013-07-31 12:23       ` Pedro Alves
2013-08-01  6:45         ` Yao Qi
2013-07-29  9:33 ` [ping]: [PATCH 0/2] New option --skip-unavailable to -stack-list-XXX commands Yao Qi

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).