diff options
-rw-r--r-- | gdb/ChangeLog | 43 | ||||
-rw-r--r-- | gdb/command.c | 248 | ||||
-rw-r--r-- | gdb/command.h | 60 | ||||
-rw-r--r-- | gdb/maint.c | 126 | ||||
-rw-r--r-- | gdb/top.c | 25 |
5 files changed, 474 insertions, 28 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8d5b70e..d4ec901 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,39 @@ +2000-03-23 Fernando Nasser <fnasser@cygnus.com> + + From David Whedon <dwhedon@gordian.com> + + * top.c (execute_command): Checks all commands beore executing + to see if the user needs to be warned that the command is + deprecated, warns user if appropriate. + (add_info), (add_info_alias), (add_com) , (add_com_alias): Changed + return values from void to struct cmd_list_element *. + * command.c (lookup_cmd_1): Check aliases before following link + in case user needs to be warned about a deprecated alias. + (deprecate_cmd): new exported function for command deprecation, + sets flags and posibly a replacement string. + (deprecated_cmd_warning): New exported funciton to warn user about + a deprecated command. + (lookup_cmd_composition): New exported function that determines + alias, prefix_command, and cmd based on a string. This is useful + is we want to full name of a command. + * command.h : Added prototypes for deprecate_cmd, + deprecated_warn_user and lookup_cmd_composition, added flags to + the cmd_list_element structure, changed return values for + add_com_* and add_info_* from void to cmd_list_element. + * maint.c : (maintenance_deprecate): New function to deprecate a + command. This exists only so that the testsuite can deprecate + commands at runtime and check the warning behavior. + (maintenance_undeprecate) : New function, drops deprecated flags. + (maintenance_do_deprecate): Actually does the (un)deprecation. + (initialize_maint_cmds): Added the above new deprecate commands. + +2000-03-22 Daniel Berlin <dan@cgsoftware.com> + * command.c (apropos_cmd_helper): New function, meat of the + apropos command. + (apropos_command): New apropos command to search command + names/documentation for regular expressions. + (_initialize_command): Add the apropos command. + 2000-03-23 Michael Snyder <msnyder@cleaver.cygnus.com> * sol-thread.c (ps_pglobal_lookup): Change argument type from @@ -40,13 +76,6 @@ (delete_file_handler, handle_file_event): Likewise. (gdb_wait_for_event, poll_timers): Likewise. -2000-03-22 Daniel Berlin <dan@cgsoftware.com> - * command.c (apropos_cmd_helper): New function, meat of the - apropos command. - (apropos_command): New apropos command to search command - names/documentation for regular expressions. - (_initialize_command): Add the apropos command. - 2000-03-22 Peter Schauer <pes@regent.e-technik.tu-muenchen.de> * printcmd.c (print_scalar_formatted): Truncate addresses to the diff --git a/gdb/command.c b/gdb/command.c index 826cc46..737ac77 100644 --- a/gdb/command.c +++ b/gdb/command.c @@ -112,6 +112,8 @@ add_cmd (name, class, fun, doc, list) c->class = class; c->function.cfunc = fun; c->doc = doc; + c->flags = 0; + c->replacement = NULL; c->hook = NULL; c->prefixlist = NULL; c->prefixname = NULL; @@ -129,6 +131,33 @@ add_cmd (name, class, fun, doc, list) return c; } + +/* Deprecates a command CMD. + REPLACEMENT is the name of the command which should be used in place + of this command, or NULL if no such command exists. + + This function does not check to see if command REPLACEMENT exists + since gdb may not have gotten around to adding REPLACEMENT when this + function is called. + + Returns a pointer to the deprecated command. */ + +struct cmd_list_element * +deprecate_cmd (cmd, replacement) + struct cmd_list_element *cmd; + char *replacement; +{ + cmd->flags |= (CMD_DEPRECATED | DEPRECATED_WARN_USER); + + if (replacement != NULL) + cmd->replacement = replacement; + else + cmd->replacement = NULL; + + return cmd; +} + + /* Same as above, except that the abbrev_flag is set. */ #if 0 /* Currently unused */ @@ -730,6 +759,7 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes) char *p, *command; int len, tmp, nfound; struct cmd_list_element *found, *c; + char *line = *text; while (**text == ' ' || **text == '\t') (*text)++; @@ -799,11 +829,19 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes) *text = p; - /* If this was an abbreviation, use the base command instead. */ - if (found->cmd_pointer) - found = found->cmd_pointer; - + { + /* We drop the alias (abbreviation) in favor of the command it is + pointing to. If the alias is deprecated, though, we need to + warn the user about it before we drop it. Note that while we + are warning about the alias, we may also warn about the command + itself and we will adjust the appropriate DEPRECATED_WARN_USER + flags */ + + if (found->flags & DEPRECATED_WARN_USER) + deprecated_cmd_warning (&line); + found = found->cmd_pointer; + } /* If we found a prefix command, keep looking. */ if (found->prefixlist) @@ -982,6 +1020,208 @@ lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes) return 0; } +/* We are here presumably because an alias or command in *TEXT is + deprecated and a warning message should be generated. This function + decodes *TEXT and potentially generates a warning message as outlined + below. + + Example for 'set endian big' which has a fictitious alias 'seb'. + + If alias wasn't used in *TEXT, and the command is deprecated: + "warning: 'set endian big' is deprecated." + + If alias was used, and only the alias is deprecated: + "warning: 'seb' an alias for the command 'set endian big' is deprecated." + + If alias was used and command is deprecated (regardless of whether the + alias itself is deprecated: + + "warning: 'set endian big' (seb) is deprecated." + + After the message has been sent, clear the appropriate flags in the + command and/or the alias so the user is no longer bothered. + +*/ +void +deprecated_cmd_warning (char **text) +{ + struct cmd_list_element *alias = NULL; + struct cmd_list_element *prefix_cmd = NULL; + struct cmd_list_element *cmd = NULL; + struct cmd_list_element *c; + char *type; + + if (!lookup_cmd_composition (*text, &alias, &prefix_cmd, &cmd)) + /* return if text doesn't evaluate to a command */ + return; + + if (!((alias ? (alias->flags & DEPRECATED_WARN_USER) : 0) + || (cmd->flags & DEPRECATED_WARN_USER) ) ) + /* return if nothing is deprecated */ + return; + + printf_filtered ("Warning:"); + + if (alias && !(cmd->flags & CMD_DEPRECATED)) + printf_filtered (" '%s', an alias for the", alias->name); + + printf_filtered (" command '"); + + if (prefix_cmd) + printf_filtered ("%s", prefix_cmd->prefixname); + + printf_filtered ("%s", cmd->name); + + if (alias && (cmd->flags & CMD_DEPRECATED)) + printf_filtered ("' (%s) is deprecated.\n", alias->name); + else + printf_filtered ("' is deprecated.\n"); + + + /* if it is only the alias that is deprecated, we want to indicate the + new alias, otherwise we'll indicate the new command */ + + if (alias && !(cmd->flags & CMD_DEPRECATED)) + { + if (alias->replacement) + printf_filtered ("Use '%s'.\n\n", alias->replacement); + else + printf_filtered ("No alternative known.\n\n"); + } + else + { + if (cmd->replacement) + printf_filtered ("Use '%s'.\n\n", cmd->replacement); + else + printf_filtered ("No alternative known.\n\n"); + } + + /* We've warned you, now we'll keep quiet */ + if (alias) + alias->flags &= ~DEPRECATED_WARN_USER; + + cmd->flags &= ~DEPRECATED_WARN_USER; +} + + + +/* Look up the contents of LINE as a command in the command list 'cmdlist'. + Return 1 on success, 0 on failure. + + If LINE refers to an alias, *alias will point to that alias. + + If LINE is a postfix command (i.e. one that is preceeded by a prefix + command) set *prefix_cmd. + + Set *cmd to point to the command LINE indicates. + + If any of *alias, *prefix_cmd, or *cmd cannot be determined or do not + exist, they are NULL when we return. + +*/ +int +lookup_cmd_composition (char *text, + struct cmd_list_element **alias, + struct cmd_list_element **prefix_cmd, + struct cmd_list_element **cmd) +{ + char *p, *command; + int len, tmp, nfound; + struct cmd_list_element *cur_list; + struct cmd_list_element *prev_cmd; + *alias = NULL; + *prefix_cmd = NULL; + *cmd = NULL; + + cur_list = cmdlist; + + while (1) + { + /* Go through as many command lists as we need to + to find the command TEXT refers to. */ + + prev_cmd = *cmd; + + while (*text == ' ' || *text == '\t') + (text)++; + + /* Treating underscores as part of command words is important + so that "set args_foo()" doesn't get interpreted as + "set args _foo()". */ + for (p = text; + *p && (isalnum (*p) || *p == '-' || *p == '_' || + (tui_version && + (*p == '+' || *p == '<' || *p == '>' || *p == '$')) || + (xdb_commands && (*p == '!' || *p == '/' || *p == '?'))); + p++) + ; + + /* If nothing but whitespace, return. */ + if (p == text) + return 0; + + len = p - text; + + /* text and p now bracket the first command word to lookup (and + it's length is len). We copy this into a local temporary */ + + command = (char *) alloca (len + 1); + for (tmp = 0; tmp < len; tmp++) + { + char x = text[tmp]; + command[tmp] = x; + } + command[len] = '\0'; + + /* Look it up. */ + *cmd = 0; + nfound = 0; + *cmd = find_cmd (command, len, cur_list, 1, &nfound); + + /* We didn't find the command in the entered case, so lower case it + and search again. + */ + if (!*cmd || nfound == 0) + { + for (tmp = 0; tmp < len; tmp++) + { + char x = command[tmp]; + command[tmp] = isupper (x) ? tolower (x) : x; + } + *cmd = find_cmd (command, len, cur_list, 1, &nfound); + } + + if (*cmd == (struct cmd_list_element *) -1) + { + return 0; /* ambiguous */ + } + + if (*cmd == NULL) + return 0; /* nothing found */ + else + { + if ((*cmd)->cmd_pointer) + { + /* cmd was actually an alias, we note that an alias was used + (by assigning *alais) and we set *cmd. + */ + *alias = *cmd; + *cmd = (*cmd)->cmd_pointer; + } + *prefix_cmd = prev_cmd; + } + if ((*cmd)->prefixlist) + cur_list = *(*cmd)->prefixlist; + else + return 1; + + text = p; + } +} + + + + #if 0 /* Look up the contents of *LINE as a command in the command list LIST. LIST is a chain of struct cmd_list_element's. diff --git a/gdb/command.h b/gdb/command.h index fcff845..200a487 100644 --- a/gdb/command.h +++ b/gdb/command.h @@ -82,6 +82,15 @@ var_types; /* This structure records one command'd definition. */ + +/* This flag is used by the code executing commands to warn the user + the first time a deprecated command is used, see the 'flags' field in + the following struct. +*/ +#define CMD_DEPRECATED 0x1 +#define DEPRECATED_WARN_USER 0x2 +#define MALLOCED_REPLACEMENT 0x4 + struct cmd_list_element { /* Points to next command in this list. */ @@ -115,6 +124,31 @@ struct cmd_list_element Entire string should also end with a period, not a newline. */ char *doc; + /* flags : a bitfield + + bit 0: (LSB) CMD_DEPRECATED, when 1 indicated that this command + is deprecated. It may be removed from gdb's command set in the + future. + + bit 1: DEPRECATED_WARN_USER, the user needs to be warned that + this is a deprecated command. The user should only be warned + the first time a command is used. + + bit 2: MALLOCED_REPLACEMENT, when functions are deprecated at + compile time (this is the way it should, in general, be done) + the memory comtaining the replacement string is statically + allocated. In some cases it makes sense to deprecate commands + at runtime (the testsuite is one example). In this case the + memory for replacement is malloc'ed. When a command is + undeprecated or re-deprecated at runtime we don't want to risk + calling free on statically allocated memory, so we check this + flag. + */ + int flags; + + /* if this command is deprecated, this is the replacement name */ + char *replacement; + /* Hook for another command to be executed before this command. */ struct cmd_list_element *hook; @@ -208,18 +242,30 @@ extern struct cmd_list_element * lookup_cmd_1 PARAMS ((char **, struct cmd_list_element *, struct cmd_list_element **, int)); +extern struct cmd_list_element * + deprecate_cmd (struct cmd_list_element *, char * ); + extern void -add_com PARAMS ((char *, enum command_class, void (*fun) (char *, int), + deprecated_cmd_warning (char **); + +extern int + lookup_cmd_composition (char *text, + struct cmd_list_element **alias, + struct cmd_list_element **prefix_cmd, + struct cmd_list_element **cmd); + +extern struct cmd_list_element * + add_com PARAMS ((char *, enum command_class, void (*fun) (char *, int), char *)); -extern void -add_com_alias PARAMS ((char *, char *, enum command_class, int)); +extern struct cmd_list_element * + add_com_alias PARAMS ((char *, char *, enum command_class, int)); -extern void -add_info PARAMS ((char *, void (*fun) (char *, int), char *)); +extern struct cmd_list_element * + add_info PARAMS ((char *, void (*fun) (char *, int), char *)); -extern void -add_info_alias PARAMS ((char *, char *, int)); +extern struct cmd_list_element * + add_info_alias PARAMS ((char *, char *, int)); extern char ** complete_on_cmdlist PARAMS ((struct cmd_list_element *, char *, char *)); diff --git a/gdb/maint.c b/gdb/maint.c index 725c6c5..e443522 100644 --- a/gdb/maint.c +++ b/gdb/maint.c @@ -358,6 +358,119 @@ maintenance_translate_address (arg, from_tty) return; } + +/* When a comamnd is deprecated the user will be warned the first time + the command is used. If possible, a replacement will be offered. */ + +static void +maintenance_deprecate (char *args, int from_tty) +{ + if (args == NULL || *args == '\0') + { + printf_unfiltered ("\"maintenance deprecate\" takes an argument, \n\ +the command you want to deprecate, and optionally the replacement command \n\ +enclosed in quotes.\n"); + } + + maintenance_do_deprecate (args, 1); + +} + + +static void +maintenance_undeprecate (char *args, int from_tty) +{ + if (args == NULL || *args == '\0') + { + printf_unfiltered ("\"maintenance undeprecate\" takes an argument, \n\ +the command you want to undeprecate.\n"); + } + + maintenance_do_deprecate (args, 0); + +} + +/* + You really shouldn't be using this. It is just for the testsuite. + Rather, you should use deprecate_cmd() when the command is created + in _initialize_blah(). + + This function deprecates a command and optionally assigns it a + replacement. +*/ + +static void maintenance_do_deprecate(char *text, int deprecate){ + + struct cmd_list_element *alias=NULL; + struct cmd_list_element *prefix_cmd=NULL; + struct cmd_list_element *cmd=NULL; + + char *start_ptr=NULL; + char *end_ptr=NULL; + int len; + char *replacement=NULL; + + + if (!lookup_cmd_composition (text, &alias, &prefix_cmd, &cmd)){ + printf_filtered ("Can't find command '%s' to deprecate.\n", text); + return; + } + + if (deprecate) + { + /* look for a replacement command */ + if (start_ptr = strchr (text, '\"')) + { + start_ptr++; + if(end_ptr = strrchr (start_ptr, '\"')) + { + len = end_ptr-start_ptr; + start_ptr[len]='\0'; + replacement = xstrdup (start_ptr); + } + } + } + + if (!start_ptr || !end_ptr) + replacement = NULL; + + + /* If they used an alias, we only want to deprecate the alias. + + Note the MALLOCED_REPLACEMENT test. If the command's replacement + string was allocated at compile time we don't want to free the + memory. + */ + if (alias) + { + + if (alias->flags & MALLOCED_REPLACEMENT) + free (alias->replacement); + + if (deprecate) + alias->flags |= (DEPRECATED_WARN_USER | CMD_DEPRECATED); + else + alias->flags &= ~(DEPRECATED_WARN_USER | CMD_DEPRECATED); + alias->replacement=replacement; + alias->flags |= MALLOCED_REPLACEMENT; + return; + } + else if (cmd) + { + if (cmd->flags & MALLOCED_REPLACEMENT) + free (cmd->replacement); + + if (deprecate) + cmd->flags |= (DEPRECATED_WARN_USER | CMD_DEPRECATED); + else + cmd->flags &= ~(DEPRECATED_WARN_USER | CMD_DEPRECATED); + cmd->replacement=replacement; + cmd->flags |= MALLOCED_REPLACEMENT; + return; + } +} + + void _initialize_maint_cmds () { @@ -456,6 +569,19 @@ If a SOURCE file is specified, dump only that file's partial symbols.", "Translate a section name and address to a symbol.", &maintenancelist); + add_cmd ("deprecate", class_maintenance, maintenance_deprecate, + "Deprecate a command. Note that this is just in here so the \n\ +testsuite can check the comamnd deprecator. You probably shouldn't use this,\n\ +rather you should use the C function deprecate_cmd(). If you decide you \n\ +want to use it: maintenance deprecate 'commandname' \"replacement\". The \n\ +replacement is optional.", &maintenancelist); + + add_cmd ("undeprecate", class_maintenance, maintenance_undeprecate, + "Undeprecate a command. Note that this is just in here so the \n\ +testsuite can check the comamnd deprecator. You probably shouldn't use this,\n\ +If you decide you want to use it: maintenance undeprecate 'commandname'", + &maintenancelist); + add_show_from_set ( add_set_cmd ("watchdog", class_maintenance, var_zinteger, (char *) &watchdog, "Set watchdog timer.\n\ @@ -1474,6 +1474,7 @@ execute_command (p, from_tty) register struct cmd_list_element *c; register enum language flang; static int warned = 0; + char *line; /* FIXME: These should really be in an appropriate header file */ extern void serial_log_command PARAMS ((const char *)); @@ -1494,7 +1495,8 @@ execute_command (p, from_tty) if (*p) { char *arg; - + line = p; + c = lookup_cmd (&p, cmdlist, "", 0, 1); /* If the target is running, we allow only a limited set of @@ -1517,11 +1519,14 @@ execute_command (p, from_tty) p--; *(p + 1) = '\0'; } - + /* If this command has been hooked, run the hook first. */ if (c->hook) execute_user_command (c->hook, (char *) 0); + if (c->flags & DEPRECATED_WARN_USER) + deprecated_cmd_warning (&line); + if (c->class == class_user) execute_user_command (c, arg); else if (c->type == set_cmd || c->type == show_cmd) @@ -2892,24 +2897,24 @@ free_command_lines (lptr) /* Add an element to the list of info subcommands. */ -void +struct cmd_list_element * add_info (name, fun, doc) char *name; void (*fun) PARAMS ((char *, int)); char *doc; { - add_cmd (name, no_class, fun, doc, &infolist); + return add_cmd (name, no_class, fun, doc, &infolist); } /* Add an alias to the list of info subcommands. */ -void +struct cmd_list_element * add_info_alias (name, oldname, abbrev_flag) char *name; char *oldname; int abbrev_flag; { - add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist); + return add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist); } /* The "info" command is defined as a prefix, with allow_unknown = 0. @@ -2965,26 +2970,26 @@ show_command (arg, from_tty) /* Add an element to the list of commands. */ -void +struct cmd_list_element * add_com (name, class, fun, doc) char *name; enum command_class class; void (*fun) PARAMS ((char *, int)); char *doc; { - add_cmd (name, class, fun, doc, &cmdlist); + return add_cmd (name, class, fun, doc, &cmdlist); } /* Add an alias or abbreviation command to the list of commands. */ -void +struct cmd_list_element * add_com_alias (name, oldname, class, abbrev_flag) char *name; char *oldname; enum command_class class; int abbrev_flag; { - add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist); + return add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist); } void |