📄 command.c
字号:
} p = str; while (*p && *p != '\n' && *p != '.' && *p != ',') p++; if (p - str > line_size - 1) { line_size = p - str + 1; free ((PTR)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]); fputs_filtered (line_buffer, stream);}/* * 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 (list, class, prefix, recurse, stream) struct cmd_list_element *list; enum command_class class; char *prefix; int recurse; 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->function.cfunc == NULL) || (class == c->class && c->function.cfunc != 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); }}/* 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. 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 (text, clist, result_list, ignore_help_classes) char **text; struct cmd_list_element *clist, **result_list; int ignore_help_classes;{ char *p, *command; int len, tmp, nfound; struct cmd_list_element *found, *c; 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 == '_'); 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, converting to lower case as we go. */ command = (char *) alloca (len + 1); for (tmp = 0; tmp < len; tmp++) { char x = (*text)[tmp]; command[tmp] = isupper(x) ? tolower(x) : x; } command[len] = '\0'; /* Look it up. */ found = 0; nfound = 0; for (c = clist; c; c = c->next) if (!strncmp (command, c->name, len) && (!ignore_help_classes || c->function.cfunc)) { found = c; nfound++; if (c->name[len] == '\0') { nfound = 1; break; } } /* 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 this was an abbreviation, use the base command instead. */ if (found->cmd_pointer) 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 properley, 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) /* This used to say *result_list = *found->prefixlist If that was correct, need to modify the documentation at the top of this function to clarify what is supposed to be going on. */ *result_list = found; return c; } else { /* We matched! */ return c; } } else { if (result_list != NULL) *result_list = clist; return found; }}/* All this hair to move the space to the front of cmdtype */static voidundef_cmd_error (cmdtype, q) char *cmdtype, *q;{ error ("Undefined %scommand: \"%s\". Try \"help%s%.*s\".", cmdtype, q, *cmdtype? " ": "", strlen(cmdtype)-1, cmdtype);}/* Look up the contents of *LINE as a command in the command list LIST. LIST is a chain of struct cmd_list_element's. If it is found, return the struct cmd_list_element for that command and update *LINE to point after the command name, at the first argument. If not found, call error if ALLOW_UNKNOWN is zero otherwise (or if error returns) return zero. Call error if specified command is ambiguous, unless ALLOW_UNKNOWN is negative. CMDTYPE precedes the word "command" in the error message. If INGNORE_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 0). */struct cmd_list_element *lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes) char **line; struct cmd_list_element *list; char *cmdtype; int allow_unknown; int ignore_help_classes;{ struct cmd_list_element *last_list = 0; struct cmd_list_element *c = lookup_cmd_1 (line, list, &last_list, ignore_help_classes); char *ptr = (*line) + strlen (*line) - 1; /* Clear off trailing whitespace. */ while (ptr >= *line && (*ptr == ' ' || *ptr == '\t')) ptr--; *(ptr + 1) = '\0'; if (!c) { if (!allow_unknown) { if (!*line) error ("Lack of needed %scommand", cmdtype); else { char *p = *line, *q; while (isalnum(*p) || *p == '-') p++; q = (char *) alloca (p - *line + 1); strncpy (q, *line, p - *line); q[p-*line] = '\0'; undef_cmd_error (cmdtype, q); } } else return 0; } else if (c == (struct cmd_list_element *) -1) { /* Ambigous. Local values should be off prefixlist or called values. */ int local_allow_unknown = (last_list ? last_list->allow_unknown : allow_unknown); char *local_cmdtype = last_list ? last_list->prefixname : cmdtype; struct cmd_list_element *local_list = (last_list ? *(last_list->prefixlist) : list); if (local_allow_unknown < 0) { if (last_list) return last_list; /* Found something. */ else return 0; /* Found nothing. */ } else { /* Report as error. */ int amb_len; char ambbuf[100]; for (amb_len = 0; ((*line)[amb_len] && (*line)[amb_len] != ' ' && (*line)[amb_len] != '\t'); amb_len++) ; ambbuf[0] = 0; for (c = local_list; c; c = c->next) if (!strncmp (*line, c->name, amb_len)) { if (strlen (ambbuf) + strlen (c->name) + 6 < (int)sizeof ambbuf) { if (strlen (ambbuf)) strcat (ambbuf, ", "); strcat (ambbuf, c->name); } else { strcat (ambbuf, ".."); break; } } error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype, *line, ambbuf); return 0; /* lint */ } } else { /* We've got something. It may still not be what the caller wants (if this command *needs* a subcommand). */ while (**line == ' ' || **line == '\t') (*line)++; if (c->prefixlist && **line && !c->allow_unknown) undef_cmd_error (c->prefixname, *line); /* Seems to be what he wants. Return it. */ return c; } return 0;} #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. If it is found, return the struct cmd_list_element for that command and update *LINE to point after the command name, at the first argument. If not found, call error if ALLOW_UNKNOWN is zero otherwise (or if error returns) return zero. Call error if specified command is ambiguous, unless ALLOW_UNKNOWN is negative. CMDTYPE precedes the word "command" in the error message. */struct cmd_list_element *lookup_cmd (line, list, cmdtype, allow_unknown) char **line; struct cmd_list_element *list; char *cmdtype; int allow_unknown;{ register char *p; register struct cmd_list_element *c, *found; int nfound; char ambbuf[100]; char *processed_cmd; int i, cmd_len; /* Skip leading whitespace. */ while (**line == ' ' || **line == '\t') (*line)++; /* Clear out trailing whitespace. */ p = *line + strlen (*line); while (p != *line && (p[-1] == ' ' || p[-1] == '\t')) p--; *p = 0; /* Find end of command name. */ p = *line; while (*p == '-' || isalnum(*p)) p++; /* Look up the command name. If exact match, keep that. Otherwise, take command abbreviated, if unique. Note that (in my opinion) a null string does *not* indicate ambiguity; simply the end of the argument. */ if (p == *line) { if (!allow_unknown) error ("Lack of needed %scommand", cmdtype); return 0; } /* Copy over to a local buffer, converting to lowercase on the way. This is in case the command being parsed is a subcommand which doesn't match anything, and that's ok. We want the original untouched for the routine of the original command. */ processed_cmd = (char *) alloca (p - *line + 1); for (cmd_len = 0; cmd_len < p - *line; cmd_len++) { char x = (*line)[cmd_len]; if (isupper(x)) processed_cmd[cmd_len] = tolower(x); else processed_cmd[cmd_len] = x; } processed_cmd[cmd_len] = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -