This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 1/7] new observer command_option_changed.
Hi,
This patch is to add an extra field 'notify_observer_p' to identify
the command will notify observer 'command_option_changed', and teach
GDB to check the change of command option, and notify observer.
Compared with V1, V2 has following changes,
1. Move notifying 'command_option_changed' observer out of
do_setshow_command to its caller, execute_command, so that we can
get the full command line to send MI notification for multi-word
options.
2. Split do_setshow_command to do_set_command and do_show_command.
Note that in order to make patch easier to read, the indnetation is
not adjusted. Indentation is fixed in a separate patch.
gdb:
2012-07-27 Yao Qi <yao@codesourcery.com>
* cli/cli-decode.c (add_cmd): Set field 'notify_observer_p' to 0.
(add_setshow_auto_boolean_cmd): Move auto_boolean_enums out.
Remove 'static'.
* cli/cli-decode.h (struct cmd_list_element) <notify_observer_p>:
New field.
Declare 'auto_boolean_enums'.
* cli/cli-setshow.c (do_setshow_command): Split it to ...
(do_set_command, do_show_command): ... them. New.
(cmd_show_list): Caller update.
* auto-load.c (set_auto_load_cmd): Likewise.
* remote.c (show_remote_cmd): Likewise.
* cli/cli-setshow.h: Update declarations.
* top.c (execute_command): Call do_set_command and
call observer_notify_command_option_changed if it return true.
gdb/doc:
2012-07-27 Yao Qi <yao@codesourcery.com>
* observer.texi: New observer command_option_changed.
---
gdb/auto-load.c | 2 +-
gdb/cli/cli-decode.c | 4 +-
gdb/cli/cli-decode.h | 4 +
gdb/cli/cli-setshow.c | 164 ++++++++++++++++++++++++++++++++++++------------
gdb/cli/cli-setshow.h | 10 +--
gdb/doc/observer.texi | 8 +++
gdb/remote.c | 2 +-
gdb/top.c | 22 ++++++-
8 files changed, 163 insertions(+), 53 deletions(-)
diff --git a/gdb/auto-load.c b/gdb/auto-load.c
index 87dd1e4..471a8a7 100644
--- a/gdb/auto-load.c
+++ b/gdb/auto-load.c
@@ -1024,7 +1024,7 @@ set_auto_load_cmd (char *args, int from_tty)
if (list->var_type == var_boolean)
{
gdb_assert (list->type == set_cmd);
- do_setshow_command (args, from_tty, list);
+ do_set_command (args, from_tty, list);
}
}
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index c337b43..35c7e1e 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -203,6 +203,7 @@ add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
c->user_commands = NULL;
c->cmd_pointer = NULL;
c->alias_chain = NULL;
+ c->notify_observer_p = 0;
return c;
}
@@ -430,6 +431,8 @@ add_setshow_enum_cmd (char *name,
c->enums = enumlist;
}
+const char * const auto_boolean_enums[] = { "on", "off", "auto", NULL };
+
/* Add an auto-boolean command named NAME to both the set and show
command list lists. CLASS is as in add_cmd. VAR is address of the
variable which will contain the value. DOC is the documentation
@@ -445,7 +448,6 @@ add_setshow_auto_boolean_cmd (char *name,
struct cmd_list_element **set_list,
struct cmd_list_element **show_list)
{
- static const char *auto_boolean_enums[] = { "on", "off", "auto", NULL };
struct cmd_list_element *c;
add_setshow_cmd_full (name, class, var_auto_boolean, var,
diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h
index b5e0790..ae5d0a1 100644
--- a/gdb/cli/cli-decode.h
+++ b/gdb/cli/cli-decode.h
@@ -210,6 +210,9 @@ struct cmd_list_element
/* Link pointer for aliases on an alias list. */
struct cmd_list_element *alias_chain;
+
+ /* Notify 'command_option_changed' observer if it is true. */
+ int notify_observer_p;
};
extern void help_cmd_list (struct cmd_list_element *, enum command_class,
@@ -232,5 +235,6 @@ extern void not_just_help_class_command (char *arg, int from_tty);
extern void print_doc_line (struct ui_file *, char *);
+extern const char * const auto_boolean_enums[];
#endif /* !defined (CLI_DECODE_H) */
diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index 7ffb89e..17c336e 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -116,18 +116,20 @@ deprecated_show_value_hack (struct ui_file *ignore_file,
}
}
-/* Do a "set" or "show" command. ARG is NULL if no argument, or the
+/* Do a "set" command. ARG is NULL if no argument, or the
text of the argument, and FROM_TTY is nonzero if this command is
being entered directly by the user (i.e. these are just like any
- other command). C is the command list element for the command. */
+ other command). C is the command list element for the command. Return
+ true if command option is changed, otherwise return false. */
-void
-do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
+int
+do_set_command (char *arg, int from_tty, struct cmd_list_element *c)
{
- struct ui_out *uiout = current_uiout;
+ /* A flag to indicate the option is changed or not. */
+ int option_changed = 0;
+
+ gdb_assert (c->type == set_cmd);
- if (c->type == set_cmd)
- {
switch (c->var_type)
{
case var_string:
@@ -170,50 +172,106 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
#endif
*q++ = '\0';
new = (char *) xrealloc (new, q - new);
- xfree (*(char **) c->var);
- *(char **) c->var = new;
+
+ if (*(char **) c->var == NULL
+ || strcmp (*(char **) c->var, new) != 0)
+ {
+ xfree (*(char **) c->var);
+ *(char **) c->var = new;
+
+ option_changed = 1;
+ }
+ else
+ xfree (new);
}
break;
case var_string_noescape:
if (arg == NULL)
arg = "";
- xfree (*(char **) c->var);
- *(char **) c->var = xstrdup (arg);
+
+ if (*(char **) c->var == NULL || strcmp (*(char **) c->var, arg) != 0)
+ {
+ xfree (*(char **) c->var);
+ *(char **) c->var = xstrdup (arg);
+
+ option_changed = 1;
+ }
break;
case var_filename:
if (arg == NULL)
error_no_arg (_("filename to set it to."));
/* FALLTHROUGH */
case var_optional_filename:
- xfree (*(char **) c->var);
+ {
+ char *val = NULL;
- if (arg != NULL)
- {
- /* Clear trailing whitespace of filename. */
- char *ptr = arg + strlen (arg) - 1;
+ if (arg != NULL)
+ {
+ /* Clear trailing whitespace of filename. */
+ char *ptr = arg + strlen (arg) - 1;
- while (ptr >= arg && (*ptr == ' ' || *ptr == '\t'))
- ptr--;
- *(ptr + 1) = '\0';
+ while (ptr >= arg && (*ptr == ' ' || *ptr == '\t'))
+ ptr--;
+ *(ptr + 1) = '\0';
- *(char **) c->var = tilde_expand (arg);
- }
- else
- *(char **) c->var = xstrdup ("");
+ val = tilde_expand (arg);
+ }
+ else
+ val = xstrdup ("");
+
+ if (*(char **) c->var == NULL
+ || strcmp (*(char **) c->var, val) != 0)
+ {
+ xfree (*(char **) c->var);
+ *(char **) c->var = val;
+
+ option_changed = 1;
+ }
+ else
+ xfree (val);
+ }
break;
case var_boolean:
- *(int *) c->var = parse_binary_operation (arg);
+ {
+ int val = parse_binary_operation (arg);
+
+ if (val != *(int *) c->var)
+ {
+ *(int *) c->var = val;
+
+ option_changed = 1;
+ }
+ }
break;
case var_auto_boolean:
- *(enum auto_boolean *) c->var = parse_auto_binary_operation (arg);
+ {
+ enum auto_boolean val = parse_auto_binary_operation (arg);
+
+ if (*(enum auto_boolean *) c->var != val)
+ {
+ *(enum auto_boolean *) c->var = val;
+
+ option_changed = 1;
+ }
+ }
break;
case var_uinteger:
case var_zuinteger:
if (arg == NULL)
error_no_arg (_("integer to set it to."));
- *(unsigned int *) c->var = parse_and_eval_long (arg);
- if (c->var_type == var_uinteger && *(unsigned int *) c->var == 0)
- *(unsigned int *) c->var = UINT_MAX;
+ {
+ unsigned int val = parse_and_eval_long (arg);
+
+ if (c->var_type == var_uinteger && val == 0)
+ val = UINT_MAX;
+
+ if (*(unsigned int *) c->var != val)
+ {
+ *(unsigned int *) c->var = val;
+
+ option_changed = 1;
+ }
+ }
break;
case var_integer:
case var_zinteger:
@@ -224,11 +282,17 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
error_no_arg (_("integer to set it to."));
val = parse_and_eval_long (arg);
if (val == 0 && c->var_type == var_integer)
- *(int *) c->var = INT_MAX;
+ val = INT_MAX;
else if (val >= INT_MAX)
error (_("integer %u out of range"), val);
- else
- *(int *) c->var = val;
+
+
+ if (*(int *) c->var != val)
+ {
+ *(int *) c->var = val;
+
+ option_changed = 1;
+ }
break;
}
case var_enum:
@@ -293,15 +357,36 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
if (nmatches > 1)
error (_("Ambiguous item \"%s\"."), arg);
- *(const char **) c->var = match;
+ if (*(const char **) c->var != match)
+ {
+ *(const char **) c->var = match;
+
+ option_changed = 1;
+ }
}
break;
default:
error (_("gdb internal error: bad var_type in do_setshow_command"));
}
- }
- else if (c->type == show_cmd)
- {
+ c->func (c, NULL, from_tty);
+ if (deprecated_set_hook)
+ deprecated_set_hook (c);
+
+ return option_changed;
+}
+
+/* Do a "show" command. ARG is NULL if no argument, or the
+ text of the argument, and FROM_TTY is nonzero if this command is
+ being entered directly by the user (i.e. these are just like any
+ other command). C is the command list element for the command. */
+
+void
+do_show_command (char *arg, int from_tty, struct cmd_list_element *c)
+{
+ struct ui_out *uiout = current_uiout;
+
+ gdb_assert (c->type == show_cmd);
+ {
struct cleanup *old_chain;
struct ui_file *stb;
@@ -387,12 +472,9 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
deprecated_show_value_hack (gdb_stdout, from_tty, c, value);
}
do_cleanups (old_chain);
- }
- else
- error (_("gdb internal error: bad cmd_type in do_setshow_command"));
+
c->func (c, NULL, from_tty);
- if (c->type == set_cmd && deprecated_set_hook)
- deprecated_set_hook (c);
+ }
}
/* Show all the settings in a list of show commands. */
@@ -431,7 +513,7 @@ cmd_show_list (struct cmd_list_element *list, int from_tty, char *prefix)
ui_out_field_string (uiout, "name", list->name);
ui_out_text (uiout, ": ");
if (list->type == show_cmd)
- do_setshow_command ((char *) NULL, from_tty, list);
+ do_show_command ((char *) NULL, from_tty, list);
else
cmd_func (list, NULL, from_tty);
/* Close the tuple. */
diff --git a/gdb/cli/cli-setshow.h b/gdb/cli/cli-setshow.h
index cb8d2c5..8f43e53 100644
--- a/gdb/cli/cli-setshow.h
+++ b/gdb/cli/cli-setshow.h
@@ -21,12 +21,10 @@ struct cmd_list_element;
/* Exported to cli/cli-cmds.c and gdb/top.c */
-/* Do a "set" or "show" command. ARG is NULL if no argument, or the
- text of the argument, and FROM_TTY is nonzero if this command is
- being entered directly by the user (i.e. these are just like any
- other command). C is the command list element for the command. */
-extern void do_setshow_command (char *arg, int from_tty,
- struct cmd_list_element *c);
+extern int do_set_command (char *arg, int from_tty,
+ struct cmd_list_element *c);
+extern void do_show_command (char *arg, int from_tty,
+ struct cmd_list_element *c);
/* Exported to cli/cli-cmds.c and gdb/top.c, language.c and valprint.c */
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index 14d4ac3..4c44a80 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -234,6 +234,14 @@ the current top-level prompt.
Variable gdb_datadir has been set. The value may not necessarily change.
@end deftypefun
+@deftypefun void command_option_changed (const char *@var{option}, const char *@var{value})
+The option of some @code{set} commands in console are changed. This
+method is called after a command @code{set @var{option} @var{value}}.
+@var{option} is the option of @code{set} command, and @var{value}
+is the value of changed option.
+
+@end deftypefun
+
@deftypefun void test_notification (int @var{somearg})
This observer is used for internal testing. Do not use.
See testsuite/gdb.gdb/observer.exp.
diff --git a/gdb/remote.c b/gdb/remote.c
index fa514dc..87b8921 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -11270,7 +11270,7 @@ show_remote_cmd (char *args, int from_tty)
ui_out_field_string (uiout, "name", list->name);
ui_out_text (uiout, ": ");
if (list->type == show_cmd)
- do_setshow_command ((char *) NULL, from_tty, list);
+ do_show_command ((char *) NULL, from_tty, list);
else
cmd_func (list, NULL, from_tty);
/* Close the tuple. */
diff --git a/gdb/top.c b/gdb/top.c
index 061ad48..46fa9c3 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -412,7 +412,7 @@ execute_command (char *p, int from_tty)
{
struct cleanup *cleanup_if_error, *cleanup;
struct cmd_list_element *c;
- char *line;
+ char *line, *orig;
cleanup_if_error = make_bpstat_clear_actions_cleanup ();
cleanup = prepare_execute_command ();
@@ -468,14 +468,30 @@ execute_command (char *p, int from_tty)
/* If this command has been pre-hooked, run the hook first. */
execute_cmd_pre_hook (c);
+ orig = line;
if (c->flags & DEPRECATED_WARN_USER)
deprecated_cmd_warning (&line);
/* c->user_commands would be NULL in the case of a python command. */
if (c->class == class_user && c->user_commands)
execute_user_command (c, arg);
- else if (c->type == set_cmd || c->type == show_cmd)
- do_setshow_command (arg, from_tty, c);
+ else if (c->type == set_cmd)
+ {
+ if (do_set_command (arg, from_tty, c) && c->notify_observer_p)
+ {
+ /* Skip 'set ' */
+ int len = arg - orig - 4;
+ char *option = xmalloc (len);
+
+ memcpy (option, orig + 4, len - 1);
+ option[len - 1] = 0;
+
+ observer_notify_command_option_changed (option, arg);
+ xfree (option);
+ }
+ }
+ else if (c->type == show_cmd)
+ do_show_command (arg, from_tty, c);
else if (!cmd_func_p (c))
error (_("That is not a command, just a help topic."));
else if (deprecated_call_command_hook)
--
1.7.7.6