public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA 1/3] / command : fast way to change setting(s), run a command, reset settings(s).
  2019-04-13 19:00 [RFA 0/3] / command : fast way to change setting(s) to run a command Philippe Waroquiers
  2019-04-13 19:00 ` [RFA 2/3] Test for slash_command Philippe Waroquiers
  2019-04-13 19:00 ` [RFA 3/3] NEWS and documentation for / (slash) command Philippe Waroquiers
@ 2019-04-13 19:00 ` Philippe Waroquiers
  2019-04-14 18:20   ` Kevin Buettner
  2 siblings, 1 reply; 8+ messages in thread
From: Philippe Waroquiers @ 2019-04-13 19:00 UTC (permalink / raw)
  To: gdb-patches; +Cc: Philippe Waroquiers

GDB has a lot of settings related to how commands behaves and/or print things.

There is however currently no easy way to temporarily change a setting
for a command.
This patch implements a new command called /, that allows to temporarily
change the settings in order to execute another command.
The objective for this / command is to be fast to type, so it uses
1 or 2 letters codes to identify which settings(s) to temporarily set.

Examples with printing an array:
********************************
gdb -ex 'b 24' -ex 'run' ./gdb/testsuite/outputs/gdb.ada/tick_length_array_enum_idx/foo_n207_004

     Default setting: arrays are not pretty printed.
        p full
          $1 = (false, true, false, true, false)
    To 'one time' pretty print an array, we currently need to do:
         set print array on
         p full
           $2 = (false,
             true,
             false,
             true,
             false)
         set print array off
    With the / command:
         /a p full
    To set it off, prefix with !.
    E.g.:
        /!a p some_array
     is the same as:
         set print array off
         p full
         set print array on
     Note: the / command in fact restores the setting in force before /
     changes them.
     I.e., if 'set print array' was on before '/!a p some_array'
     then after the execution of / command, it is still on.
   Other example: to print the array indexes:
      /i p full
   is the equivalent of:
       set print array-index on
       p full
       set print array-index off

   These can be combined, i.e.
     /ai p full
   is the equivalent of:
       set print array on
       set print array-index on
       p full
       set print array-index off
       set print array off

Numeric settings can also be overriden.  For example, the nr of elements
to print for an array (default is 200):
       set print elements 2
       p full
       set print elements 200
     is the equivalent of:
       /2e p full
     If e is not prefixed by a digit, then this is the same as no limit:
       set print elements unlimited
       p full
       set print elements 200
     is the equivalent of;
       /e p full

One can also do:
      /ai2e p full
to print full array with temporarily setting of pretty printing 2 elements,
with array indexes.

There is not enough letter to support all the print settings etc.
So, the upper case letters are used to introduce prefixes, typically
used for the less used settings.
For example:
     stepi
     bt
       #0  0x0000555555555a3f in foo_n207_004 () at ...
     set print address off
     bt
       #0  foo_n207_004 () at ...
     set print address on
  The last 3 commands are the equivalent of:
     /Pa bt

It is also possible to override enum settings.
E.g.
  set print frame-arguments all
  bt
  set print frame-arguments scalars
is equivalent to:
  /fa bt

Similarly, one can now easily set the language for just one command:
  set language c
  print something
  set language auto
is equivalent to:
  /lc print something

In terms of implementation:
A argument slash_seq (with default value nullptr) has been added to:
  add_setshow_boolean_cmd
  add_setshow_uinteger_cmd
  add_setshow_enum_cmd.

The above behaviour is obtained by passing the relevant string value
for this new slash_seq argument.
E.g. to have a shortcut /a for pretty printing array, the "a" has been
added as last argument in the below call:
    add_setshow_boolean_cmd ("array", class_support,
			   &user_print_options.prettyformat_arrays, _("\
Set pretty formatting of arrays."), _("\
Show pretty formatting of arrays."), NULL,
			   NULL,
			   show_prettyformat_arrays,
			   &setprintlist, &showprintlist,
			   "a");

The set print frame-arguments shortcuts are obtained by adding
"f[asn]" as last argument, where 'a' means 'all', 's' means 'scalars',
'n' means 'none'.

The full list of settings that can be used is given by 'help /' (see below).
Of course, we might add some more settings to the below list.
For example, the (probably soon to land) 'set print max-depth'
should added to the list (the letter d is still available for this one :).

(gdb) help /
Usage: /SETTING... COMMAND
Temporarily changes settings according to SETTING, run COMMAND,
and then restore the settings to their previous values.
Each temporarily changeable setting is identified by a unique sequence
of one or more letters.
A boolean setting is temporarily activated (set to "on") by giving
its sequence of letters.  If the boolean sequence of letters is prefixed
by !, the boolean setting is deactivated (set to "off").
An integer setting is temporarily changed by using its sequence of letters
optionally prefixed by the temporary value desired.
If no prefix value is given before the integer setting letters,
the integer setting is temporarily changed to an unlimited value.
An enum setting is temporarily changed by giving its sequence of letters
followed by a letter designating the chosen enum value.
Example:
  /100e!ai print some_array
is equivalent to:
  # save current values of the settings set print elements/array/array-index.
  set print elements 100
  set print array off
  set print array-index on
  print some_array
  # restore the saved values of the changed settings.
The temporarily changeable settings are:
/Be       set backtrace past-entry       Boolean on|off
/Bl       set backtrace limit            Unsigned integer (0 means unlimited)
/Bm       set backtrace past-main        Boolean on|off
/Co       set print object               Boolean on|off
/Cs       set print static-members       Boolean on|off
/Cv       set print vtbl                 Boolean on|off
/Pa       set print address              Boolean on|off
/Ps       set print symbol               Boolean on|off
/Rf       set print raw frame-arguments  Boolean on|off
/a        set print array                Boolean on|off
/e        set print elements             Unsigned integer (0 means unlimited)
/f[asn]   set print frame-arguments      Enum, a = all, s = scalars, n = none
/i        set print array-indexes        Boolean on|off
/l[aluAscCdfgmMOo] set language          Enum, a = auto, l = local,
                                u = unknown, A = ada, s = asm, c = c, C = c++,
                                d = d, f = fortran, g = go, m = minimal,
                                M = modula-2, O = objective-c, o = opencl
/n        set print null-stop            Boolean on|off
/p        set print pretty               Boolean on|off
/r        set print repeats              Unsigned integer (0 means unlimited)
/u        set print union                Boolean on|off
/v        set varsize-limit              Unsigned integer (0 means unlimited)
(gdb)

gdb/ChangeLog
2019-04-13  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* cli/cli-decode.c (slash_settings): New variable.
	(slash_settings_var_type_name): New typedef.
	(slash_settings_var_type_names): New variable.
	(get_slash_settings_var_type_name, slash_ncmp, check_mismatch,
	scoped_set_restore_slash_settings::scoped_set_restore_slash_settings,
	scoped_set_restore_slash_settings::command, prefixname,
	scoped_set_restore_slash_settings::~scoped_set_restore_slash_settings,
	scoped_set_restore_slash_settings::swap_values): New functions.
	(add_set_or_show_cmd, add_setshow_cmd_full,
	add_setshow_enum_cmd, add_setshow_boolean_cmd,
	add_setshow_uinteger_cmd): New arg slash_seq.
	(apropos_cmd): Also match on the command slash_seq.
	(help_cmd): Output the list of slash_settings when help is requested
	for /.  If there is a slash_seq setting for a command, output
	it in the help command output.
	(print_help_cor_command): Likewise.
	(find_command_name_length): Recognise / as a command.
	* cli/cli-decode.h (struct cmd_list_element): New component slash_seq.
	(slash_setting_value): New struct.
	(scoped_set_restore_slash_settings): New class.
	command.h (add_setshow_enum_cmd, add_setshow_boolean_cmd,
	add_setshow_uinteger_cmd): New slash_sea arg.
	* top.c (slash_command): New function.
	(init_main): Add the new slash_command.
	* ada-lang.c, cp-valprint.c, gdb/frame.c, language.c, stack.c,
	valprint.c (_initialize_*): Add some slash_seq args.
---
 gdb/ada-lang.c       |   3 +-
 gdb/cli/cli-decode.c | 394 +++++++++++++++++++++++++++++++++++++++++--
 gdb/cli/cli-decode.h |  43 +++++
 gdb/command.h        |   9 +-
 gdb/cp-valprint.c    |   9 +-
 gdb/frame.c          |   9 +-
 gdb/language.c       |   3 +-
 gdb/stack.c          |   6 +-
 gdb/top.c            |  39 +++++
 gdb/valprint.c       |  27 ++-
 10 files changed, 502 insertions(+), 40 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index ccf8ed8039..b106649913 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -14541,7 +14541,8 @@ Set the maximum number of bytes allowed in a variable-size object."), _("\
 Show the maximum number of bytes allowed in a variable-size object."), _("\
 Attempts to access an object whose size is not a compile-time constant\n\
 and exceeds this limit will cause an error."),
-			    NULL, NULL, &setlist, &showlist);
+			    NULL, NULL, &setlist, &showlist,
+			    "v");
 
   add_info ("exceptions", info_exceptions_command,
 	    _("\
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 50430953c7..ac5008ee2a 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -429,13 +429,275 @@ empty_sfunc (const char *args, int from_tty, struct cmd_list_element *c)
 {
 }
 
+/* List of cmd_list_elements whose var can be temporarily set by the
+   / command.  */
+
+static std::vector<cmd_list_element *> slash_settings;
+
+/* A printable representation of the var_types the / command accepts.  */
+typedef struct
+{
+  const char *var_type_name;
+  enum var_types var_type;
+} slash_settings_var_type_name;
+
+static const slash_settings_var_type_name slash_settings_var_type_names[] =
+{
+  { "Boolean on|off", var_boolean },
+  { "Unsigned integer (0 means unlimited)", var_uinteger },
+  { "Enum", var_enum },
+  { NULL, var_boolean }
+};
+
+static const char *
+get_slash_settings_var_type_name (var_types var_type)
+{
+  for (const slash_settings_var_type_name *v = slash_settings_var_type_names;
+       v->var_type_name;
+       v++)
+    if (v->var_type == var_type)
+      return v->var_type_name;
+
+  gdb_assert (0);
+}
+
+/* Like strncmp, but stops the comparison at n char or when a [ character
+   or null character is encountered.  */
+static int
+slash_ncmp (const char *left, const char *right, size_t n)
+{
+  size_t l;
+  size_t r;
+
+  for (l = 0; l <= n && left[l] != 0 && left[l] != '['; l++)
+    ;
+  for (r = 0; r <= n && right[r] != 0 && right[r] != '['; r++)
+    ;
+
+  return strncmp (left, right, l > r ? r : l);
+}
+
+/* If CMD has a prefix, returns its prefix name, otherwise returns "".  */
+static const char *
+prefixname (const cmd_list_element *cmd)
+{
+  return cmd->prefix == nullptr ? "" : cmd->prefix->prefixname;
+}
+
+/* Verifies that EXPECTED matches the type of FOUND.
+   If a mismatch is found, throws an error using EXPECTED_ORIGIN
+   to indicate the source of the mismatch.  */
+
+static void
+check_mismatch (var_types expected, cmd_list_element *found,
+		const char *expected_origin, const char *beg_found)
+{
+  if (expected != found->var_type)
+    error (_("Value type for / setting \"%s\" (%s%s) is '%s'.\n"
+	     "Found unexpected '%s' qualifier at \"%s\""),
+	   found->slash_seq, prefixname (found), found->name,
+	   get_slash_settings_var_type_name (found->var_type),
+	   get_slash_settings_var_type_name (expected),
+	   expected_origin);
+}
+
+/* See cli-decode.h  */
+
+scoped_set_restore_slash_settings::scoped_set_restore_slash_settings
+(const char *args)
+{
+  const char *p = args;
+
+  if (p == nullptr)
+    error (_("/ must be followed by one or more SETTING letters."));
+
+  /* First accumulate all the cmd_list_elements in saved vector,
+     with the new desired value.  We will then swap the values
+     once we have succesfully parse all the settings.  */
+  while (*p && *p != ' ')
+    {
+      slash_setting_value v;
+      const char *beg;
+      bool check_expected = false;
+      /* The following variables are set when (and only used if)
+	 check_expected is true.  We default initialize them to silence
+	 gcc warning.  */
+      const char *expected_origin = NULL;
+      var_types expected = var_optional_filename;
+      unsigned int uinteger_val = 1234567890;
+
+      if (*(p) == '!')
+	{
+	  check_expected = true;
+	  expected_origin = p;
+	  expected = var_boolean;
+	  p++;
+	}
+      else if (isdigit (*p))
+	{
+	  check_expected = true;
+	  expected_origin = p;
+	  expected = var_uinteger;
+	  uinteger_val = atoi (p);
+	  while (isdigit (*p))
+	    p++;
+	}
+
+      beg = p;
+      while (isupper (*p))
+	p++;
+      for (auto it = slash_settings.begin (); it != slash_settings.end (); it++)
+	{
+	  cmd_list_element *o = *it;
+
+	  if (slash_ncmp (o->slash_seq, beg, p + 1 - beg) == 0)
+	    {
+	      v.cmd = o;
+	      p++;
+	      if (check_expected)
+		check_mismatch (expected, o, expected_origin, beg);
+	      switch (o->var_type)
+		{
+		case var_boolean:
+		  if (check_expected)
+		    v.value.boolean_var = 0;
+		  else
+		    v.value.boolean_var = 1;
+		  break;
+
+		case var_uinteger:
+		  if (check_expected)
+		    {
+		      v.value.uinteger_val = uinteger_val;
+		      if (v.value.uinteger_val == 0)
+			v.value.uinteger_val = UINT_MAX;
+		    }
+		  else
+		    v.value.uinteger_val = UINT_MAX;
+		  break;
+
+		case var_enum:
+		  {
+		    const char *l = o->slash_seq;
+		    const char *f;
+
+		    while (*l && *l != '[')
+		      l++;
+		    gdb_assert (*l == '[');
+		    l++;
+		    f = l;
+		    while (*f && *f != *p)
+		      f++;
+		    if (!*f)
+		      error (_("Value for slash setting '%c'"
+			       " not recognised at \"%s\""),
+			     *beg, beg + 1);
+		    p++;
+		    v.value.enum_val = o->enums[f - l];
+		    break;
+		  }
+
+		default:
+		  gdb_assert (0);
+		}
+
+	      saved.emplace_back (v);
+	      break;
+	    }
+	}
+      if (beg == p)
+	{
+	  if (*beg == ' ')
+	    {
+	      if (check_expected)
+		{
+		  if (expected == var_uinteger)
+		    error (_("Unsigned integer setting expected following"
+			     " integer value at \"%s\""), expected_origin);
+		  else if (expected == var_boolean)
+		    error (_("Boolean setting expected following"
+			     " ! at \"%s\""), expected_origin);
+		  else
+		    gdb_assert (0);
+		}
+	      else
+		error (_("No slash setting found at \"%s\""), beg);
+	    }
+	  else
+	    error (_("Slash setting not recognised at \"%s\""), beg);
+	}
+    }
+
+  while (*p == ' ')
+    p++;
+  this->cmd = p;
+
+  if (*p == 0)
+    error (_("/SETTING... must be followed by a COMMAND."));
+
+  swap_values ();
+}
+
+/* See cli-decode.h  */
+
+const char *scoped_set_restore_slash_settings::command ()
+{
+  return this->cmd;
+}
+
+/* See cli-decode.h  */
+
+scoped_set_restore_slash_settings::~scoped_set_restore_slash_settings ()
+{
+  swap_values ();
+}
+
+/* See cli-decode.h  */
+
+void scoped_set_restore_slash_settings::swap_values ()
+{
+#define SWAPVAL_SAVED_I(TYPE, COMP) do {	      \
+    TYPE tmp = saved[i].value.COMP;		      \
+    saved[i].value.COMP = *(TYPE*)saved[i].cmd->var;  \
+    *(TYPE*)saved[i].cmd->var = tmp; } while (0)
+
+  for (int i = 0; i < saved.size (); i++)
+    {
+      switch (saved[i].cmd->var_type)
+	{
+	case var_boolean:
+	  SWAPVAL_SAVED_I (int, boolean_var);
+	  break;
+
+	case var_uinteger:
+	  SWAPVAL_SAVED_I (unsigned int, uinteger_val);
+	  break;
+
+	case var_enum:
+	  SWAPVAL_SAVED_I (const char *, enum_val);
+	  break;
+
+	default:
+	  gdb_assert (0);
+	}
+      /* If some function must be run after changing the value, call it.
+	 Note: we harcode NULL for the ARGS parameter.
+	 We might instead "print" the *_val values in a string and pass
+	 this printed value instead.  A NULL seems to be ok for now.  */
+      if (cmd_func_p (saved[i].cmd))
+	cmd_func (saved[i].cmd, NULL, 0);
+    }
+}
+
 /* Add element named NAME to command list LIST (the list for set/show
    or some sublist thereof).
    TYPE is set_cmd or show_cmd.
    CLASS is as in add_cmd.
    VAR_TYPE is the kind of thing we are setting.
    VAR is address of the variable being controlled by this command.
-   DOC is the documentation string.  */
+   DOC is the documentation string.
+   if SLASH_SEQ is not null, the setting controlled by this command
+   will be temporarily changeable by the / command.  */
 
 static struct cmd_list_element *
 add_set_or_show_cmd (const char *name,
@@ -444,17 +706,49 @@ add_set_or_show_cmd (const char *name,
 		     var_types var_type,
 		     void *var,
 		     const char *doc,
-		     struct cmd_list_element **list)
+		     struct cmd_list_element **list,
+		     const char *slash_seq)
 {
   struct cmd_list_element *c = add_cmd (name, theclass, doc, list);
 
   gdb_assert (type == set_cmd || type == show_cmd);
+  gdb_assert (type == set_cmd || slash_seq == nullptr);
+
   c->type = type;
   c->var_type = var_type;
   c->var = var;
   /* This needs to be something besides NULL so that this isn't
      treated as a help class.  */
   set_cmd_sfunc (c, empty_sfunc);
+
+  /* Handle the optional slash_seq.  */
+  if (slash_seq != nullptr)
+    {
+      int cmp = 1;
+
+      for (auto it = slash_settings.begin (); it != slash_settings.end (); it++)
+	{
+	  cmd_list_element *o = *it;
+
+	  cmp = slash_ncmp (slash_seq, o->slash_seq, UINT_MAX);
+	  if (cmp == 0)
+	    {
+	      printf_unfiltered ("slash_seq /%s for cmd %s%s\n",
+				 slash_seq, prefixname (c), c->name);
+	      printf_unfiltered ("conflicts with slash_seq /%s for cmd %s%s\n",
+				 o->slash_seq, prefixname (o), o->name);
+	      gdb_assert (0);
+	    }
+	  else if (cmp < 0)
+	    {
+	      slash_settings.insert (it, c);
+	      break;
+	    }
+	}
+      if (cmp > 0)
+	slash_settings.emplace_back (c);
+      c->slash_seq = slash_seq;
+    }
   return c;
 }
 
@@ -465,7 +759,9 @@ add_set_or_show_cmd (const char *name,
    non-NULL).  SET_DOC, SHOW_DOC and HELP_DOC are the documentation
    strings.  PRINT the format string to print the value.  SET_RESULT
    and SHOW_RESULT, if not NULL, are set to the resulting command
-   structures.  */
+   structures.  If not nullptr, SLASH_SEQ gives the sequence of letters
+   that can be used in the / command to temporarily set
+   the value of this setting.  */
 
 static void
 add_setshow_cmd_full (const char *name,
@@ -478,7 +774,8 @@ add_setshow_cmd_full (const char *name,
 		      struct cmd_list_element **set_list,
 		      struct cmd_list_element **show_list,
 		      struct cmd_list_element **set_result,
-		      struct cmd_list_element **show_result)
+		      struct cmd_list_element **show_result,
+		      const char *slash_seq = nullptr)
 {
   struct cmd_list_element *set;
   struct cmd_list_element *show;
@@ -496,7 +793,7 @@ add_setshow_cmd_full (const char *name,
       full_show_doc = xstrdup (show_doc);
     }
   set = add_set_or_show_cmd (name, set_cmd, theclass, var_type, var,
-			     full_set_doc, set_list);
+			     full_set_doc, set_list, slash_seq);
   set->doc_allocated = 1;
 
   if (set_func != NULL)
@@ -505,7 +802,7 @@ add_setshow_cmd_full (const char *name,
   set_cmd_prefix (set, set_list);
 
   show = add_set_or_show_cmd (name, show_cmd, theclass, var_type, var,
-			      full_show_doc, show_list);
+			      full_show_doc, show_list, NULL);
   show->doc_allocated = 1;
   show->show_value_func = show_func;
 
@@ -532,7 +829,8 @@ add_setshow_enum_cmd (const char *name,
 		      show_value_ftype *show_func,
 		      struct cmd_list_element **set_list,
 		      struct cmd_list_element **show_list,
-		      void *context)
+		      void *context,
+		      const char *slash_seq)
 {
   struct cmd_list_element *c, *show;
 
@@ -540,7 +838,8 @@ add_setshow_enum_cmd (const char *name,
 			set_doc, show_doc, help_doc,
 			set_func, show_func,
 			set_list, show_list,
-			&c, &show);
+			&c, &show,
+			slash_seq);
   c->enums = enumlist;
 
   set_cmd_context (c, context);
@@ -585,7 +884,8 @@ add_setshow_boolean_cmd (const char *name, enum command_class theclass, int *var
 			 cmd_const_sfunc_ftype *set_func,
 			 show_value_ftype *show_func,
 			 struct cmd_list_element **set_list,
-			 struct cmd_list_element **show_list)
+			 struct cmd_list_element **show_list,
+			 const char *slash_seq)
 {
   static const char *boolean_enums[] = { "on", "off", NULL };
   struct cmd_list_element *c;
@@ -594,7 +894,7 @@ add_setshow_boolean_cmd (const char *name, enum command_class theclass, int *var
 			set_doc, show_doc, help_doc,
 			set_func, show_func,
 			set_list, show_list,
-			&c, NULL);
+			&c, NULL, slash_seq);
   c->enums = boolean_enums;
 }
 
@@ -740,7 +1040,8 @@ add_setshow_uinteger_cmd (const char *name, enum command_class theclass,
 			  cmd_const_sfunc_ftype *set_func,
 			  show_value_ftype *show_func,
 			  struct cmd_list_element **set_list,
-			  struct cmd_list_element **show_list)
+			  struct cmd_list_element **show_list,
+			  const char *slash_seq)
 {
   struct cmd_list_element *set;
 
@@ -748,7 +1049,7 @@ add_setshow_uinteger_cmd (const char *name, enum command_class theclass,
 			set_doc, show_doc, help_doc,
 			set_func, show_func,
 			set_list, show_list,
-			&set, NULL);
+			&set, NULL, slash_seq);
 
   set_cmd_completer (set, integer_unlimited_completer);
 }
@@ -965,6 +1266,22 @@ apropos_cmd (struct ui_file *stream,
 				      0 /* don't recurse */, stream);
 	    }
 	}
+      if (c->slash_seq != NULL)
+	{
+	  size_t slash_seq_len = strlen (c->slash_seq) + 1;
+	  char slash_seq [slash_seq_len + 1];
+
+	  slash_seq[0] = '/';
+	  slash_seq[1] = 0;
+	  strcat (slash_seq + 1, c->slash_seq);
+	  returnvalue = regex.search (slash_seq, slash_seq_len, 0,
+				      slash_seq_len, NULL);
+	  if (returnvalue >= 0)
+	    {
+	      print_help_for_command (c, prefix,
+				      0 /* don't recurse */, stream);
+	    }
+	}
       if (c->doc != NULL && returnvalue < 0)
 	{
 	  size_t doc_len = strlen (c->doc);
@@ -1034,7 +1351,47 @@ help_cmd (const char *command, struct ui_file *stream)
      listed.  */
 
   fputs_filtered (c->doc, stream);
-  fputs_filtered ("\n", stream);
+  if (strcmp (c->name, "/") == 0)
+    {
+      /* The / command help needs to be completed by the list of
+	 settings that can be temporarily set.  */
+      for (const cmd_list_element *o : slash_settings)
+	{
+	  std::string msg = string_printf ("/%-8s %s%s", o->slash_seq,
+					   prefixname (o), o->name);
+	  fprintf_filtered (stream, "%-40s %s", msg.c_str (),
+			    get_slash_settings_var_type_name (o->var_type));
+	  if (o->var_type == var_enum)
+	    {
+	      const char *l = o->slash_seq;
+	      const char *f;
+
+	      while (*l && *l != '[')
+		l++;
+	      gdb_assert (*l == '[');
+	      l++;
+	      f = l;
+	      while (*f && *f != ']')
+		{
+		  fprintf_filtered (stream, ",");
+		  wrap_here ("                               ");
+		  fprintf_filtered (stream, " %c = %s",
+				    *f, o->enums[f - l]);
+		  f++;
+		}
+	      gdb_assert (*f == ']');
+	    }
+	  fputs_filtered ("\n", stream);
+	}
+    }
+  else
+    fputs_filtered ("\n", stream);
+
+  if (c->slash_seq != nullptr)
+    fprintf_filtered
+      (stream,
+       _("Use /%s COMMAND to temporarily change this setting to run COMMAND.\n"),
+       c->slash_seq);
 
   if (c->prefixlist == 0 && c->func != NULL)
     return;
@@ -1212,10 +1569,11 @@ static void
 print_help_for_command (struct cmd_list_element *c, const char *prefix,
 			int recurse, struct ui_file *stream)
 {
-  fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
+  fprintf_filtered (stream, "%s%s%s%s -- ", prefix, c->name,
+		    c->slash_seq == nullptr ? "" : ", /",
+		    c->slash_seq == nullptr ? "" : c->slash_seq);
   print_doc_line (stream, c->doc);
   fputs_filtered ("\n", stream);
-  
   if (recurse
       && c->prefixlist != 0
       && c->abbrev_flag == 0)
@@ -1311,9 +1669,9 @@ find_command_name_length (const char *text)
      Note that this is larger than the character set allowed when
      creating user-defined commands.  */
 
-  /* Recognize '!' as a single character command so that, e.g., "!ls"
-     works as expected.  */
-  if (*p == '!')
+  /* Recognize '!' and '/' as a single character command so that, e.g., "!ls"
+     and "/ai print some array" works as expected.  */
+  if (*p == '!' || *p == '/')
     return 1;
 
   while (isalnum (*p) || *p == '-' || *p == '_'
diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h
index c53683d95c..49581da0a9 100644
--- a/gdb/cli/cli-decode.h
+++ b/gdb/cli/cli-decode.h
@@ -209,6 +209,10 @@ struct cmd_list_element
        matter if type is not_set.  */
     void *var = nullptr;
 
+    /* Sequence of characters that can be used by the / command
+       to temporarily set the variable affected by "set".  */
+    const char *slash_seq = nullptr;
+
     /* Pointer to NULL terminated list of enumerated values (like
        argv).  */
     const char *const *enums = nullptr;
@@ -270,4 +274,43 @@ extern int cli_user_command_p (struct cmd_list_element *);
 
 extern int find_command_name_length (const char *);
 
+/* A structure that maintains a value for a variable changeable using CMD.  */
+
+typedef struct
+{
+  cmd_list_element *cmd;
+  union {
+    int boolean_var;
+    unsigned int uinteger_val;
+    const char *enum_val;
+  } value;
+} slash_setting_value;
+
+/* Processes the given ARGS to change the settings according to the
+   slash sequences found in ARGS.
+   Restore the previous settings values upon destruction.  */
+
+class scoped_set_restore_slash_settings
+{
+public:
+
+  explicit scoped_set_restore_slash_settings (const char *args);
+
+  /* Returns the command to execute after having processed the / settings
+     found in ARGS.  */
+  const char *command ();
+
+  ~scoped_set_restore_slash_settings ();
+
+  DISABLE_COPY_AND_ASSIGN (scoped_set_restore_slash_settings);
+
+private:
+  /* The command to execute with the temporarily changed settings.  */
+  const char *cmd;
+  std::vector<slash_setting_value> saved;
+
+  /* Swap the values in SAVED with the real settings values.  */
+  void swap_values ();
+};
+
 #endif /* CLI_CLI_DECODE_H */
diff --git a/gdb/command.h b/gdb/command.h
index 4a239a7196..c8f4d19792 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -315,7 +315,8 @@ extern void add_setshow_enum_cmd (const char *name,
 				  show_value_ftype *show_func,
 				  struct cmd_list_element **set_list,
 				  struct cmd_list_element **show_list,
-				  void *context = nullptr);
+				  void *context = nullptr,
+				  const char *slash_seq = nullptr);
 
 extern void add_setshow_auto_boolean_cmd (const char *name,
 					  enum command_class theclass,
@@ -336,7 +337,8 @@ extern void add_setshow_boolean_cmd (const char *name,
 				     cmd_const_sfunc_ftype *set_func,
 				     show_value_ftype *show_func,
 				     struct cmd_list_element **set_list,
-				     struct cmd_list_element **show_list);
+				     struct cmd_list_element **show_list,
+				     const char *slash_seq = nullptr);
 
 extern void add_setshow_filename_cmd (const char *name,
 				      enum command_class theclass,
@@ -403,7 +405,8 @@ extern void add_setshow_uinteger_cmd (const char *name,
 				      cmd_const_sfunc_ftype *set_func,
 				      show_value_ftype *show_func,
 				      struct cmd_list_element **set_list,
-				      struct cmd_list_element **show_list);
+				      struct cmd_list_element **show_list,
+				      const char *slash_seq = nullptr);
 
 extern void add_setshow_zinteger_cmd (const char *name,
 				      enum command_class theclass,
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index e883179dfa..14b553f206 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -811,7 +811,8 @@ Set printing of C++ static members."), _("\
 Show printing of C++ static members."), NULL,
 			   NULL,
 			   show_static_field_print,
-			   &setprintlist, &showprintlist);
+			   &setprintlist, &showprintlist,
+			   "Cs");
 
   add_setshow_boolean_cmd ("vtbl", class_support,
 			   &user_print_options.vtblprint, _("\
@@ -819,7 +820,8 @@ Set printing of C++ virtual function tables."), _("\
 Show printing of C++ virtual function tables."), NULL,
 			   NULL,
 			   show_vtblprint,
-			   &setprintlist, &showprintlist);
+			   &setprintlist, &showprintlist,
+			   "Cv");
 
   add_setshow_boolean_cmd ("object", class_support,
 			   &user_print_options.objectprint, _("\
@@ -827,7 +829,8 @@ Set printing of object's derived type based on vtable info."), _("\
 Show printing of object's derived type based on vtable info."), NULL,
 			   NULL,
 			   show_objectprint,
-			   &setprintlist, &showprintlist);
+			   &setprintlist, &showprintlist,
+			   "Co");
 
   obstack_begin (&dont_print_stat_array_obstack,
 		 32 * sizeof (struct type *));
diff --git a/gdb/frame.c b/gdb/frame.c
index f4303d13cc..0170ae0f4d 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2926,7 +2926,8 @@ of the stack trace."),
 			   NULL,
 			   show_backtrace_past_main,
 			   &set_backtrace_cmdlist,
-			   &show_backtrace_cmdlist);
+			   &show_backtrace_cmdlist,
+			   "Bm");
 
   add_setshow_boolean_cmd ("past-entry", class_obscure,
 			   &backtrace_past_entry, _("\
@@ -2940,7 +2941,8 @@ the rest of the stack trace."),
 			   NULL,
 			   show_backtrace_past_entry,
 			   &set_backtrace_cmdlist,
-			   &show_backtrace_cmdlist);
+			   &show_backtrace_cmdlist,
+			   "Be");
 
   add_setshow_uinteger_cmd ("limit", class_obscure,
 			    &backtrace_limit, _("\
@@ -2951,7 +2953,8 @@ Literal \"unlimited\" or zero means no limit."),
 			    NULL,
 			    show_backtrace_limit,
 			    &set_backtrace_cmdlist,
-			    &show_backtrace_cmdlist);
+			    &show_backtrace_cmdlist,
+			    "Bl");
 
   /* Debug this files internals.  */
   add_setshow_zuinteger_cmd ("frame", class_maintenance, &frame_debug,  _("\
diff --git a/gdb/language.c b/gdb/language.c
index 954e4c200f..b804e34efa 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -584,7 +584,8 @@ add_set_language_command ()
 			_("Show the current source language."),
 			NULL, set_language_command,
 			show_language_command,
-			&setlist, &showlist);
+			&setlist, &showlist, NULL,
+			"l[aluAscCdfgmMOo]");
 }
 
 /* Iterate through all registered languages looking for and calling
diff --git a/gdb/stack.c b/gdb/stack.c
index f7fd9433b5..5a2491e45a 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -3103,7 +3103,8 @@ Usage: func NAME"));
 			print_frame_arguments_choices, &print_frame_arguments,
 			_("Set printing of non-scalar frame arguments"),
 			_("Show printing of non-scalar frame arguments"),
-			NULL, NULL, NULL, &setprintlist, &showprintlist);
+			NULL, NULL, NULL, &setprintlist, &showprintlist,
+			NULL, "f[asn]");
 
   add_setshow_boolean_cmd ("frame-arguments", no_class,
 			   &print_raw_frame_arguments, _("\
@@ -3112,7 +3113,8 @@ Show whether to print frame arguments in raw form."), _("\
 If set, frame arguments are printed in raw form, bypassing any\n\
 pretty-printers for that value."),
 			   NULL, NULL,
-			   &setprintrawlist, &showprintrawlist);
+			   &setprintrawlist, &showprintrawlist,
+			   "Rf");
 
   add_setshow_auto_boolean_cmd ("disassemble-next-line", class_stack,
 			        &disassemble_next_line, _("\
diff --git a/gdb/top.c b/gdb/top.c
index 60ca74da25..76838d9d33 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -2016,6 +2016,16 @@ init_gdb_version_vars (void)
   set_internalvar_integer (minor_version_var, vminor + (vrevision > 0));
 }
 
+/* Implementation of the "/" slash command.  */
+
+static void
+slash_command (const char *args, int from_tty)
+{
+  scoped_set_restore_slash_settings settings (args);
+
+  execute_command (settings.command (), from_tty);
+}
+
 static void
 init_main (void)
 {
@@ -2164,6 +2174,35 @@ Create a new UI.  It takes two arguments:\n\
 The first argument is the name of the interpreter to run.\n\
 The second argument is the terminal the UI runs on.\n"), &cmdlist);
   set_cmd_completer (c, interpreter_completer);
+
+  add_com ("/", class_support, slash_command, _("\
+Usage: /SETTING... COMMAND\n\
+Temporarily changes settings according to SETTING, run COMMAND,\n\
+and then restore the settings to their previous values.\n\
+Each temporarily changeable setting is identified by a unique sequence\n\
+of one or more letters.\n\
+A boolean setting is temporarily activated (set to \"on\") by giving\n\
+its sequence of letters.  If the boolean sequence of letters is prefixed\n\
+by !, the boolean setting is deactivated (set to \"off\").\n\
+An integer setting is temporarily changed by using its sequence of letters\n\
+optionally prefixed by the temporary value desired.\n\
+If no prefix value is given before the integer setting letters,\n\
+the integer setting is temporarily changed to an unlimited value.\n\
+An enum setting is temporarily changed by giving its sequence of letters\n\
+followed by a letter designating the chosen enum value.\n\
+Example:\n\
+  /100e!ai print some_array\n\
+is equivalent to:\n\
+  # save current values of the settings set print elements/array/array-index.\n\
+  set print elements 100\n\
+  set print array off\n\
+  set print array-index on\n\
+  print some_array\n\
+  # restore the saved values of the changed settings.\n\
+The temporarily changeable settings are:\n"));
+  /* Note that the slash_command on-line help terminates with ':', as
+     the help_cmd function will output the list of / settings that
+     can be used.  */
 }
 
 void
diff --git a/gdb/valprint.c b/gdb/valprint.c
index b02ebf6c27..1a736bb8a7 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -3055,7 +3055,8 @@ Show limit on string chars or array elements to print."), _("\
 \"set print elements unlimited\" causes there to be no limit."),
 			    NULL,
 			    show_print_max,
-			    &setprintlist, &showprintlist);
+			    &setprintlist, &showprintlist,
+			    "e");
 
   add_setshow_boolean_cmd ("null-stop", no_class,
 			   &user_print_options.stop_print_at_null, _("\
@@ -3063,7 +3064,8 @@ Set printing of char arrays to stop at first null char."), _("\
 Show printing of char arrays to stop at first null char."), NULL,
 			   NULL,
 			   show_stop_print_at_null,
-			   &setprintlist, &showprintlist);
+			   &setprintlist, &showprintlist,
+			   "n");
 
   add_setshow_uinteger_cmd ("repeats", no_class,
 			    &user_print_options.repeat_count_threshold, _("\
@@ -3072,7 +3074,8 @@ Show threshold for repeated print elements."), _("\
 \"set print repeats unlimited\" causes all elements to be individually printed."),
 			    NULL,
 			    show_repeat_count_threshold,
-			    &setprintlist, &showprintlist);
+			    &setprintlist, &showprintlist,
+			    "r");
 
   add_setshow_boolean_cmd ("pretty", class_support,
 			   &user_print_options.prettyformat_structs, _("\
@@ -3080,7 +3083,8 @@ Set pretty formatting of structures."), _("\
 Show pretty formatting of structures."), NULL,
 			   NULL,
 			   show_prettyformat_structs,
-			   &setprintlist, &showprintlist);
+			   &setprintlist, &showprintlist,
+			   "p");
 
   add_setshow_boolean_cmd ("union", class_support,
 			   &user_print_options.unionprint, _("\
@@ -3088,7 +3092,8 @@ Set printing of unions interior to structures."), _("\
 Show printing of unions interior to structures."), NULL,
 			   NULL,
 			   show_unionprint,
-			   &setprintlist, &showprintlist);
+			   &setprintlist, &showprintlist,
+			   "u");
 
   add_setshow_boolean_cmd ("array", class_support,
 			   &user_print_options.prettyformat_arrays, _("\
@@ -3096,7 +3101,8 @@ Set pretty formatting of arrays."), _("\
 Show pretty formatting of arrays."), NULL,
 			   NULL,
 			   show_prettyformat_arrays,
-			   &setprintlist, &showprintlist);
+			   &setprintlist, &showprintlist,
+			   "a");
 
   add_setshow_boolean_cmd ("address", class_support,
 			   &user_print_options.addressprint, _("\
@@ -3104,7 +3110,8 @@ Set printing of addresses."), _("\
 Show printing of addresses."), NULL,
 			   NULL,
 			   show_addressprint,
-			   &setprintlist, &showprintlist);
+			   &setprintlist, &showprintlist,
+			   "Pa");
 
   add_setshow_boolean_cmd ("symbol", class_support,
 			   &user_print_options.symbol_print, _("\
@@ -3112,7 +3119,8 @@ Set printing of symbol names when printing pointers."), _("\
 Show printing of symbol names when printing pointers."),
 			   NULL, NULL,
 			   show_symbol_print,
-			   &setprintlist, &showprintlist);
+			   &setprintlist, &showprintlist,
+			   "Ps");
 
   add_setshow_zuinteger_cmd ("input-radix", class_support, &input_radix_1,
 			     _("\
@@ -3151,5 +3159,6 @@ Use 'show input-radix' or 'show output-radix' to independently show each."),
                            &user_print_options.print_array_indexes, _("\
 Set printing of array indexes."), _("\
 Show printing of array indexes"), NULL, NULL, show_print_array_indexes,
-                           &setprintlist, &showprintlist);
+                           &setprintlist, &showprintlist,
+			   "i");
 }
-- 
2.20.1

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

* [RFA 0/3] / command : fast way to change setting(s) to run a command
@ 2019-04-13 19:00 Philippe Waroquiers
  2019-04-13 19:00 ` [RFA 2/3] Test for slash_command Philippe Waroquiers
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2019-04-13 19:00 UTC (permalink / raw)
  To: gdb-patches

Changes compared to the RFC of the 8 April (if ever someone read the RFC :) :
  * Used the word 'setting' instead of 'option'.
  * Numeric syntax is now /100e instead of /e100.
  * Boolean disable syntax is now /!a instead of /a!.
  * Various small code changes.
  * NEWS, ChangeLog, tests are done.


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

* [RFA 2/3] Test for slash_command.
  2019-04-13 19:00 [RFA 0/3] / command : fast way to change setting(s) to run a command Philippe Waroquiers
@ 2019-04-13 19:00 ` Philippe Waroquiers
  2019-04-13 19:00 ` [RFA 3/3] NEWS and documentation for / (slash) command Philippe Waroquiers
  2019-04-13 19:00 ` [RFA 1/3] / command : fast way to change setting(s), run a command, reset settings(s) Philippe Waroquiers
  2 siblings, 0 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2019-04-13 19:00 UTC (permalink / raw)
  To: gdb-patches; +Cc: Philippe Waroquiers

gdb/testsuite/ChangeLog
2019-04-13  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/slash_command.exp: New testcase.
	* gdb.base/slash_command.c: New file.
---
 gdb/testsuite/gdb.base/slash_command.c   |  38 +++++++
 gdb/testsuite/gdb.base/slash_command.exp | 125 +++++++++++++++++++++++
 2 files changed, 163 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/slash_command.c
 create mode 100644 gdb/testsuite/gdb.base/slash_command.exp

diff --git a/gdb/testsuite/gdb.base/slash_command.c b/gdb/testsuite/gdb.base/slash_command.c
new file mode 100644
index 0000000000..d54dfaaf2c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/slash_command.c
@@ -0,0 +1,38 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2019 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+static int x;
+
+int my_foo_function (int a)
+{
+  x += a;
+  return x;
+}
+
+int
+main ()
+{
+  int some_ints[5];
+
+  some_ints[0] = 0;
+  some_ints[1] = 1;
+  some_ints[2] = 2;
+  some_ints[3] = 3;
+  some_ints[4] = 4;
+  return my_foo_function (some_ints[4]) > 0; /* break here */
+}
diff --git a/gdb/testsuite/gdb.base/slash_command.exp b/gdb/testsuite/gdb.base/slash_command.exp
new file mode 100644
index 0000000000..eb83057d2c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/slash_command.exp
@@ -0,0 +1,125 @@
+# Copyright 2019 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file verifies the logic to temporarily change some settings
+# using the slash command.
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
+    return -1
+}
+
+if { ![runto_main] } then {
+    fail "can't run to main"
+    return 0
+}
+set loc [gdb_get_line_number "break here"]
+gdb_test "break $loc" ".*" "set breakpoint"
+gdb_continue_to_breakpoint "continue to breakpoint"
+
+# 'set language' == /lX
+proc check_info_function { prefix slash_seq desired_layout } {
+    gdb_test "$slash_seq info functions my_foo_function" \
+	[multi_line \
+	     "All functions matching regular expression \"my_foo_function\":" \
+	     "" \
+	     "File .*slash_command.c:" \
+	     $desired_layout
+	] \
+	$prefix
+
+}
+check_info_function "lang_auto" "" \
+    "${decimal}:	int my_foo_function\\(int\\);"
+check_info_function "slash_switch_to_Ada" "/lA" \
+    "${decimal}:	function my_foo_function \\(a1: int\\) return int;.*"
+check_info_function "lang_auto_after_slash" "" \
+    "${decimal}:	int my_foo_function\\(int\\);"
+gdb_test "set language ada"
+check_info_function "set_switch_to_Ada" "" \
+    "${decimal}:	function my_foo_function \\(a1: int\\) return int;.*"
+gdb_test "set language auto"
+
+# 'set print elements' == /Xe
+gdb_test "print some_ints" " = \\{0, 1, 2, 3, 4\\}" "default print"
+gdb_test "/2e print some_ints" "= \\{0, 1\.\.\.\\}" "temp print 2"
+gdb_test "set print elements 2" "" "set default print 2"
+gdb_test "print some_ints" "= \\{0, 1\.\.\.\\}" "default print 2"
+gdb_test "/2e print some_ints" "= \\{0, 1\.\.\.\\}" "temp print 2, default 2"
+gdb_test "/3e print some_ints" "= \\{0, 1, 2\.\.\.\\}" "temp print 3, default 2"
+gdb_test "print some_ints" "= \\{0, 1\.\.\.\\}" "default re-print 2"
+gdb_test "set print elements 200"
+gdb_test "show print elements" "is 200." "default show elt 200"
+gdb_test "/100e show print elements" "is 100." "temp show elt 100"
+gdb_test "/e show print elements" "is unlimited." "temp show elt unlimited"
+
+# 'set print array' == /a
+gdb_test "/a print some_ints" \
+    [multi_line \
+	 "\\{0," \
+	 "  1," \
+	 "  2," \
+	 "  3," \
+	 "  4}" \
+	] \
+    "temp pretty array"
+gdb_test "set print array on" "" "set default print array on"
+gdb_test "/!a print some_ints" \
+    " = \\{0, 1, 2, 3, 4\\}" "temp print array off"
+gdb_test "set print array off" "" "set default print array off"
+
+# 'set print array-indexes' == /i
+set array_index_match \
+    "= \\{\\\[0] = 0, \\\[1] = 1, \\\[2] = 2, \\\[3] = 3, \\\[4] = 4\\}"
+gdb_test "/i print some_ints" \
+    $array_index_match \
+    "temp print array-indexes"
+gdb_test "set print array-indexes on" "" "set default print array-indexes on"
+gdb_test "/i print some_ints" \
+    $array_index_match \
+    "temp print array-indexes default on"
+gdb_test "set print array-indexes off" "" "set default print array-indexes off"
+
+
+# Now, test some combinations of all the above.
+foreach slash_seq {
+    "/lAai2e"
+    "/ai2elA"
+    "/2eailA"} {
+    gdb_test "$slash_seq print some_ints" \
+	[multi_line \
+	     "= \\\(0 => 0," \
+	     "  1 => 1\.\.\.\\\).*" \
+	    ] \
+	"combination $slash_seq"
+}
+
+
+# Error handling.
+gdb_test "/123a show print array" \
+    [multi_line \
+	 "Value type for / setting \"a\" \\\(set print array\\\) is 'Boolean on\\\|off'\." \
+	 "Found unexpected 'Unsigned integer \\\(0 means unlimited\\\)' qualifier at \"123a show print array\""
+	] \
+    "unsigned integer must be followed by unsigned setting."
+
+gdb_test "/!e show print elements" \
+    [multi_line \
+	 "Value type for / setting \"e\" \\\(set print elements\\\) is 'Unsigned integer \\\(0 means unlimited\\\)'\." \
+	 "Found unexpected 'Boolean on\\\|off' qualifier at \"!e show print elements\"" \
+	] \
+    "! must be followed by boolean setting."
+
-- 
2.20.1

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

* [RFA 3/3] NEWS and documentation for / (slash) command.
  2019-04-13 19:00 [RFA 0/3] / command : fast way to change setting(s) to run a command Philippe Waroquiers
  2019-04-13 19:00 ` [RFA 2/3] Test for slash_command Philippe Waroquiers
@ 2019-04-13 19:00 ` Philippe Waroquiers
  2019-04-13 19:10   ` Eli Zaretskii
  2019-04-13 19:00 ` [RFA 1/3] / command : fast way to change setting(s), run a command, reset settings(s) Philippe Waroquiers
  2 siblings, 1 reply; 8+ messages in thread
From: Philippe Waroquiers @ 2019-04-13 19:00 UTC (permalink / raw)
  To: gdb-patches; +Cc: Philippe Waroquiers

gdb/ChangeLog
2019-04-13  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* NEWS: Mention new slash command.

gdb/doc/ChangeLog
2019-04-13  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.texinfo (Command Settings): New node documenting
	the general concept of settings, how to change them, and the
	new / command.
---
 gdb/NEWS            |  14 +++++
 gdb/doc/gdb.texinfo | 132 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 146 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index 5309a8f923..1ec0418881 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -27,6 +27,20 @@
      'array_indexes', 'symbols', 'unions', 'deref_refs', 'actual_objects',
      'static_members', 'max_elements', 'repeat_threshold', and 'format'.
 
+* New commands
+
+/SETTING... COMMAND
+  The / command temporarily changes some settings according to SETTING
+  to run COMMAND.  After running COMMAND, the settings are reset to
+  the values they had before the execution.
+  For example, '/lc print somevar' temporarily
+  switches to the C language in order to print somevar.
+  '/r print somevariable' temporarily sets unlimited repeat value
+  to print somevariable.  Settings can be combined: '/rlc print somevar'
+  will switch to the C language and print somevar with an unlimited
+  repeat value.
+  Use 'help /' to list all settings that are temporarily changeable.
+
 *** Changes in GDB 8.3
 
 * GDB and GDBserver now support access to additional registers on
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index f410d026b8..7521d40036 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1493,6 +1493,7 @@ show you the alternatives available, if there is more than one possibility).
 
 @menu
 * Command Syntax::              How to give commands to @value{GDBN}
+* Command Settings::            How to change default behaviour of commands
 * Completion::                  Command completion
 * Help::                        How to ask @value{GDBN} for help
 @end menu
@@ -1548,6 +1549,137 @@ commands.  This command accepts the current line, like @key{RET}, and
 then fetches the next line relative to the current line from the history
 for editing.
 
+
+@node Command Settings
+@section Command Settings
+@cindex change default behaviour of commands
+@cindex change default settings
+
+Many commands change their behaviour according to command specific
+variables or settings, that can be changed interactively.
+For example, the @code{print} @pxref{Arguments} command will print arrays
+differently depending on various settings changeable by the commands
+@code{set print elements NUMBER-OF-ELEMENTS},
+@code{set print array-indexes}, @dots{}.
+
+These settings can be set in the gdbinit files loaded at @value{GDBN} startup.
+@xref{Startup}.
+
+The settings can also be changed interactively during the debugging session.
+For example, to change the limit of array elements to print,
+the following can be done:
+@smallexample
+(@value{GDBN}) set print elements 10
+print some_array
+$3 = @{0, 10, 20, 30, 40, 50, 60, 70, 80, 90...@}
+@end smallexample
+
+The default value of 200 elements to print has been changed to 10
+by the above @code{set print elements 10} command.  The value of 10
+becomes the new default.  It this value of 10 is to be used only
+for printing @code{some_array}, then the command
+@code{set print elements 200} must be executed to set the default back
+to 200.
+
+@kindex slash command
+@kindex /
+@cindex Settings
+@cindex Temporarily change settings
+@noindent
+@code{/SETTING... COMMAND}: Temporarily change settings for only one command.
+
+The @code{/} (slash) command allows to temporarily change various
+settings to run a specific command.  For example, the command
+@smallexample
+/a10e print some_array
+@end smallexample
+@noindent
+is equivalent to the following 5 commands:
+@smallexample
+set print array on
+set print elements 10
+print some_array
+set print elements 200
+set print array off
+@end smallexample
+
+Each temporarily changeable setting is identified by a sequence of
+one or more letters.  The most frequently used settings are identified
+by a single lower case letter.  Less frequently used settings are identified
+by one or more upper case letters, followed by a single lower case letter.
+
+For example, the setting @code{set print elements} is identified by
+the letter @code{e}.  The setting @code{set backtrace past-entry} is
+identified by the letters @code{Be}.
+
+@noindent
+Three types of settings can be temporarily changed by the @code{/} command:
+
+@table @code
+@item Boolean settings
+A boolean setting is temporarily activated (set to @code{on}) by
+giving its sequence of letters.  To temporarily deactivate (set to @code{off})
+a boolean setting, its sequence of letter must be prefixed by the
+exclamation mark character @code{!}.
+
+@item Unsigned integer settings
+An unsigned integer setting is temporarily changed by giving the desired
+numeric value followed by its sequence of letters.  If no numeric value
+preceedes the setting, the setting is temporarily changed to unlimited.
+The value 0 also indicates to change the setting to unlimited.
+
+@item Enumeration settings
+An enumeration setting is temporarily changed by giving its sequence
+of letters followed by a single character designating the chosen
+enumeration value.  For example, the letter @code{l} identifies
+the @code{set language} setting.  Using @code{/lA print somevar}
+will temporarily change the language to Ada (identified by the letter
+@code{A}) to execute the command @code{print somevar}, while
+@code{/lf print somevar} will rather switch to fortran.
+
+@end table
+
+To change several settings for the same command, just append each
+desired setting once after each other.  For example, @code{/lA10e}
+will temporarily change the language to Ada and set a limit of 10 elements
+to print for arrays and strings.
+
+The following table gives the list of settings that the @code{/} command
+can temporarily change.  The first column gives the letter sequence
+identifying the setting corresponding to the command in the second column.
+The third column gives the type of the setting, and list the different
+possible values for the enumeration settings.  Note that the below table
+is produced by the @code{help /} command.
+
+@smallexample
+@c In the 'doc' build directory, the following can be produced by:
+@c ../../gdb/gdb -q --nx  -ex 'set width 80' -ex 'set height 0' -ex 'help /' -ex quit |
+@c   sed -e '1,/The temporarily changeable settings are:/d' -e ':a;s/^\( *\) /@\1/;ta' -e 's/^/@exdent /'
+@c Maybe this could/should be automated by the doc Makefile ?
+@exdent /Be       set backtrace past-entry       Boolean on|off
+@exdent /Bl       set backtrace limit            Unsigned integer (0 means unlimited)
+@exdent /Bm       set backtrace past-main        Boolean on|off
+@exdent /Co       set print object               Boolean on|off
+@exdent /Cs       set print static-members       Boolean on|off
+@exdent /Cv       set print vtbl                 Boolean on|off
+@exdent /Pa       set print address              Boolean on|off
+@exdent /Ps       set print symbol               Boolean on|off
+@exdent /Rf       set print raw frame-arguments  Boolean on|off
+@exdent /a        set print array                Boolean on|off
+@exdent /e        set print elements             Unsigned integer (0 means unlimited)
+@exdent /f[asn]   set print frame-arguments      Enum, a = all, s = scalars, n = none
+@exdent /i        set print array-indexes        Boolean on|off
+@exdent /l[aluAscCdfgmMOo] set language          Enum, a = auto, l = local,
+@exdent @                               u = unknown, A = ada, s = asm, c = c, C = c++,
+@exdent @                               d = d, f = fortran, g = go, m = minimal,
+@exdent @                               M = modula-2, O = objective-c, o = opencl
+@exdent /n        set print null-stop            Boolean on|off
+@exdent /p        set print pretty               Boolean on|off
+@exdent /r        set print repeats              Unsigned integer (0 means unlimited)
+@exdent /u        set print union                Boolean on|off
+@exdent /v        set varsize-limit              Unsigned integer (0 means unlimited)
+@end smallexample
+
 @node Completion
 @section Command Completion
 
-- 
2.20.1

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

* Re: [RFA 3/3] NEWS and documentation for / (slash) command.
  2019-04-13 19:00 ` [RFA 3/3] NEWS and documentation for / (slash) command Philippe Waroquiers
@ 2019-04-13 19:10   ` Eli Zaretskii
  2019-04-13 19:22     ` Philippe Waroquiers
  0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2019-04-13 19:10 UTC (permalink / raw)
  To: Philippe Waroquiers; +Cc: gdb-patches

> From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
> Cc: Philippe Waroquiers <philippe.waroquiers@skynet.be>
> Date: Sat, 13 Apr 2019 21:00:16 +0200
> 
> +* New commands
> +
> +/SETTING... COMMAND
> +  The / command temporarily changes some settings according to SETTING
> +  to run COMMAND.
     ^^^^^^^^^^^^^^
I'd say "for the duration of COMMAND" instead.

> +@cindex Settings
> +@cindex Temporarily change settings

By convention, index entries are not capitalized, to avoid problems
with sorting them alphabetically (which produces locale-dependent
results).

> +The following table gives the list of settings that the @code{/} command
> +can temporarily change.  The first column gives the letter sequence
> +identifying the setting corresponding to the command in the second column.
> +The third column gives the type of the setting, and list the different
> +possible values for the enumeration settings.  Note that the below table
> +is produced by the @code{help /} command.
> +
> +@smallexample
> +@c In the 'doc' build directory, the following can be produced by:
> +@c ../../gdb/gdb -q --nx  -ex 'set width 80' -ex 'set height 0' -ex 'help /' -ex quit |
> +@c   sed -e '1,/The temporarily changeable settings are:/d' -e ':a;s/^\( *\) /@\1/;ta' -e 's/^/@exdent /'
> +@c Maybe this could/should be automated by the doc Makefile ?
> +@exdent /Be       set backtrace past-entry       Boolean on|off
> +@exdent /Bl       set backtrace limit            Unsigned integer (0 means unlimited)

Please rewrite this as a @multitable, so that it looks good in all
formats.

Thanks.

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

* Re: [RFA 3/3] NEWS and documentation for / (slash) command.
  2019-04-13 19:10   ` Eli Zaretskii
@ 2019-04-13 19:22     ` Philippe Waroquiers
  0 siblings, 0 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2019-04-13 19:22 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Thanks for the review and the (as usual) good
suggestions/comments.
I will handle them for the next version.

Note that (if not done yet), it might be good
to check the on-line 'help /' doc which is in the top.c file
(see [RFA 1/3]).

Thanks

Philippe

On Sat, 2019-04-13 at 22:10 +0300, Eli Zaretskii wrote:
> > From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
> > Cc: Philippe Waroquiers <philippe.waroquiers@skynet.be>
> > Date: Sat, 13 Apr 2019 21:00:16 +0200
> > 
> > +* New commands
> > +
> > +/SETTING... COMMAND
> > +  The / command temporarily changes some settings according to SETTING
> > +  to run COMMAND.
> 
>      ^^^^^^^^^^^^^^
> I'd say "for the duration of COMMAND" instead.
> 
> > +@cindex Settings
> > +@cindex Temporarily change settings
> 
> By convention, index entries are not capitalized, to avoid problems
> with sorting them alphabetically (which produces locale-dependent
> results).
> 
> > +The following table gives the list of settings that the @code{/} command
> > +can temporarily change.  The first column gives the letter sequence
> > +identifying the setting corresponding to the command in the second column.
> > +The third column gives the type of the setting, and list the different
> > +possible values for the enumeration settings.  Note that the below table
> > +is produced by the @code{help /} command.
> > +
> > +@smallexample
> > +@c In the 'doc' build directory, the following can be produced by:
> > +@c ../../gdb/gdb -q --nx  -ex 'set width 80' -ex 'set height 0' -ex 'help /' -ex quit |
> > +@c   sed -e '1,/The temporarily changeable settings are:/d' -e ':a;s/^\( *\) /@\1/;ta' -e 's/^/@exdent /'
> > +@c Maybe this could/should be automated by the doc Makefile ?
> > +@exdent /Be       set backtrace past-entry       Boolean on|off
> > +@exdent /Bl       set backtrace limit            Unsigned integer (0 means unlimited)
> 
> Please rewrite this as a @multitable, so that it looks good in all
> formats.
> 
> Thanks.

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

* Re: [RFA 1/3] / command : fast way to change setting(s), run a command, reset settings(s).
  2019-04-13 19:00 ` [RFA 1/3] / command : fast way to change setting(s), run a command, reset settings(s) Philippe Waroquiers
@ 2019-04-14 18:20   ` Kevin Buettner
  2019-04-15  7:34     ` Philippe Waroquiers
  0 siblings, 1 reply; 8+ messages in thread
From: Kevin Buettner @ 2019-04-14 18:20 UTC (permalink / raw)
  To: Philippe Waroquiers; +Cc: gdb-patches

On Sat, 13 Apr 2019 21:00:14 +0200
Philippe Waroquiers <philippe.waroquiers@skynet.be> wrote:

> GDB has a lot of settings related to how commands behaves and/or print things.
> 
> There is however currently no easy way to temporarily change a setting
> for a command.
> This patch implements a new command called /, that allows to temporarily
> change the settings in order to execute another command.
> The objective for this / command is to be fast to type, so it uses
> 1 or 2 letters codes to identify which settings(s) to temporarily set.

Hi Philippe,

I'd like to see some discussion regarding your proposed changes to
the command line interface first.  (Though it is indeed useful to have
a patch to try out your proposed changes.)

I think it might be useful to post your examples along with a pointer
to this patch set to gdb@sourceware.org.

If this discussion has already occurred and I've somehow missed it,
I'd appreciate a link...

Kevin

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

* Re: [RFA 1/3] / command : fast way to change setting(s), run a command, reset settings(s).
  2019-04-14 18:20   ` Kevin Buettner
@ 2019-04-15  7:34     ` Philippe Waroquiers
  0 siblings, 0 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2019-04-15  7:34 UTC (permalink / raw)
  To: Kevin Buettner; +Cc: gdb-patches

On Sun, 2019-04-14 at 11:20 -0700, Kevin Buettner wrote:
> On Sat, 13 Apr 2019 21:00:14 +0200
> Philippe Waroquiers <philippe.waroquiers@skynet.be> wrote:
> 
> > GDB has a lot of settings related to how commands behaves and/or print things.
> > 
> > There is however currently no easy way to temporarily change a setting
> > for a command.
> > This patch implements a new command called /, that allows to temporarily
> > change the settings in order to execute another command.
> > The objective for this / command is to be fast to type, so it uses
> > 1 or 2 letters codes to identify which settings(s) to temporarily set.
> 
> Hi Philippe,
> 
> I'd like to see some discussion regarding your proposed changes to
> the command line interface first.  (Though it is indeed useful to have
> a patch to try out your proposed changes.)
> 
> I think it might be useful to post your examples along with a pointer
> to this patch set to gdb@sourceware.org.
> 
> If this discussion has already occurred and I've somehow missed it,
> I'd appreciate a link...
There was an RFC on gdb-patches but no previous discussion on gdb.
So, here it is:
https://sourceware.org/ml/gdb/2019-04/msg00006.html

Thanks
Philippe

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

end of thread, other threads:[~2019-04-15  7:34 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-13 19:00 [RFA 0/3] / command : fast way to change setting(s) to run a command Philippe Waroquiers
2019-04-13 19:00 ` [RFA 2/3] Test for slash_command Philippe Waroquiers
2019-04-13 19:00 ` [RFA 3/3] NEWS and documentation for / (slash) command Philippe Waroquiers
2019-04-13 19:10   ` Eli Zaretskii
2019-04-13 19:22     ` Philippe Waroquiers
2019-04-13 19:00 ` [RFA 1/3] / command : fast way to change setting(s), run a command, reset settings(s) Philippe Waroquiers
2019-04-14 18:20   ` Kevin Buettner
2019-04-15  7:34     ` Philippe Waroquiers

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