📄 command.c
字号:
/* Handle lists of commands, their decoding and documentation, for GDB. Copyright 1986, 1989, 1990, 1991 Free Software Foundation, Inc.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#include "gdbcmd.h"#include "symtab.h"#include "value.h"#include <ctype.h>#include <string.h>/* Prototypes for local functions */static voidundef_cmd_error PARAMS ((char *, char *));static voidshow_user PARAMS ((char *, int));static voidshow_user_1 PARAMS ((struct cmd_list_element *, FILE *));static voidmake_command PARAMS ((char *, int));static voidshell_escape PARAMS ((char *, int));static intparse_binary_operation PARAMS ((char *));static voidprint_doc_line PARAMS ((FILE *, char *));/* Add element named NAME to command list *LIST. FUN should be the function to execute the command; it will get a character string as argument, with leading and trailing blanks already eliminated. DOC is a documentation string for the command. Its first line should be a complete sentence. It should start with ? for a command that is an abbreviation or with * for a command that most users don't need to know about. */struct cmd_list_element *add_cmd (name, class, fun, doc, list) char *name; enum command_class class; void (*fun) PARAMS ((char *, int)); char *doc; struct cmd_list_element **list;{ register struct cmd_list_element *c = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element)); delete_cmd (name, list); c->next = *list; c->name = name; c->class = class; c->function.cfunc = fun; c->doc = doc; c->prefixlist = 0; c->prefixname = (char *)NULL; c->allow_unknown = 0; c->hook = 0; c->hookee = 0; c->cmd_pointer = 0; c->abbrev_flag = 0; c->type = not_set_cmd; c->completer = make_symbol_completion_list; c->var = 0; c->var_type = var_boolean; c->user_commands = 0; *list = c; return c;}/* Same as above, except that the abbrev_flag is set. */#if 0 /* Currently unused */struct cmd_list_element *add_abbrev_cmd (name, class, fun, doc, list) char *name; enum command_class class; void (*fun) PARAMS ((char *, int)); char *doc; struct cmd_list_element **list;{ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list); c->abbrev_flag = 1; return c;}#endifstruct cmd_list_element *add_alias_cmd (name, oldname, class, abbrev_flag, list) char *name; char *oldname; enum command_class class; int abbrev_flag; struct cmd_list_element **list;{ /* Must do this since lookup_cmd tries to side-effect its first arg */ char *copied_name; register struct cmd_list_element *old; register struct cmd_list_element *c; copied_name = (char *) alloca (strlen (oldname) + 1); strcpy (copied_name, oldname); old = lookup_cmd (&copied_name, *list, "", 1, 1); if (old == 0) { delete_cmd (name, list); return 0; } c = add_cmd (name, class, old->function.cfunc, old->doc, list); c->prefixlist = old->prefixlist; c->prefixname = old->prefixname; c->allow_unknown = old->allow_unknown; c->abbrev_flag = abbrev_flag; c->cmd_pointer = old; return c;}/* Like add_cmd but adds an element for a command prefix: a name that should be followed by a subcommand to be looked up in another command list. PREFIXLIST should be the address of the variable containing that list. */struct cmd_list_element *add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname, allow_unknown, list) char *name; enum command_class class; void (*fun) PARAMS ((char *, int)); char *doc; struct cmd_list_element **prefixlist; char *prefixname; int allow_unknown; struct cmd_list_element **list;{ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list); c->prefixlist = prefixlist; c->prefixname = prefixname; c->allow_unknown = allow_unknown; return c;}/* Like add_prefix_cmd but sets the abbrev_flag on the new command. */ struct cmd_list_element *add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname, allow_unknown, list) char *name; enum command_class class; void (*fun) PARAMS ((char *, int)); char *doc; struct cmd_list_element **prefixlist; char *prefixname; int allow_unknown; struct cmd_list_element **list;{ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list); c->prefixlist = prefixlist; c->prefixname = prefixname; c->allow_unknown = allow_unknown; c->abbrev_flag = 1; return c;}/* ARGSUSED */voidnot_just_help_class_command (args, from_tty) char *args; int from_tty;{}/* Add element named NAME to command list LIST (the list for set or some sublist thereof). 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. */struct cmd_list_element *add_set_cmd (name, class, var_type, var, doc, list) char *name; enum command_class class; var_types var_type; char *var; char *doc; struct cmd_list_element **list;{ /* For set/show, we have to call do_setshow_command differently than an ordinary function (take commandlist as well as arg), so the function field isn't helpful. However, function == NULL means that it's a help class, so set the function to not_just_help_class_command. */ struct cmd_list_element *c = add_cmd (name, class, not_just_help_class_command, doc, list); c->type = set_cmd; c->var_type = var_type; c->var = var; return c;}/* Where SETCMD has already been added, add the corresponding show command to LIST and return a pointer to it. */struct cmd_list_element *add_show_from_set (setcmd, list) struct cmd_list_element *setcmd; struct cmd_list_element **list;{ struct cmd_list_element *showcmd = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element)); memcpy (showcmd, setcmd, sizeof (struct cmd_list_element)); delete_cmd (showcmd->name, list); showcmd->type = show_cmd; /* Replace "set " at start of docstring with "show ". */ if (setcmd->doc[0] == 'S' && setcmd->doc[1] == 'e' && setcmd->doc[2] == 't' && setcmd->doc[3] == ' ') showcmd->doc = concat ("Show ", setcmd->doc + 4, NULL); else fprintf (stderr, "GDB internal error: Bad docstring for set command\n"); showcmd->next = *list; *list = showcmd; return showcmd;}/* Remove the command named NAME from the command list. */voiddelete_cmd (name, list) char *name; struct cmd_list_element **list;{ register struct cmd_list_element *c; struct cmd_list_element *p; while (*list && !strcmp ((*list)->name, name)) { if ((*list)->hookee) (*list)->hookee->hook = 0; /* Hook slips out of its mouth */ p = (*list)->next; free ((PTR)*list); *list = p; } if (*list) for (c = *list; c->next;) { if (!strcmp (c->next->name, name)) { if (c->next->hookee) c->next->hookee->hook = 0; /* hooked cmd gets away. */ p = c->next->next; free ((PTR)c->next); c->next = p; } else c = c->next; }}/* This command really has to deal with two things: * 1) I want documentation on *this string* (usually called by * "help commandname"). * 2) I want documentation on *this list* (usually called by * giving a command that requires subcommands. Also called by saying * just "help".) * * I am going to split this into two seperate comamnds, help_cmd and * help_list. */voidhelp_cmd (command, stream) char *command; FILE *stream;{ struct cmd_list_element *c; extern struct cmd_list_element *cmdlist; if (!command) { help_list (cmdlist, "", all_classes, stream); return; } c = lookup_cmd (&command, cmdlist, "", 0, 0); if (c == 0) return; /* There are three cases here. If c->prefixlist is nonzero, we have a prefix command. Print its documentation, then list its subcommands. If c->function is nonzero, we really have a command. Print its documentation and return. If c->function is zero, we have a class name. Print its documentation (as if it were a command) and then set class to the number of this class so that the commands in the class will be listed. */ fputs_filtered (c->doc, stream); fputs_filtered ("\n", stream); if (c->prefixlist == 0 && c->function.cfunc != NULL) return; fprintf_filtered (stream, "\n"); /* If this is a prefix command, print it's subcommands */ if (c->prefixlist) help_list (*c->prefixlist, c->prefixname, all_commands, stream); /* If this is a class name, print all of the commands in the class */ if (c->function.cfunc == NULL) help_list (cmdlist, "", c->class, stream); if (c->hook) fprintf_filtered (stream, "\nThis command has a hook defined: %s\n", c->hook->name);}/* * Get a specific kind of help on a command list. * * LIST is the list. * CMDTYPE is the prefix to use in the title string. * CLASS is the class with which to list the nodes of this list (see * documentation for help_cmd_list below), As usual, ALL_COMMANDS for * everything, ALL_CLASSES for just classes, and non-negative for only things * in a specific class. * and STREAM is the output stream on which to print things. * If you call this routine with a class >= 0, it recurses. */voidhelp_list (list, cmdtype, class, stream) struct cmd_list_element *list; char *cmdtype; enum command_class class; FILE *stream;{ int len; char *cmdtype1, *cmdtype2; /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */ len = strlen (cmdtype); cmdtype1 = (char *) alloca (len + 1); cmdtype1[0] = 0; cmdtype2 = (char *) alloca (len + 4); cmdtype2[0] = 0; if (len) { cmdtype1[0] = ' '; strncpy (cmdtype1 + 1, cmdtype, len - 1); cmdtype1[len] = 0; strncpy (cmdtype2, cmdtype, len - 1); strcpy (cmdtype2 + len - 1, " sub"); } if (class == all_classes) fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2); else fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2); help_cmd_list (list, class, cmdtype, (int)class >= 0, stream); if (class == all_classes) fprintf_filtered (stream, "\n\Type \"help%s\" followed by a class name for a list of commands in that class.", cmdtype1); fprintf_filtered (stream, "\n\Type \"help%s\" followed by %scommand name for full documentation.\n\Command name abbreviations are allowed if unambiguous.\n", cmdtype1, cmdtype2);} /* Print only the first line of STR on STREAM. */static voidprint_doc_line (stream, str) FILE *stream; char *str;{ static char *line_buffer = 0; static int line_size; register char *p; if (!line_buffer) { line_size = 80; line_buffer = (char *) xmalloc (line_size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -