📄 cli-decode.c
字号:
if (*list) for (c = *list; c->next;) { if (STREQ (c->next->name, name)) { if (c->next->hookee_pre) c->next->hookee_pre->hook_pre = 0; /* hooked cmd gets away. */ if (c->next->hookee_post) c->next->hookee_post->hook_post = 0; /* remove post hook */ /* :( no fishing metaphore */ p = c->next->next; xfree (c->next); c->next = p; } else c = c->next; }}/* Shorthands to the commands above. *//* Add an element to the list of info subcommands. */struct cmd_list_element *add_info (char *name, void (*fun) (char *, int), char *doc){ return add_cmd (name, no_class, fun, doc, &infolist);}/* Add an alias to the list of info subcommands. */struct cmd_list_element *add_info_alias (char *name, char *oldname, int abbrev_flag){ return add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist);}/* Add an element to the list of commands. */struct cmd_list_element *add_com (char *name, enum command_class class, void (*fun) (char *, int), char *doc){ return add_cmd (name, class, fun, doc, &cmdlist);}/* Add an alias or abbreviation command to the list of commands. */struct cmd_list_element *add_com_alias (char *name, char *oldname, enum command_class class, int abbrev_flag){ return add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist);}/* Recursively walk the commandlist structures, and print out the documentation of commands that match our regex in either their name, or their documentation.*/void apropos_cmd (struct ui_file *stream, struct cmd_list_element *commandlist, struct re_pattern_buffer *regex, char *prefix){ register struct cmd_list_element *c; int returnvalue=1; /*Needed to avoid double printing*/ /* Walk through the commands */ for (c=commandlist;c;c=c->next) { if (c->name != NULL) { /* Try to match against the name*/ returnvalue=re_search(regex,c->name,strlen(c->name),0,strlen(c->name),NULL); if (returnvalue >= 0) { /* Stolen from help_cmd_list. We don't directly use * help_cmd_list because it doesn't let us print out * single commands */ fprintf_filtered (stream, "%s%s -- ", prefix, c->name); print_doc_line (stream, c->doc); fputs_filtered ("\n", stream); returnvalue=0; /*Set this so we don't print it again.*/ } } if (c->doc != NULL && returnvalue != 0) { /* Try to match against documentation */ if (re_search(regex,c->doc,strlen(c->doc),0,strlen(c->doc),NULL) >=0) { /* Stolen from help_cmd_list. We don't directly use * help_cmd_list because it doesn't let us print out * single commands */ fprintf_filtered (stream, "%s%s -- ", prefix, c->name); print_doc_line (stream, c->doc); fputs_filtered ("\n", stream); } } /* Check if this command has subcommands */ if (c->prefixlist != NULL) { /* Recursively call ourselves on the subcommand list, passing the right prefix in. */ apropos_cmd (stream,*c->prefixlist,regex,c->prefixname); } }}/* 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 (char *command, struct ui_file *stream){ struct cmd_list_element *c; extern struct cmd_list_element *cmdlist; if (!command) { help_list (cmdlist, "", all_classes, stream); return; } if (strcmp (command, "all") == 0) { help_all (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->func is non NULL, we really have a command. Print its documentation and return. If c->func is NULL, 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->func != 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->func == NULL) help_list (cmdlist, "", c->class, stream); if (c->hook_pre || c->hook_post) fprintf_filtered (stream, "\nThis command has a hook (or hooks) defined:\n"); if (c->hook_pre) fprintf_filtered (stream, "\tThis command is run after : %s (pre hook)\n", c->hook_pre->name); if (c->hook_post) fprintf_filtered (stream, "\tThis command is run before : %s (post hook)\n", c->hook_post->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 (struct cmd_list_element *list, char *cmdtype, enum command_class class, struct ui_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 ", cmdtype1); wrap_here (""); fprintf_filtered (stream, "that class."); } fprintf_filtered (stream, "\nType \"help%s\" followed by %scommand name ", cmdtype1, cmdtype2); wrap_here (""); fputs_filtered ("for ", stream); wrap_here (""); fputs_filtered ("full ", stream); wrap_here (""); fputs_filtered ("documentation.\n", stream); fputs_filtered ("Command name abbreviations are allowed if unambiguous.\n", stream);}static voidhelp_all (struct ui_file *stream){ struct cmd_list_element *c; extern struct cmd_list_element *cmdlist; for (c = cmdlist; c; c = c->next) { if (c->abbrev_flag) continue; /* If this is a prefix command, print it's subcommands */ if (c->prefixlist) help_cmd_list (*c->prefixlist, all_commands, c->prefixname, 0, stream); /* If this is a class name, print all of the commands in the class */ else if (c->func == NULL) help_cmd_list (cmdlist, c->class, "", 0, stream); }}/* Print only the first line of STR on STREAM. */voidprint_doc_line (struct ui_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); } p = str; while (*p && *p != '\n' && *p != '.' && *p != ',') p++; if (p - str > line_size - 1) { line_size = p - str + 1; xfree (line_buffer); line_buffer = (char *) xmalloc (line_size); } strncpy (line_buffer, str, p - str); line_buffer[p - str] = '\0'; if (islower (line_buffer[0])) line_buffer[0] = toupper (line_buffer[0]); ui_out_text (uiout, line_buffer);}/* * Implement a help command on command list LIST. * RECURSE should be non-zero if this should be done recursively on * all sublists of LIST. * PREFIX is the prefix to print before each command name. * STREAM is the stream upon which the output should be written. * CLASS should be: * A non-negative class number to list only commands in that * class. * ALL_COMMANDS to list all commands in list. * ALL_CLASSES to list all classes in list. * * Note that RECURSE will be active on *all* sublists, not just the * ones selected by the criteria above (ie. the selection mechanism * is at the low level, not the high-level). */voidhelp_cmd_list (struct cmd_list_element *list, enum command_class class, char *prefix, int recurse, struct ui_file *stream){ register struct cmd_list_element *c; for (c = list; c; c = c->next) { if (c->abbrev_flag == 0 && (class == all_commands || (class == all_classes && c->func == NULL) || (class == c->class && c->func != NULL))) { fprintf_filtered (stream, "%s%s -- ", prefix, c->name); print_doc_line (stream, c->doc); fputs_filtered ("\n", stream); } if (recurse && c->prefixlist != 0 && c->abbrev_flag == 0) help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream); }}/* Search the input clist for 'command'. Return the command if found (or NULL if not), and return the number of commands found in nfound */static struct cmd_list_element *find_cmd (char *command, int len, struct cmd_list_element *clist, int ignore_help_classes, int *nfound){ struct cmd_list_element *found, *c; found = (struct cmd_list_element *) NULL; *nfound = 0; for (c = clist; c; c = c->next) if (!strncmp (command, c->name, len) && (!ignore_help_classes || c->func)) { found = c; (*nfound)++; if (c->name[len] == '\0') { *nfound = 1; break; } } return found;}/* This routine takes a line of TEXT and a CLIST in which to start the lookup. When it returns it will have incremented the text pointer past the section of text it matched, set *RESULT_LIST to point to the list in which the last word was matched, and will return a pointer to the cmd list element which the text matches. It will return NULL if no match at all was possible. It will return -1 (cast appropriately, ick) if ambigous matches are possible; in this case *RESULT_LIST will be set to point to the list in which there are ambiguous choices (and *TEXT will be set to the ambiguous text string). If the located command was an abbreviation, this routine returns the base command of the abbreviation. It does no error reporting whatsoever; control will always return to the superior routine. In the case of an ambiguous return (-1), *RESULT_LIST will be set to point at the prefix_command (ie. the best match) *or* (special case) will be NULL if no prefix command was ever found. For example, in the case of "info a", "info" matches without ambiguity, but "a" could be "args" or "address", so *RESULT_LIST is set to the cmd_list_element for "info". So in this case RESULT_LIST should not be interpeted as a pointer to the beginning of a list; it simply points to a specific command. In the case of an ambiguous return *TEXT is advanced past the last non-ambiguous prefix (e.g. "info t" can be "info types" or "info target"; upon return *TEXT has been advanced past "info "). If RESULT_LIST is NULL, don't set *RESULT_LIST (but don't otherwise affect the operation). This routine does *not* modify the text pointed to by TEXT. If IGNORE_HELP_CLASSES is nonzero, ignore any command list elements which are actually help classes rather than commands (i.e. the function field of the struct cmd_list_element is NULL). */struct cmd_list_element *lookup_cmd_1 (char **text, struct cmd_list_element *clist, struct cmd_list_element **result_list, int ignore_help_classes){ char *p, *command; int len, tmp, nfound; struct cmd_list_element *found, *c; char *line = *text; 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()". */ /* NOTE: cagney/2003-02-13 The `tui_active' was previously `tui_version'. */ for (p = *text; *p && (isalnum (*p) || *p == '-' || *p == '_' ||#if defined(TUI) (tui_active && (*p == '+' || *p == '<' || *p == '>' || *p == '$')) ||#endif (xdb_commands && (*p == '!' || *p == '/' || *p == '?'))); p++) ; /* If nothing but whitespace, return 0. */ 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. */ found = 0; nfound = 0; found = find_cmd (command, len, clist, ignore_help_classes, &nfound); /* ** We didn't find the command in the entered case, so lower case it ** and search again. */ if (!found || nfound == 0) { for (tmp = 0; tmp < len; tmp++) { char x = command[tmp]; command[tmp] = isupper (x) ? tolower (x) : x; } found = find_cmd (command, len, clist, ignore_help_classes, &nfound); } /* If nothing matches, we have a simple failure. */ if (nfound == 0) return 0; if (nfound > 1) { if (result_list != NULL) /* Will be modified in calling routine if we know what the prefix command is. */ *result_list = 0; return (struct cmd_list_element *) -1; /* Ambiguous. */ } /* We've matched something on this list. Move text pointer forward. */ *text = p; if (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) { c = lookup_cmd_1 (text, *found->prefixlist, result_list, ignore_help_classes); if (!c) { /* Didn't find anything; this is as far as we got. */ if (result_list != NULL) *result_list = clist; return found; } else if (c == (struct cmd_list_element *) -1) { /* We've gotten this far properly, but the next step is ambiguous. We need to set the result list to the best we've found (if an inferior hasn't already set it). */ if (result_list != NULL) if (!*result_list)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -