198944Sobrien/* Handle lists of commands, their decoding and documentation, for GDB. 298944Sobrien 398944Sobrien Copyright 1986, 1989, 1990, 1991, 1998, 2000, 2001, 2002 Free 498944Sobrien Software Foundation, Inc. 598944Sobrien 698944Sobrien This program is free software; you can redistribute it and/or modify 798944Sobrien it under the terms of the GNU General Public License as published by 898944Sobrien the Free Software Foundation; either version 2 of the License, or 998944Sobrien (at your option) any later version. 1098944Sobrien 1198944Sobrien This program is distributed in the hope that it will be useful, 1298944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1398944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1498944Sobrien GNU General Public License for more details. 1598944Sobrien 1698944Sobrien You should have received a copy of the GNU General Public License 1798944Sobrien along with this program; if not, write to the Free Software 1898944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 1998944Sobrien Boston, MA 02111-1307, USA. */ 2098944Sobrien 2198944Sobrien#include "defs.h" 2298944Sobrien#include "symtab.h" 2398944Sobrien#include <ctype.h> 2498944Sobrien#include "gdb_regex.h" 25130803Smarcel#include "gdb_string.h" 2698944Sobrien 2798944Sobrien#include "ui-out.h" 2898944Sobrien 2998944Sobrien#include "cli/cli-cmds.h" 3098944Sobrien#include "cli/cli-decode.h" 3198944Sobrien 32130803Smarcel#ifdef TUI 33130803Smarcel#include "tui/tui.h" /* For tui_active et.al. */ 34130803Smarcel#endif 35130803Smarcel 36130803Smarcel#include "gdb_assert.h" 37130803Smarcel 3898944Sobrien/* Prototypes for local functions */ 3998944Sobrien 4098944Sobrienstatic void undef_cmd_error (char *, char *); 4198944Sobrien 4298944Sobrienstatic struct cmd_list_element *find_cmd (char *command, 4398944Sobrien int len, 4498944Sobrien struct cmd_list_element *clist, 4598944Sobrien int ignore_help_classes, 4698944Sobrien int *nfound); 4798944Sobrien 4898944Sobrienstatic void help_all (struct ui_file *stream); 4998944Sobrien 5098944Sobrien/* Set the callback function for the specified command. For each both 5198944Sobrien the commands callback and func() are set. The latter set to a 5298944Sobrien bounce function (unless cfunc / sfunc is NULL that is). */ 5398944Sobrien 5498944Sobrienstatic void 5598944Sobriendo_cfunc (struct cmd_list_element *c, char *args, int from_tty) 5698944Sobrien{ 5798944Sobrien c->function.cfunc (args, from_tty); /* Ok. */ 5898944Sobrien} 5998944Sobrien 6098944Sobrienvoid 61130803Smarcelset_cmd_cfunc (struct cmd_list_element *cmd, cmd_cfunc_ftype *cfunc) 6298944Sobrien{ 6398944Sobrien if (cfunc == NULL) 6498944Sobrien cmd->func = NULL; 6598944Sobrien else 6698944Sobrien cmd->func = do_cfunc; 6798944Sobrien cmd->function.cfunc = cfunc; /* Ok. */ 6898944Sobrien} 6998944Sobrien 7098944Sobrienstatic void 7198944Sobriendo_sfunc (struct cmd_list_element *c, char *args, int from_tty) 7298944Sobrien{ 7398944Sobrien c->function.sfunc (args, from_tty, c); /* Ok. */ 7498944Sobrien} 7598944Sobrien 7698944Sobrienvoid 77130803Smarcelset_cmd_sfunc (struct cmd_list_element *cmd, cmd_sfunc_ftype *sfunc) 7898944Sobrien{ 7998944Sobrien if (sfunc == NULL) 8098944Sobrien cmd->func = NULL; 8198944Sobrien else 8298944Sobrien cmd->func = do_sfunc; 8398944Sobrien cmd->function.sfunc = sfunc; /* Ok. */ 8498944Sobrien} 8598944Sobrien 8698944Sobrienint 8798944Sobriencmd_cfunc_eq (struct cmd_list_element *cmd, 8898944Sobrien void (*cfunc) (char *args, int from_tty)) 8998944Sobrien{ 9098944Sobrien return cmd->func == do_cfunc && cmd->function.cfunc == cfunc; 9198944Sobrien} 9298944Sobrien 93130803Smarcelvoid 94130803Smarcelset_cmd_context (struct cmd_list_element *cmd, void *context) 95130803Smarcel{ 96130803Smarcel cmd->context = context; 97130803Smarcel} 9898944Sobrien 99130803Smarcelvoid * 100130803Smarcelget_cmd_context (struct cmd_list_element *cmd) 101130803Smarcel{ 102130803Smarcel return cmd->context; 103130803Smarcel} 104130803Smarcel 105130803Smarcelenum cmd_types 106130803Smarcelcmd_type (struct cmd_list_element *cmd) 107130803Smarcel{ 108130803Smarcel return cmd->type; 109130803Smarcel} 110130803Smarcel 111130803Smarcelvoid 112130803Smarcelset_cmd_completer (struct cmd_list_element *cmd, 113130803Smarcel char **(*completer) (char *text, char *word)) 114130803Smarcel{ 115130803Smarcel cmd->completer = completer; /* Ok. */ 116130803Smarcel} 117130803Smarcel 118130803Smarcel 11998944Sobrien/* Add element named NAME. 12098944Sobrien CLASS is the top level category into which commands are broken down 12198944Sobrien for "help" purposes. 12298944Sobrien FUN should be the function to execute the command; 12398944Sobrien it will get a character string as argument, with leading 12498944Sobrien and trailing blanks already eliminated. 12598944Sobrien 12698944Sobrien DOC is a documentation string for the command. 12798944Sobrien Its first line should be a complete sentence. 12898944Sobrien It should start with ? for a command that is an abbreviation 12998944Sobrien or with * for a command that most users don't need to know about. 13098944Sobrien 13198944Sobrien Add this command to command list *LIST. 13298944Sobrien 13398944Sobrien Returns a pointer to the added command (not necessarily the head 13498944Sobrien of *LIST). */ 13598944Sobrien 13698944Sobrienstruct cmd_list_element * 13798944Sobrienadd_cmd (char *name, enum command_class class, void (*fun) (char *, int), 13898944Sobrien char *doc, struct cmd_list_element **list) 13998944Sobrien{ 140130803Smarcel struct cmd_list_element *c 14198944Sobrien = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element)); 14298944Sobrien struct cmd_list_element *p; 14398944Sobrien 14498944Sobrien delete_cmd (name, list); 14598944Sobrien 14698944Sobrien if (*list == NULL || strcmp ((*list)->name, name) >= 0) 14798944Sobrien { 14898944Sobrien c->next = *list; 14998944Sobrien *list = c; 15098944Sobrien } 15198944Sobrien else 15298944Sobrien { 15398944Sobrien p = *list; 15498944Sobrien while (p->next && strcmp (p->next->name, name) <= 0) 15598944Sobrien { 15698944Sobrien p = p->next; 15798944Sobrien } 15898944Sobrien c->next = p->next; 15998944Sobrien p->next = c; 16098944Sobrien } 16198944Sobrien 16298944Sobrien c->name = name; 16398944Sobrien c->class = class; 16498944Sobrien set_cmd_cfunc (c, fun); 165130803Smarcel set_cmd_context (c, NULL); 16698944Sobrien c->doc = doc; 16798944Sobrien c->flags = 0; 16898944Sobrien c->replacement = NULL; 16998944Sobrien c->pre_show_hook = NULL; 17098944Sobrien c->hook_pre = NULL; 17198944Sobrien c->hook_post = NULL; 17298944Sobrien c->hook_in = 0; 17398944Sobrien c->prefixlist = NULL; 17498944Sobrien c->prefixname = NULL; 17598944Sobrien c->allow_unknown = 0; 17698944Sobrien c->abbrev_flag = 0; 177130803Smarcel set_cmd_completer (c, make_symbol_completion_list); 17898944Sobrien c->type = not_set_cmd; 17998944Sobrien c->var = NULL; 18098944Sobrien c->var_type = var_boolean; 18198944Sobrien c->enums = NULL; 18298944Sobrien c->user_commands = NULL; 18398944Sobrien c->hookee_pre = NULL; 18498944Sobrien c->hookee_post = NULL; 18598944Sobrien c->cmd_pointer = NULL; 18698944Sobrien 18798944Sobrien return c; 18898944Sobrien} 18998944Sobrien 19098944Sobrien/* Deprecates a command CMD. 19198944Sobrien REPLACEMENT is the name of the command which should be used in place 19298944Sobrien of this command, or NULL if no such command exists. 19398944Sobrien 19498944Sobrien This function does not check to see if command REPLACEMENT exists 19598944Sobrien since gdb may not have gotten around to adding REPLACEMENT when this 19698944Sobrien function is called. 19798944Sobrien 19898944Sobrien Returns a pointer to the deprecated command. */ 19998944Sobrien 20098944Sobrienstruct cmd_list_element * 20198944Sobriendeprecate_cmd (struct cmd_list_element *cmd, char *replacement) 20298944Sobrien{ 20398944Sobrien cmd->flags |= (CMD_DEPRECATED | DEPRECATED_WARN_USER); 20498944Sobrien 20598944Sobrien if (replacement != NULL) 20698944Sobrien cmd->replacement = replacement; 20798944Sobrien else 20898944Sobrien cmd->replacement = NULL; 20998944Sobrien 21098944Sobrien return cmd; 21198944Sobrien} 21298944Sobrien 21398944Sobrienstruct cmd_list_element * 21498944Sobrienadd_alias_cmd (char *name, char *oldname, enum command_class class, 21598944Sobrien int abbrev_flag, struct cmd_list_element **list) 21698944Sobrien{ 21798944Sobrien /* Must do this since lookup_cmd tries to side-effect its first arg */ 21898944Sobrien char *copied_name; 219130803Smarcel struct cmd_list_element *old; 220130803Smarcel struct cmd_list_element *c; 22198944Sobrien copied_name = (char *) alloca (strlen (oldname) + 1); 22298944Sobrien strcpy (copied_name, oldname); 22398944Sobrien old = lookup_cmd (&copied_name, *list, "", 1, 1); 22498944Sobrien 22598944Sobrien if (old == 0) 22698944Sobrien { 22798944Sobrien delete_cmd (name, list); 22898944Sobrien return 0; 22998944Sobrien } 23098944Sobrien 23198944Sobrien c = add_cmd (name, class, NULL, old->doc, list); 23298944Sobrien /* NOTE: Both FUNC and all the FUNCTIONs need to be copied. */ 23398944Sobrien c->func = old->func; 23498944Sobrien c->function = old->function; 23598944Sobrien c->prefixlist = old->prefixlist; 23698944Sobrien c->prefixname = old->prefixname; 23798944Sobrien c->allow_unknown = old->allow_unknown; 23898944Sobrien c->abbrev_flag = abbrev_flag; 23998944Sobrien c->cmd_pointer = old; 24098944Sobrien return c; 24198944Sobrien} 24298944Sobrien 24398944Sobrien/* Like add_cmd but adds an element for a command prefix: 24498944Sobrien a name that should be followed by a subcommand to be looked up 24598944Sobrien in another command list. PREFIXLIST should be the address 24698944Sobrien of the variable containing that list. */ 24798944Sobrien 24898944Sobrienstruct cmd_list_element * 24998944Sobrienadd_prefix_cmd (char *name, enum command_class class, void (*fun) (char *, int), 25098944Sobrien char *doc, struct cmd_list_element **prefixlist, 25198944Sobrien char *prefixname, int allow_unknown, 25298944Sobrien struct cmd_list_element **list) 25398944Sobrien{ 254130803Smarcel struct cmd_list_element *c = add_cmd (name, class, fun, doc, list); 25598944Sobrien c->prefixlist = prefixlist; 25698944Sobrien c->prefixname = prefixname; 25798944Sobrien c->allow_unknown = allow_unknown; 25898944Sobrien return c; 25998944Sobrien} 26098944Sobrien 26198944Sobrien/* Like add_prefix_cmd but sets the abbrev_flag on the new command. */ 26298944Sobrien 26398944Sobrienstruct cmd_list_element * 26498944Sobrienadd_abbrev_prefix_cmd (char *name, enum command_class class, 26598944Sobrien void (*fun) (char *, int), char *doc, 26698944Sobrien struct cmd_list_element **prefixlist, char *prefixname, 26798944Sobrien int allow_unknown, struct cmd_list_element **list) 26898944Sobrien{ 269130803Smarcel struct cmd_list_element *c = add_cmd (name, class, fun, doc, list); 27098944Sobrien c->prefixlist = prefixlist; 27198944Sobrien c->prefixname = prefixname; 27298944Sobrien c->allow_unknown = allow_unknown; 27398944Sobrien c->abbrev_flag = 1; 27498944Sobrien return c; 27598944Sobrien} 27698944Sobrien 27798944Sobrien/* This is an empty "cfunc". */ 27898944Sobrienvoid 27998944Sobriennot_just_help_class_command (char *args, int from_tty) 28098944Sobrien{ 28198944Sobrien} 28298944Sobrien 28398944Sobrien/* This is an empty "sfunc". */ 28498944Sobrienstatic void empty_sfunc (char *, int, struct cmd_list_element *); 28598944Sobrien 28698944Sobrienstatic void 28798944Sobrienempty_sfunc (char *args, int from_tty, struct cmd_list_element *c) 28898944Sobrien{ 28998944Sobrien} 29098944Sobrien 291130803Smarcel/* Add element named NAME to command list LIST (the list for set/show 29298944Sobrien or some sublist thereof). 293130803Smarcel TYPE is set_cmd or show_cmd. 29498944Sobrien CLASS is as in add_cmd. 29598944Sobrien VAR_TYPE is the kind of thing we are setting. 29698944Sobrien VAR is address of the variable being controlled by this command. 29798944Sobrien DOC is the documentation string. */ 29898944Sobrien 299130803Smarcelstatic struct cmd_list_element * 300130803Smarceladd_set_or_show_cmd (char *name, 301130803Smarcel enum cmd_types type, 302130803Smarcel enum command_class class, 303130803Smarcel var_types var_type, 304130803Smarcel void *var, 305130803Smarcel char *doc, 306130803Smarcel struct cmd_list_element **list) 30798944Sobrien{ 30898944Sobrien struct cmd_list_element *c = add_cmd (name, class, NULL, doc, list); 309130803Smarcel gdb_assert (type == set_cmd || type == show_cmd); 310130803Smarcel c->type = type; 31198944Sobrien c->var_type = var_type; 31298944Sobrien c->var = var; 31398944Sobrien /* This needs to be something besides NULL so that this isn't 31498944Sobrien treated as a help class. */ 31598944Sobrien set_cmd_sfunc (c, empty_sfunc); 31698944Sobrien return c; 31798944Sobrien} 31898944Sobrien 319130803Smarcel/* Add element named NAME to both the command SET_LIST and SHOW_LIST. 320130803Smarcel CLASS is as in add_cmd. VAR_TYPE is the kind of thing we are 321130803Smarcel setting. VAR is address of the variable being controlled by this 322130803Smarcel command. SET_FUNC and SHOW_FUNC are the callback functions (if 323130803Smarcel non-NULL). SET_DOC and SHOW_DOC are the documentation strings. 324130803Smarcel SET_RESULT and SHOW_RESULT, if not NULL, are set to the resulting 325130803Smarcel command structures. */ 326130803Smarcel 327130803Smarcelvoid 328130803Smarceladd_setshow_cmd_full (char *name, 329130803Smarcel enum command_class class, 330130803Smarcel var_types var_type, void *var, 331130803Smarcel char *set_doc, char *show_doc, 332130803Smarcel cmd_sfunc_ftype *set_func, cmd_sfunc_ftype *show_func, 333130803Smarcel struct cmd_list_element **set_list, 334130803Smarcel struct cmd_list_element **show_list, 335130803Smarcel struct cmd_list_element **set_result, 336130803Smarcel struct cmd_list_element **show_result) 337130803Smarcel{ 338130803Smarcel struct cmd_list_element *set; 339130803Smarcel struct cmd_list_element *show; 340130803Smarcel set = add_set_or_show_cmd (name, set_cmd, class, var_type, var, 341130803Smarcel set_doc, set_list); 342130803Smarcel if (set_func != NULL) 343130803Smarcel set_cmd_sfunc (set, set_func); 344130803Smarcel show = add_set_or_show_cmd (name, show_cmd, class, var_type, var, 345130803Smarcel show_doc, show_list); 346130803Smarcel if (show_func != NULL) 347130803Smarcel set_cmd_sfunc (show, show_func); 348130803Smarcel 349130803Smarcel if (set_result != NULL) 350130803Smarcel *set_result = set; 351130803Smarcel if (show_result != NULL) 352130803Smarcel *show_result = show; 353130803Smarcel} 354130803Smarcel 355130803Smarcel/* Add element named NAME to both the command SET_LIST and SHOW_LIST. 356130803Smarcel CLASS is as in add_cmd. VAR_TYPE is the kind of thing we are 357130803Smarcel setting. VAR is address of the variable being controlled by this 358130803Smarcel command. SET_FUNC and SHOW_FUNC are the callback functions (if 359130803Smarcel non-NULL). SET_DOC and SHOW_DOC are the documentation strings. */ 360130803Smarcel 361130803Smarcelvoid 362130803Smarceladd_setshow_cmd (char *name, 363130803Smarcel enum command_class class, 364130803Smarcel var_types var_type, void *var, 365130803Smarcel char *set_doc, char *show_doc, 366130803Smarcel cmd_sfunc_ftype *set_func, cmd_sfunc_ftype *show_func, 367130803Smarcel struct cmd_list_element **set_list, 368130803Smarcel struct cmd_list_element **show_list) 369130803Smarcel{ 370130803Smarcel add_setshow_cmd_full (name, class, var_type, var, set_doc, show_doc, 371130803Smarcel set_func, show_func, set_list, show_list, 372130803Smarcel NULL, NULL); 373130803Smarcel} 374130803Smarcel 375130803Smarcelstruct cmd_list_element * 376130803Smarceladd_set_cmd (char *name, 377130803Smarcel enum command_class class, 378130803Smarcel var_types var_type, 379130803Smarcel void *var, 380130803Smarcel char *doc, 381130803Smarcel struct cmd_list_element **list) 382130803Smarcel{ 383130803Smarcel return add_set_or_show_cmd (name, set_cmd, class, var_type, var, doc, list); 384130803Smarcel} 385130803Smarcel 38698944Sobrien/* Add element named NAME to command list LIST (the list for set 38798944Sobrien or some sublist thereof). 38898944Sobrien CLASS is as in add_cmd. 38998944Sobrien ENUMLIST is a list of strings which may follow NAME. 39098944Sobrien VAR is address of the variable which will contain the matching string 39198944Sobrien (from ENUMLIST). 39298944Sobrien DOC is the documentation string. */ 39398944Sobrien 39498944Sobrienstruct cmd_list_element * 39598944Sobrienadd_set_enum_cmd (char *name, 39698944Sobrien enum command_class class, 39798944Sobrien const char *enumlist[], 39898944Sobrien const char **var, 39998944Sobrien char *doc, 40098944Sobrien struct cmd_list_element **list) 40198944Sobrien{ 40298944Sobrien struct cmd_list_element *c 40398944Sobrien = add_set_cmd (name, class, var_enum, var, doc, list); 40498944Sobrien c->enums = enumlist; 40598944Sobrien 40698944Sobrien return c; 40798944Sobrien} 40898944Sobrien 409130803Smarcel/* Add an auto-boolean command named NAME to both the set and show 410130803Smarcel command list lists. CLASS is as in add_cmd. VAR is address of the 411130803Smarcel variable which will contain the value. DOC is the documentation 412130803Smarcel string. FUNC is the corresponding callback. */ 413130803Smarcelvoid 414130803Smarceladd_setshow_auto_boolean_cmd (char *name, 415130803Smarcel enum command_class class, 416130803Smarcel enum auto_boolean *var, 417130803Smarcel char *set_doc, char *show_doc, 418130803Smarcel cmd_sfunc_ftype *set_func, 419130803Smarcel cmd_sfunc_ftype *show_func, 420130803Smarcel struct cmd_list_element **set_list, 421130803Smarcel struct cmd_list_element **show_list) 42298944Sobrien{ 42398944Sobrien static const char *auto_boolean_enums[] = { "on", "off", "auto", NULL }; 42498944Sobrien struct cmd_list_element *c; 425130803Smarcel add_setshow_cmd_full (name, class, var_auto_boolean, var, 426130803Smarcel set_doc, show_doc, set_func, show_func, 427130803Smarcel set_list, show_list, 428130803Smarcel &c, NULL); 42998944Sobrien c->enums = auto_boolean_enums; 43098944Sobrien} 43198944Sobrien 432130803Smarcel/* Add element named NAME to both the set and show command LISTs (the 433130803Smarcel list for set/show or some sublist thereof). CLASS is as in 434130803Smarcel add_cmd. VAR is address of the variable which will contain the 435130803Smarcel value. SET_DOC and SHOW_DOR are the documentation strings. */ 436130803Smarcelvoid 437130803Smarceladd_setshow_boolean_cmd (char *name, 438130803Smarcel enum command_class class, 439130803Smarcel int *var, char *set_doc, char *show_doc, 440130803Smarcel cmd_sfunc_ftype *set_func, 441130803Smarcel cmd_sfunc_ftype *show_func, 442130803Smarcel struct cmd_list_element **set_list, 443130803Smarcel struct cmd_list_element **show_list) 44498944Sobrien{ 44598944Sobrien static const char *boolean_enums[] = { "on", "off", NULL }; 44698944Sobrien struct cmd_list_element *c; 447130803Smarcel add_setshow_cmd_full (name, class, var_boolean, var, 448130803Smarcel set_doc, show_doc, 449130803Smarcel set_func, show_func, 450130803Smarcel set_list, show_list, 451130803Smarcel &c, NULL); 45298944Sobrien c->enums = boolean_enums; 45398944Sobrien} 45498944Sobrien 455130803Smarcel/* Add element named NAME to both the set and show command LISTs (the 456130803Smarcel list for set/show or some sublist thereof). CLASS is as in 457130803Smarcel add_cmd. VAR is address of the variable which will contain the 458130803Smarcel value. SET_DOC and SHOW_DOR are the documentation strings. */ 459130803Smarcelvoid 460130803Smarceladd_setshow_uinteger_cmd (char *name, 461130803Smarcel enum command_class class, 462130803Smarcel unsigned int *var, char *set_doc, char *show_doc, 463130803Smarcel cmd_sfunc_ftype *set_func, 464130803Smarcel cmd_sfunc_ftype *show_func, 465130803Smarcel struct cmd_list_element **set_list, 466130803Smarcel struct cmd_list_element **show_list) 467130803Smarcel{ 468130803Smarcel add_setshow_cmd_full (name, class, var_uinteger, var, 469130803Smarcel set_doc, show_doc, 470130803Smarcel set_func, show_func, 471130803Smarcel set_list, show_list, 472130803Smarcel NULL, NULL); 473130803Smarcel} 474130803Smarcel 47598944Sobrien/* Where SETCMD has already been added, add the corresponding show 476130803Smarcel command to LIST and return a pointer to the added command (not 47798944Sobrien necessarily the head of LIST). */ 478130803Smarcel/* NOTE: cagney/2002-03-17: The original version of add_show_from_set 479130803Smarcel used memcpy() to clone `set' into `show'. This meant that in 480130803Smarcel addition to all the needed fields (var, name, et.al.) some 481130803Smarcel unnecessary fields were copied (namely the callback function). The 482130803Smarcel function explictly copies relevant fields. For a `set' and `show' 483130803Smarcel command to share the same callback, the caller must set both 484130803Smarcel explicitly. */ 48598944Sobrienstruct cmd_list_element * 48698944Sobrienadd_show_from_set (struct cmd_list_element *setcmd, 48798944Sobrien struct cmd_list_element **list) 48898944Sobrien{ 489130803Smarcel char *doc; 490130803Smarcel const static char setstring[] = "Set "; 49198944Sobrien 492130803Smarcel /* Create a doc string by replacing "Set " at the start of the 493130803Smarcel `set'' command's doco with "Show ". */ 494130803Smarcel gdb_assert (strncmp (setcmd->doc, setstring, sizeof (setstring) - 1) == 0); 495130803Smarcel doc = concat ("Show ", setcmd->doc + sizeof (setstring) - 1, NULL); 49698944Sobrien 497130803Smarcel /* Insert the basic command. */ 498130803Smarcel return add_set_or_show_cmd (setcmd->name, show_cmd, setcmd->class, 499130803Smarcel setcmd->var_type, setcmd->var, doc, list); 50098944Sobrien} 50198944Sobrien 50298944Sobrien/* Remove the command named NAME from the command list. */ 50398944Sobrien 50498944Sobrienvoid 50598944Sobriendelete_cmd (char *name, struct cmd_list_element **list) 50698944Sobrien{ 507130803Smarcel struct cmd_list_element *c; 50898944Sobrien struct cmd_list_element *p; 50998944Sobrien 510130803Smarcel while (*list && strcmp ((*list)->name, name) == 0) 51198944Sobrien { 51298944Sobrien if ((*list)->hookee_pre) 51398944Sobrien (*list)->hookee_pre->hook_pre = 0; /* Hook slips out of its mouth */ 51498944Sobrien if ((*list)->hookee_post) 51598944Sobrien (*list)->hookee_post->hook_post = 0; /* Hook slips out of its bottom */ 51698944Sobrien p = (*list)->next; 51798944Sobrien xfree (* list); 51898944Sobrien *list = p; 51998944Sobrien } 52098944Sobrien 52198944Sobrien if (*list) 52298944Sobrien for (c = *list; c->next;) 52398944Sobrien { 524130803Smarcel if (strcmp (c->next->name, name) == 0) 52598944Sobrien { 52698944Sobrien if (c->next->hookee_pre) 52798944Sobrien c->next->hookee_pre->hook_pre = 0; /* hooked cmd gets away. */ 52898944Sobrien if (c->next->hookee_post) 52998944Sobrien c->next->hookee_post->hook_post = 0; /* remove post hook */ 53098944Sobrien /* :( no fishing metaphore */ 53198944Sobrien p = c->next->next; 53298944Sobrien xfree (c->next); 53398944Sobrien c->next = p; 53498944Sobrien } 53598944Sobrien else 53698944Sobrien c = c->next; 53798944Sobrien } 53898944Sobrien} 53998944Sobrien 54098944Sobrien/* Shorthands to the commands above. */ 54198944Sobrien 54298944Sobrien/* Add an element to the list of info subcommands. */ 54398944Sobrien 54498944Sobrienstruct cmd_list_element * 54598944Sobrienadd_info (char *name, void (*fun) (char *, int), char *doc) 54698944Sobrien{ 54798944Sobrien return add_cmd (name, no_class, fun, doc, &infolist); 54898944Sobrien} 54998944Sobrien 55098944Sobrien/* Add an alias to the list of info subcommands. */ 55198944Sobrien 55298944Sobrienstruct cmd_list_element * 55398944Sobrienadd_info_alias (char *name, char *oldname, int abbrev_flag) 55498944Sobrien{ 55598944Sobrien return add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist); 55698944Sobrien} 55798944Sobrien 55898944Sobrien/* Add an element to the list of commands. */ 55998944Sobrien 56098944Sobrienstruct cmd_list_element * 56198944Sobrienadd_com (char *name, enum command_class class, void (*fun) (char *, int), 56298944Sobrien char *doc) 56398944Sobrien{ 56498944Sobrien return add_cmd (name, class, fun, doc, &cmdlist); 56598944Sobrien} 56698944Sobrien 56798944Sobrien/* Add an alias or abbreviation command to the list of commands. */ 56898944Sobrien 56998944Sobrienstruct cmd_list_element * 57098944Sobrienadd_com_alias (char *name, char *oldname, enum command_class class, 57198944Sobrien int abbrev_flag) 57298944Sobrien{ 57398944Sobrien return add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist); 57498944Sobrien} 57598944Sobrien 57698944Sobrien/* Recursively walk the commandlist structures, and print out the 57798944Sobrien documentation of commands that match our regex in either their 57898944Sobrien name, or their documentation. 57998944Sobrien*/ 58098944Sobrienvoid 58198944Sobrienapropos_cmd (struct ui_file *stream, struct cmd_list_element *commandlist, 58298944Sobrien struct re_pattern_buffer *regex, char *prefix) 58398944Sobrien{ 584130803Smarcel struct cmd_list_element *c; 58598944Sobrien int returnvalue=1; /*Needed to avoid double printing*/ 58698944Sobrien /* Walk through the commands */ 58798944Sobrien for (c=commandlist;c;c=c->next) 58898944Sobrien { 58998944Sobrien if (c->name != NULL) 59098944Sobrien { 59198944Sobrien /* Try to match against the name*/ 59298944Sobrien returnvalue=re_search(regex,c->name,strlen(c->name),0,strlen(c->name),NULL); 59398944Sobrien if (returnvalue >= 0) 59498944Sobrien { 59598944Sobrien /* Stolen from help_cmd_list. We don't directly use 59698944Sobrien * help_cmd_list because it doesn't let us print out 59798944Sobrien * single commands 59898944Sobrien */ 59998944Sobrien fprintf_filtered (stream, "%s%s -- ", prefix, c->name); 60098944Sobrien print_doc_line (stream, c->doc); 60198944Sobrien fputs_filtered ("\n", stream); 60298944Sobrien returnvalue=0; /*Set this so we don't print it again.*/ 60398944Sobrien } 60498944Sobrien } 60598944Sobrien if (c->doc != NULL && returnvalue != 0) 60698944Sobrien { 60798944Sobrien /* Try to match against documentation */ 60898944Sobrien if (re_search(regex,c->doc,strlen(c->doc),0,strlen(c->doc),NULL) >=0) 60998944Sobrien { 61098944Sobrien /* Stolen from help_cmd_list. We don't directly use 61198944Sobrien * help_cmd_list because it doesn't let us print out 61298944Sobrien * single commands 61398944Sobrien */ 61498944Sobrien fprintf_filtered (stream, "%s%s -- ", prefix, c->name); 61598944Sobrien print_doc_line (stream, c->doc); 61698944Sobrien fputs_filtered ("\n", stream); 61798944Sobrien } 61898944Sobrien } 61998944Sobrien /* Check if this command has subcommands */ 62098944Sobrien if (c->prefixlist != NULL) 62198944Sobrien { 62298944Sobrien /* Recursively call ourselves on the subcommand list, 62398944Sobrien passing the right prefix in. 62498944Sobrien */ 62598944Sobrien apropos_cmd (stream,*c->prefixlist,regex,c->prefixname); 62698944Sobrien } 62798944Sobrien } 62898944Sobrien} 62998944Sobrien 63098944Sobrien/* This command really has to deal with two things: 63198944Sobrien * 1) I want documentation on *this string* (usually called by 63298944Sobrien * "help commandname"). 63398944Sobrien * 2) I want documentation on *this list* (usually called by 63498944Sobrien * giving a command that requires subcommands. Also called by saying 63598944Sobrien * just "help".) 63698944Sobrien * 63798944Sobrien * I am going to split this into two seperate comamnds, help_cmd and 63898944Sobrien * help_list. 63998944Sobrien */ 64098944Sobrien 64198944Sobrienvoid 64298944Sobrienhelp_cmd (char *command, struct ui_file *stream) 64398944Sobrien{ 64498944Sobrien struct cmd_list_element *c; 64598944Sobrien extern struct cmd_list_element *cmdlist; 64698944Sobrien 64798944Sobrien if (!command) 64898944Sobrien { 64998944Sobrien help_list (cmdlist, "", all_classes, stream); 65098944Sobrien return; 65198944Sobrien } 65298944Sobrien 65398944Sobrien if (strcmp (command, "all") == 0) 65498944Sobrien { 65598944Sobrien help_all (stream); 65698944Sobrien return; 65798944Sobrien } 65898944Sobrien 65998944Sobrien c = lookup_cmd (&command, cmdlist, "", 0, 0); 66098944Sobrien 66198944Sobrien if (c == 0) 66298944Sobrien return; 66398944Sobrien 66498944Sobrien /* There are three cases here. 66598944Sobrien If c->prefixlist is nonzero, we have a prefix command. 66698944Sobrien Print its documentation, then list its subcommands. 66798944Sobrien 66898944Sobrien If c->func is non NULL, we really have a command. Print its 66998944Sobrien documentation and return. 67098944Sobrien 67198944Sobrien If c->func is NULL, we have a class name. Print its 67298944Sobrien documentation (as if it were a command) and then set class to the 67398944Sobrien number of this class so that the commands in the class will be 67498944Sobrien listed. */ 67598944Sobrien 67698944Sobrien fputs_filtered (c->doc, stream); 67798944Sobrien fputs_filtered ("\n", stream); 67898944Sobrien 67998944Sobrien if (c->prefixlist == 0 && c->func != NULL) 68098944Sobrien return; 68198944Sobrien fprintf_filtered (stream, "\n"); 68298944Sobrien 68398944Sobrien /* If this is a prefix command, print it's subcommands */ 68498944Sobrien if (c->prefixlist) 68598944Sobrien help_list (*c->prefixlist, c->prefixname, all_commands, stream); 68698944Sobrien 68798944Sobrien /* If this is a class name, print all of the commands in the class */ 68898944Sobrien if (c->func == NULL) 68998944Sobrien help_list (cmdlist, "", c->class, stream); 69098944Sobrien 69198944Sobrien if (c->hook_pre || c->hook_post) 69298944Sobrien fprintf_filtered (stream, 69398944Sobrien "\nThis command has a hook (or hooks) defined:\n"); 69498944Sobrien 69598944Sobrien if (c->hook_pre) 69698944Sobrien fprintf_filtered (stream, 69798944Sobrien "\tThis command is run after : %s (pre hook)\n", 69898944Sobrien c->hook_pre->name); 69998944Sobrien if (c->hook_post) 70098944Sobrien fprintf_filtered (stream, 70198944Sobrien "\tThis command is run before : %s (post hook)\n", 70298944Sobrien c->hook_post->name); 70398944Sobrien} 70498944Sobrien 70598944Sobrien/* 70698944Sobrien * Get a specific kind of help on a command list. 70798944Sobrien * 70898944Sobrien * LIST is the list. 70998944Sobrien * CMDTYPE is the prefix to use in the title string. 71098944Sobrien * CLASS is the class with which to list the nodes of this list (see 71198944Sobrien * documentation for help_cmd_list below), As usual, ALL_COMMANDS for 71298944Sobrien * everything, ALL_CLASSES for just classes, and non-negative for only things 71398944Sobrien * in a specific class. 71498944Sobrien * and STREAM is the output stream on which to print things. 71598944Sobrien * If you call this routine with a class >= 0, it recurses. 71698944Sobrien */ 71798944Sobrienvoid 71898944Sobrienhelp_list (struct cmd_list_element *list, char *cmdtype, 71998944Sobrien enum command_class class, struct ui_file *stream) 72098944Sobrien{ 72198944Sobrien int len; 72298944Sobrien char *cmdtype1, *cmdtype2; 72398944Sobrien 72498944Sobrien /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */ 72598944Sobrien len = strlen (cmdtype); 72698944Sobrien cmdtype1 = (char *) alloca (len + 1); 72798944Sobrien cmdtype1[0] = 0; 72898944Sobrien cmdtype2 = (char *) alloca (len + 4); 72998944Sobrien cmdtype2[0] = 0; 73098944Sobrien if (len) 73198944Sobrien { 73298944Sobrien cmdtype1[0] = ' '; 73398944Sobrien strncpy (cmdtype1 + 1, cmdtype, len - 1); 73498944Sobrien cmdtype1[len] = 0; 73598944Sobrien strncpy (cmdtype2, cmdtype, len - 1); 73698944Sobrien strcpy (cmdtype2 + len - 1, " sub"); 73798944Sobrien } 73898944Sobrien 73998944Sobrien if (class == all_classes) 74098944Sobrien fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2); 74198944Sobrien else 74298944Sobrien fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2); 74398944Sobrien 74498944Sobrien help_cmd_list (list, class, cmdtype, (int) class >= 0, stream); 74598944Sobrien 74698944Sobrien if (class == all_classes) 747130803Smarcel { 748130803Smarcel fprintf_filtered (stream, "\n\ 749130803SmarcelType \"help%s\" followed by a class name for a list of commands in ", 750130803Smarcel cmdtype1); 751130803Smarcel wrap_here (""); 752130803Smarcel fprintf_filtered (stream, "that class."); 753130803Smarcel } 75498944Sobrien 755130803Smarcel fprintf_filtered (stream, "\nType \"help%s\" followed by %scommand name ", 75698944Sobrien cmdtype1, cmdtype2); 757130803Smarcel wrap_here (""); 758130803Smarcel fputs_filtered ("for ", stream); 759130803Smarcel wrap_here (""); 760130803Smarcel fputs_filtered ("full ", stream); 761130803Smarcel wrap_here (""); 762130803Smarcel fputs_filtered ("documentation.\n", stream); 763130803Smarcel fputs_filtered ("Command name abbreviations are allowed if unambiguous.\n", 764130803Smarcel stream); 76598944Sobrien} 76698944Sobrien 76798944Sobrienstatic void 76898944Sobrienhelp_all (struct ui_file *stream) 76998944Sobrien{ 77098944Sobrien struct cmd_list_element *c; 77198944Sobrien extern struct cmd_list_element *cmdlist; 77298944Sobrien 77398944Sobrien for (c = cmdlist; c; c = c->next) 77498944Sobrien { 77598944Sobrien if (c->abbrev_flag) 77698944Sobrien continue; 77798944Sobrien /* If this is a prefix command, print it's subcommands */ 77898944Sobrien if (c->prefixlist) 77998944Sobrien help_cmd_list (*c->prefixlist, all_commands, c->prefixname, 0, stream); 78098944Sobrien 78198944Sobrien /* If this is a class name, print all of the commands in the class */ 78298944Sobrien else if (c->func == NULL) 78398944Sobrien help_cmd_list (cmdlist, c->class, "", 0, stream); 78498944Sobrien } 78598944Sobrien} 78698944Sobrien 78798944Sobrien/* Print only the first line of STR on STREAM. */ 78898944Sobrienvoid 78998944Sobrienprint_doc_line (struct ui_file *stream, char *str) 79098944Sobrien{ 79198944Sobrien static char *line_buffer = 0; 79298944Sobrien static int line_size; 793130803Smarcel char *p; 79498944Sobrien 79598944Sobrien if (!line_buffer) 79698944Sobrien { 79798944Sobrien line_size = 80; 79898944Sobrien line_buffer = (char *) xmalloc (line_size); 79998944Sobrien } 80098944Sobrien 80198944Sobrien p = str; 80298944Sobrien while (*p && *p != '\n' && *p != '.' && *p != ',') 80398944Sobrien p++; 80498944Sobrien if (p - str > line_size - 1) 80598944Sobrien { 80698944Sobrien line_size = p - str + 1; 80798944Sobrien xfree (line_buffer); 80898944Sobrien line_buffer = (char *) xmalloc (line_size); 80998944Sobrien } 81098944Sobrien strncpy (line_buffer, str, p - str); 81198944Sobrien line_buffer[p - str] = '\0'; 81298944Sobrien if (islower (line_buffer[0])) 81398944Sobrien line_buffer[0] = toupper (line_buffer[0]); 81498944Sobrien ui_out_text (uiout, line_buffer); 81598944Sobrien} 81698944Sobrien 81798944Sobrien/* 81898944Sobrien * Implement a help command on command list LIST. 81998944Sobrien * RECURSE should be non-zero if this should be done recursively on 82098944Sobrien * all sublists of LIST. 82198944Sobrien * PREFIX is the prefix to print before each command name. 82298944Sobrien * STREAM is the stream upon which the output should be written. 82398944Sobrien * CLASS should be: 82498944Sobrien * A non-negative class number to list only commands in that 82598944Sobrien * class. 82698944Sobrien * ALL_COMMANDS to list all commands in list. 82798944Sobrien * ALL_CLASSES to list all classes in list. 82898944Sobrien * 82998944Sobrien * Note that RECURSE will be active on *all* sublists, not just the 83098944Sobrien * ones selected by the criteria above (ie. the selection mechanism 83198944Sobrien * is at the low level, not the high-level). 83298944Sobrien */ 83398944Sobrienvoid 83498944Sobrienhelp_cmd_list (struct cmd_list_element *list, enum command_class class, 83598944Sobrien char *prefix, int recurse, struct ui_file *stream) 83698944Sobrien{ 837130803Smarcel struct cmd_list_element *c; 83898944Sobrien 83998944Sobrien for (c = list; c; c = c->next) 84098944Sobrien { 84198944Sobrien if (c->abbrev_flag == 0 && 84298944Sobrien (class == all_commands 84398944Sobrien || (class == all_classes && c->func == NULL) 84498944Sobrien || (class == c->class && c->func != NULL))) 84598944Sobrien { 84698944Sobrien fprintf_filtered (stream, "%s%s -- ", prefix, c->name); 84798944Sobrien print_doc_line (stream, c->doc); 84898944Sobrien fputs_filtered ("\n", stream); 84998944Sobrien } 85098944Sobrien if (recurse 85198944Sobrien && c->prefixlist != 0 85298944Sobrien && c->abbrev_flag == 0) 85398944Sobrien help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream); 85498944Sobrien } 85598944Sobrien} 85698944Sobrien 85798944Sobrien 85898944Sobrien/* Search the input clist for 'command'. Return the command if 85998944Sobrien found (or NULL if not), and return the number of commands 86098944Sobrien found in nfound */ 86198944Sobrien 86298944Sobrienstatic struct cmd_list_element * 86398944Sobrienfind_cmd (char *command, int len, struct cmd_list_element *clist, 86498944Sobrien int ignore_help_classes, int *nfound) 86598944Sobrien{ 86698944Sobrien struct cmd_list_element *found, *c; 86798944Sobrien 86898944Sobrien found = (struct cmd_list_element *) NULL; 86998944Sobrien *nfound = 0; 87098944Sobrien for (c = clist; c; c = c->next) 87198944Sobrien if (!strncmp (command, c->name, len) 87298944Sobrien && (!ignore_help_classes || c->func)) 87398944Sobrien { 87498944Sobrien found = c; 87598944Sobrien (*nfound)++; 87698944Sobrien if (c->name[len] == '\0') 87798944Sobrien { 87898944Sobrien *nfound = 1; 87998944Sobrien break; 88098944Sobrien } 88198944Sobrien } 88298944Sobrien return found; 88398944Sobrien} 88498944Sobrien 88598944Sobrien/* This routine takes a line of TEXT and a CLIST in which to start the 88698944Sobrien lookup. When it returns it will have incremented the text pointer past 88798944Sobrien the section of text it matched, set *RESULT_LIST to point to the list in 88898944Sobrien which the last word was matched, and will return a pointer to the cmd 88998944Sobrien list element which the text matches. It will return NULL if no match at 89098944Sobrien all was possible. It will return -1 (cast appropriately, ick) if ambigous 89198944Sobrien matches are possible; in this case *RESULT_LIST will be set to point to 89298944Sobrien the list in which there are ambiguous choices (and *TEXT will be set to 89398944Sobrien the ambiguous text string). 89498944Sobrien 89598944Sobrien If the located command was an abbreviation, this routine returns the base 89698944Sobrien command of the abbreviation. 89798944Sobrien 89898944Sobrien It does no error reporting whatsoever; control will always return 89998944Sobrien to the superior routine. 90098944Sobrien 90198944Sobrien In the case of an ambiguous return (-1), *RESULT_LIST will be set to point 90298944Sobrien at the prefix_command (ie. the best match) *or* (special case) will be NULL 90398944Sobrien if no prefix command was ever found. For example, in the case of "info a", 90498944Sobrien "info" matches without ambiguity, but "a" could be "args" or "address", so 90598944Sobrien *RESULT_LIST is set to the cmd_list_element for "info". So in this case 90698944Sobrien RESULT_LIST should not be interpeted as a pointer to the beginning of a 90798944Sobrien list; it simply points to a specific command. In the case of an ambiguous 90898944Sobrien return *TEXT is advanced past the last non-ambiguous prefix (e.g. 90998944Sobrien "info t" can be "info types" or "info target"; upon return *TEXT has been 91098944Sobrien advanced past "info "). 91198944Sobrien 91298944Sobrien If RESULT_LIST is NULL, don't set *RESULT_LIST (but don't otherwise 91398944Sobrien affect the operation). 91498944Sobrien 91598944Sobrien This routine does *not* modify the text pointed to by TEXT. 91698944Sobrien 91798944Sobrien If IGNORE_HELP_CLASSES is nonzero, ignore any command list elements which 91898944Sobrien are actually help classes rather than commands (i.e. the function field of 91998944Sobrien the struct cmd_list_element is NULL). */ 92098944Sobrien 92198944Sobrienstruct cmd_list_element * 92298944Sobrienlookup_cmd_1 (char **text, struct cmd_list_element *clist, 92398944Sobrien struct cmd_list_element **result_list, int ignore_help_classes) 92498944Sobrien{ 92598944Sobrien char *p, *command; 92698944Sobrien int len, tmp, nfound; 92798944Sobrien struct cmd_list_element *found, *c; 92898944Sobrien char *line = *text; 92998944Sobrien 93098944Sobrien while (**text == ' ' || **text == '\t') 93198944Sobrien (*text)++; 93298944Sobrien 93398944Sobrien /* Treating underscores as part of command words is important 93498944Sobrien so that "set args_foo()" doesn't get interpreted as 93598944Sobrien "set args _foo()". */ 936130803Smarcel /* NOTE: cagney/2003-02-13 The `tui_active' was previously 937130803Smarcel `tui_version'. */ 93898944Sobrien for (p = *text; 93998944Sobrien *p && (isalnum (*p) || *p == '-' || *p == '_' || 940130803Smarcel#if defined(TUI) 941130803Smarcel (tui_active && 94298944Sobrien (*p == '+' || *p == '<' || *p == '>' || *p == '$')) || 943130803Smarcel#endif 94498944Sobrien (xdb_commands && (*p == '!' || *p == '/' || *p == '?'))); 94598944Sobrien p++) 94698944Sobrien ; 94798944Sobrien 94898944Sobrien /* If nothing but whitespace, return 0. */ 94998944Sobrien if (p == *text) 95098944Sobrien return 0; 95198944Sobrien 95298944Sobrien len = p - *text; 95398944Sobrien 95498944Sobrien /* *text and p now bracket the first command word to lookup (and 95598944Sobrien it's length is len). We copy this into a local temporary */ 95698944Sobrien 95798944Sobrien 95898944Sobrien command = (char *) alloca (len + 1); 95998944Sobrien for (tmp = 0; tmp < len; tmp++) 96098944Sobrien { 96198944Sobrien char x = (*text)[tmp]; 96298944Sobrien command[tmp] = x; 96398944Sobrien } 96498944Sobrien command[len] = '\0'; 96598944Sobrien 96698944Sobrien /* Look it up. */ 96798944Sobrien found = 0; 96898944Sobrien nfound = 0; 96998944Sobrien found = find_cmd (command, len, clist, ignore_help_classes, &nfound); 97098944Sobrien 97198944Sobrien /* 97298944Sobrien ** We didn't find the command in the entered case, so lower case it 97398944Sobrien ** and search again. 97498944Sobrien */ 97598944Sobrien if (!found || nfound == 0) 97698944Sobrien { 97798944Sobrien for (tmp = 0; tmp < len; tmp++) 97898944Sobrien { 97998944Sobrien char x = command[tmp]; 98098944Sobrien command[tmp] = isupper (x) ? tolower (x) : x; 98198944Sobrien } 98298944Sobrien found = find_cmd (command, len, clist, ignore_help_classes, &nfound); 98398944Sobrien } 98498944Sobrien 98598944Sobrien /* If nothing matches, we have a simple failure. */ 98698944Sobrien if (nfound == 0) 98798944Sobrien return 0; 98898944Sobrien 98998944Sobrien if (nfound > 1) 99098944Sobrien { 99198944Sobrien if (result_list != NULL) 99298944Sobrien /* Will be modified in calling routine 99398944Sobrien if we know what the prefix command is. */ 99498944Sobrien *result_list = 0; 99598944Sobrien return (struct cmd_list_element *) -1; /* Ambiguous. */ 99698944Sobrien } 99798944Sobrien 99898944Sobrien /* We've matched something on this list. Move text pointer forward. */ 99998944Sobrien 100098944Sobrien *text = p; 100198944Sobrien 100298944Sobrien if (found->cmd_pointer) 100398944Sobrien { 100498944Sobrien /* We drop the alias (abbreviation) in favor of the command it is 100598944Sobrien pointing to. If the alias is deprecated, though, we need to 100698944Sobrien warn the user about it before we drop it. Note that while we 100798944Sobrien are warning about the alias, we may also warn about the command 100898944Sobrien itself and we will adjust the appropriate DEPRECATED_WARN_USER 100998944Sobrien flags */ 101098944Sobrien 101198944Sobrien if (found->flags & DEPRECATED_WARN_USER) 101298944Sobrien deprecated_cmd_warning (&line); 101398944Sobrien found = found->cmd_pointer; 101498944Sobrien } 101598944Sobrien /* If we found a prefix command, keep looking. */ 101698944Sobrien 101798944Sobrien if (found->prefixlist) 101898944Sobrien { 101998944Sobrien c = lookup_cmd_1 (text, *found->prefixlist, result_list, 102098944Sobrien ignore_help_classes); 102198944Sobrien if (!c) 102298944Sobrien { 102398944Sobrien /* Didn't find anything; this is as far as we got. */ 102498944Sobrien if (result_list != NULL) 102598944Sobrien *result_list = clist; 102698944Sobrien return found; 102798944Sobrien } 102898944Sobrien else if (c == (struct cmd_list_element *) -1) 102998944Sobrien { 103098944Sobrien /* We've gotten this far properly, but the next step 103198944Sobrien is ambiguous. We need to set the result list to the best 103298944Sobrien we've found (if an inferior hasn't already set it). */ 103398944Sobrien if (result_list != NULL) 103498944Sobrien if (!*result_list) 103598944Sobrien /* This used to say *result_list = *found->prefixlist 103698944Sobrien If that was correct, need to modify the documentation 103798944Sobrien at the top of this function to clarify what is supposed 103898944Sobrien to be going on. */ 103998944Sobrien *result_list = found; 104098944Sobrien return c; 104198944Sobrien } 104298944Sobrien else 104398944Sobrien { 104498944Sobrien /* We matched! */ 104598944Sobrien return c; 104698944Sobrien } 104798944Sobrien } 104898944Sobrien else 104998944Sobrien { 105098944Sobrien if (result_list != NULL) 105198944Sobrien *result_list = clist; 105298944Sobrien return found; 105398944Sobrien } 105498944Sobrien} 105598944Sobrien 105698944Sobrien/* All this hair to move the space to the front of cmdtype */ 105798944Sobrien 105898944Sobrienstatic void 105998944Sobrienundef_cmd_error (char *cmdtype, char *q) 106098944Sobrien{ 106198944Sobrien error ("Undefined %scommand: \"%s\". Try \"help%s%.*s\".", 106298944Sobrien cmdtype, 106398944Sobrien q, 106498944Sobrien *cmdtype ? " " : "", 1065130803Smarcel (int) strlen (cmdtype) - 1, 106698944Sobrien cmdtype); 106798944Sobrien} 106898944Sobrien 106998944Sobrien/* Look up the contents of *LINE as a command in the command list LIST. 107098944Sobrien LIST is a chain of struct cmd_list_element's. 107198944Sobrien If it is found, return the struct cmd_list_element for that command 107298944Sobrien and update *LINE to point after the command name, at the first argument. 107398944Sobrien If not found, call error if ALLOW_UNKNOWN is zero 107498944Sobrien otherwise (or if error returns) return zero. 107598944Sobrien Call error if specified command is ambiguous, 107698944Sobrien unless ALLOW_UNKNOWN is negative. 107798944Sobrien CMDTYPE precedes the word "command" in the error message. 107898944Sobrien 107998944Sobrien If INGNORE_HELP_CLASSES is nonzero, ignore any command list 108098944Sobrien elements which are actually help classes rather than commands (i.e. 108198944Sobrien the function field of the struct cmd_list_element is 0). */ 108298944Sobrien 108398944Sobrienstruct cmd_list_element * 108498944Sobrienlookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype, 108598944Sobrien int allow_unknown, int ignore_help_classes) 108698944Sobrien{ 108798944Sobrien struct cmd_list_element *last_list = 0; 108898944Sobrien struct cmd_list_element *c = 108998944Sobrien lookup_cmd_1 (line, list, &last_list, ignore_help_classes); 109098944Sobrien 109198944Sobrien /* Note: Do not remove trailing whitespace here because this 109298944Sobrien would be wrong for complete_command. Jim Kingdon */ 109398944Sobrien 109498944Sobrien if (!c) 109598944Sobrien { 109698944Sobrien if (!allow_unknown) 109798944Sobrien { 109898944Sobrien if (!*line) 109998944Sobrien error ("Lack of needed %scommand", cmdtype); 110098944Sobrien else 110198944Sobrien { 110298944Sobrien char *p = *line, *q; 110398944Sobrien 110498944Sobrien while (isalnum (*p) || *p == '-') 110598944Sobrien p++; 110698944Sobrien 110798944Sobrien q = (char *) alloca (p - *line + 1); 110898944Sobrien strncpy (q, *line, p - *line); 110998944Sobrien q[p - *line] = '\0'; 111098944Sobrien undef_cmd_error (cmdtype, q); 111198944Sobrien } 111298944Sobrien } 111398944Sobrien else 111498944Sobrien return 0; 111598944Sobrien } 111698944Sobrien else if (c == (struct cmd_list_element *) -1) 111798944Sobrien { 111898944Sobrien /* Ambigous. Local values should be off prefixlist or called 111998944Sobrien values. */ 112098944Sobrien int local_allow_unknown = (last_list ? last_list->allow_unknown : 112198944Sobrien allow_unknown); 112298944Sobrien char *local_cmdtype = last_list ? last_list->prefixname : cmdtype; 112398944Sobrien struct cmd_list_element *local_list = 112498944Sobrien (last_list ? *(last_list->prefixlist) : list); 112598944Sobrien 112698944Sobrien if (local_allow_unknown < 0) 112798944Sobrien { 112898944Sobrien if (last_list) 112998944Sobrien return last_list; /* Found something. */ 113098944Sobrien else 113198944Sobrien return 0; /* Found nothing. */ 113298944Sobrien } 113398944Sobrien else 113498944Sobrien { 113598944Sobrien /* Report as error. */ 113698944Sobrien int amb_len; 113798944Sobrien char ambbuf[100]; 113898944Sobrien 113998944Sobrien for (amb_len = 0; 114098944Sobrien ((*line)[amb_len] && (*line)[amb_len] != ' ' 114198944Sobrien && (*line)[amb_len] != '\t'); 114298944Sobrien amb_len++) 114398944Sobrien ; 114498944Sobrien 114598944Sobrien ambbuf[0] = 0; 114698944Sobrien for (c = local_list; c; c = c->next) 114798944Sobrien if (!strncmp (*line, c->name, amb_len)) 114898944Sobrien { 114998944Sobrien if (strlen (ambbuf) + strlen (c->name) + 6 < (int) sizeof ambbuf) 115098944Sobrien { 115198944Sobrien if (strlen (ambbuf)) 115298944Sobrien strcat (ambbuf, ", "); 115398944Sobrien strcat (ambbuf, c->name); 115498944Sobrien } 115598944Sobrien else 115698944Sobrien { 115798944Sobrien strcat (ambbuf, ".."); 115898944Sobrien break; 115998944Sobrien } 116098944Sobrien } 116198944Sobrien error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype, 116298944Sobrien *line, ambbuf); 116398944Sobrien return 0; /* lint */ 116498944Sobrien } 116598944Sobrien } 116698944Sobrien else 116798944Sobrien { 116898944Sobrien /* We've got something. It may still not be what the caller 116998944Sobrien wants (if this command *needs* a subcommand). */ 117098944Sobrien while (**line == ' ' || **line == '\t') 117198944Sobrien (*line)++; 117298944Sobrien 117398944Sobrien if (c->prefixlist && **line && !c->allow_unknown) 117498944Sobrien undef_cmd_error (c->prefixname, *line); 117598944Sobrien 117698944Sobrien /* Seems to be what he wants. Return it. */ 117798944Sobrien return c; 117898944Sobrien } 117998944Sobrien return 0; 118098944Sobrien} 118198944Sobrien 118298944Sobrien/* We are here presumably because an alias or command in *TEXT is 118398944Sobrien deprecated and a warning message should be generated. This function 118498944Sobrien decodes *TEXT and potentially generates a warning message as outlined 118598944Sobrien below. 118698944Sobrien 118798944Sobrien Example for 'set endian big' which has a fictitious alias 'seb'. 118898944Sobrien 118998944Sobrien If alias wasn't used in *TEXT, and the command is deprecated: 119098944Sobrien "warning: 'set endian big' is deprecated." 119198944Sobrien 119298944Sobrien If alias was used, and only the alias is deprecated: 119398944Sobrien "warning: 'seb' an alias for the command 'set endian big' is deprecated." 119498944Sobrien 119598944Sobrien If alias was used and command is deprecated (regardless of whether the 119698944Sobrien alias itself is deprecated: 119798944Sobrien 119898944Sobrien "warning: 'set endian big' (seb) is deprecated." 119998944Sobrien 120098944Sobrien After the message has been sent, clear the appropriate flags in the 120198944Sobrien command and/or the alias so the user is no longer bothered. 120298944Sobrien 120398944Sobrien*/ 120498944Sobrienvoid 120598944Sobriendeprecated_cmd_warning (char **text) 120698944Sobrien{ 120798944Sobrien struct cmd_list_element *alias = NULL; 120898944Sobrien struct cmd_list_element *prefix_cmd = NULL; 120998944Sobrien struct cmd_list_element *cmd = NULL; 121098944Sobrien struct cmd_list_element *c; 121198944Sobrien char *type; 121298944Sobrien 121398944Sobrien if (!lookup_cmd_composition (*text, &alias, &prefix_cmd, &cmd)) 121498944Sobrien /* return if text doesn't evaluate to a command */ 121598944Sobrien return; 121698944Sobrien 121798944Sobrien if (!((alias ? (alias->flags & DEPRECATED_WARN_USER) : 0) 121898944Sobrien || (cmd->flags & DEPRECATED_WARN_USER) ) ) 121998944Sobrien /* return if nothing is deprecated */ 122098944Sobrien return; 122198944Sobrien 122298944Sobrien printf_filtered ("Warning:"); 122398944Sobrien 122498944Sobrien if (alias && !(cmd->flags & CMD_DEPRECATED)) 122598944Sobrien printf_filtered (" '%s', an alias for the", alias->name); 122698944Sobrien 122798944Sobrien printf_filtered (" command '"); 122898944Sobrien 122998944Sobrien if (prefix_cmd) 123098944Sobrien printf_filtered ("%s", prefix_cmd->prefixname); 123198944Sobrien 123298944Sobrien printf_filtered ("%s", cmd->name); 123398944Sobrien 123498944Sobrien if (alias && (cmd->flags & CMD_DEPRECATED)) 123598944Sobrien printf_filtered ("' (%s) is deprecated.\n", alias->name); 123698944Sobrien else 123798944Sobrien printf_filtered ("' is deprecated.\n"); 123898944Sobrien 123998944Sobrien 124098944Sobrien /* if it is only the alias that is deprecated, we want to indicate the 124198944Sobrien new alias, otherwise we'll indicate the new command */ 124298944Sobrien 124398944Sobrien if (alias && !(cmd->flags & CMD_DEPRECATED)) 124498944Sobrien { 124598944Sobrien if (alias->replacement) 124698944Sobrien printf_filtered ("Use '%s'.\n\n", alias->replacement); 124798944Sobrien else 124898944Sobrien printf_filtered ("No alternative known.\n\n"); 124998944Sobrien } 125098944Sobrien else 125198944Sobrien { 125298944Sobrien if (cmd->replacement) 125398944Sobrien printf_filtered ("Use '%s'.\n\n", cmd->replacement); 125498944Sobrien else 125598944Sobrien printf_filtered ("No alternative known.\n\n"); 125698944Sobrien } 125798944Sobrien 125898944Sobrien /* We've warned you, now we'll keep quiet */ 125998944Sobrien if (alias) 126098944Sobrien alias->flags &= ~DEPRECATED_WARN_USER; 126198944Sobrien 126298944Sobrien cmd->flags &= ~DEPRECATED_WARN_USER; 126398944Sobrien} 126498944Sobrien 126598944Sobrien 126698944Sobrien 126798944Sobrien/* Look up the contents of LINE as a command in the command list 'cmdlist'. 126898944Sobrien Return 1 on success, 0 on failure. 126998944Sobrien 127098944Sobrien If LINE refers to an alias, *alias will point to that alias. 127198944Sobrien 127298944Sobrien If LINE is a postfix command (i.e. one that is preceeded by a prefix 127398944Sobrien command) set *prefix_cmd. 127498944Sobrien 127598944Sobrien Set *cmd to point to the command LINE indicates. 127698944Sobrien 127798944Sobrien If any of *alias, *prefix_cmd, or *cmd cannot be determined or do not 127898944Sobrien exist, they are NULL when we return. 127998944Sobrien 128098944Sobrien*/ 128198944Sobrienint 128298944Sobrienlookup_cmd_composition (char *text, 128398944Sobrien struct cmd_list_element **alias, 128498944Sobrien struct cmd_list_element **prefix_cmd, 128598944Sobrien struct cmd_list_element **cmd) 128698944Sobrien{ 128798944Sobrien char *p, *command; 128898944Sobrien int len, tmp, nfound; 128998944Sobrien struct cmd_list_element *cur_list; 129098944Sobrien struct cmd_list_element *prev_cmd; 129198944Sobrien *alias = NULL; 129298944Sobrien *prefix_cmd = NULL; 129398944Sobrien *cmd = NULL; 129498944Sobrien 129598944Sobrien cur_list = cmdlist; 129698944Sobrien 129798944Sobrien while (1) 129898944Sobrien { 129998944Sobrien /* Go through as many command lists as we need to 130098944Sobrien to find the command TEXT refers to. */ 130198944Sobrien 130298944Sobrien prev_cmd = *cmd; 130398944Sobrien 130498944Sobrien while (*text == ' ' || *text == '\t') 130598944Sobrien (text)++; 130698944Sobrien 130798944Sobrien /* Treating underscores as part of command words is important 130898944Sobrien so that "set args_foo()" doesn't get interpreted as 130998944Sobrien "set args _foo()". */ 1310130803Smarcel /* NOTE: cagney/2003-02-13 The `tui_active' was previously 1311130803Smarcel `tui_version'. */ 131298944Sobrien for (p = text; 131398944Sobrien *p && (isalnum (*p) || *p == '-' || *p == '_' || 1314130803Smarcel#if defined(TUI) 1315130803Smarcel (tui_active && 131698944Sobrien (*p == '+' || *p == '<' || *p == '>' || *p == '$')) || 1317130803Smarcel#endif 131898944Sobrien (xdb_commands && (*p == '!' || *p == '/' || *p == '?'))); 131998944Sobrien p++) 132098944Sobrien ; 132198944Sobrien 132298944Sobrien /* If nothing but whitespace, return. */ 132398944Sobrien if (p == text) 132498944Sobrien return 0; 132598944Sobrien 132698944Sobrien len = p - text; 132798944Sobrien 132898944Sobrien /* text and p now bracket the first command word to lookup (and 132998944Sobrien it's length is len). We copy this into a local temporary */ 133098944Sobrien 133198944Sobrien command = (char *) alloca (len + 1); 133298944Sobrien for (tmp = 0; tmp < len; tmp++) 133398944Sobrien { 133498944Sobrien char x = text[tmp]; 133598944Sobrien command[tmp] = x; 133698944Sobrien } 133798944Sobrien command[len] = '\0'; 133898944Sobrien 133998944Sobrien /* Look it up. */ 134098944Sobrien *cmd = 0; 134198944Sobrien nfound = 0; 134298944Sobrien *cmd = find_cmd (command, len, cur_list, 1, &nfound); 134398944Sobrien 134498944Sobrien /* We didn't find the command in the entered case, so lower case it 134598944Sobrien and search again. 134698944Sobrien */ 134798944Sobrien if (!*cmd || nfound == 0) 134898944Sobrien { 134998944Sobrien for (tmp = 0; tmp < len; tmp++) 135098944Sobrien { 135198944Sobrien char x = command[tmp]; 135298944Sobrien command[tmp] = isupper (x) ? tolower (x) : x; 135398944Sobrien } 135498944Sobrien *cmd = find_cmd (command, len, cur_list, 1, &nfound); 135598944Sobrien } 135698944Sobrien 135798944Sobrien if (*cmd == (struct cmd_list_element *) -1) 135898944Sobrien { 135998944Sobrien return 0; /* ambiguous */ 136098944Sobrien } 136198944Sobrien 136298944Sobrien if (*cmd == NULL) 136398944Sobrien return 0; /* nothing found */ 136498944Sobrien else 136598944Sobrien { 136698944Sobrien if ((*cmd)->cmd_pointer) 136798944Sobrien { 136898944Sobrien /* cmd was actually an alias, we note that an alias was used 136998944Sobrien (by assigning *alais) and we set *cmd. 137098944Sobrien */ 137198944Sobrien *alias = *cmd; 137298944Sobrien *cmd = (*cmd)->cmd_pointer; 137398944Sobrien } 137498944Sobrien *prefix_cmd = prev_cmd; 137598944Sobrien } 137698944Sobrien if ((*cmd)->prefixlist) 137798944Sobrien cur_list = *(*cmd)->prefixlist; 137898944Sobrien else 137998944Sobrien return 1; 138098944Sobrien 138198944Sobrien text = p; 138298944Sobrien } 138398944Sobrien} 138498944Sobrien 138598944Sobrien/* Helper function for SYMBOL_COMPLETION_FUNCTION. */ 138698944Sobrien 138798944Sobrien/* Return a vector of char pointers which point to the different 138898944Sobrien possible completions in LIST of TEXT. 138998944Sobrien 139098944Sobrien WORD points in the same buffer as TEXT, and completions should be 139198944Sobrien returned relative to this position. For example, suppose TEXT is "foo" 139298944Sobrien and we want to complete to "foobar". If WORD is "oo", return 139398944Sobrien "oobar"; if WORD is "baz/foo", return "baz/foobar". */ 139498944Sobrien 139598944Sobrienchar ** 139698944Sobriencomplete_on_cmdlist (struct cmd_list_element *list, char *text, char *word) 139798944Sobrien{ 139898944Sobrien struct cmd_list_element *ptr; 139998944Sobrien char **matchlist; 140098944Sobrien int sizeof_matchlist; 140198944Sobrien int matches; 140298944Sobrien int textlen = strlen (text); 140398944Sobrien 140498944Sobrien sizeof_matchlist = 10; 140598944Sobrien matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *)); 140698944Sobrien matches = 0; 140798944Sobrien 140898944Sobrien for (ptr = list; ptr; ptr = ptr->next) 140998944Sobrien if (!strncmp (ptr->name, text, textlen) 141098944Sobrien && !ptr->abbrev_flag 141198944Sobrien && (ptr->func 141298944Sobrien || ptr->prefixlist)) 141398944Sobrien { 141498944Sobrien if (matches == sizeof_matchlist) 141598944Sobrien { 141698944Sobrien sizeof_matchlist *= 2; 141798944Sobrien matchlist = (char **) xrealloc ((char *) matchlist, 141898944Sobrien (sizeof_matchlist 141998944Sobrien * sizeof (char *))); 142098944Sobrien } 142198944Sobrien 142298944Sobrien matchlist[matches] = (char *) 142398944Sobrien xmalloc (strlen (word) + strlen (ptr->name) + 1); 142498944Sobrien if (word == text) 142598944Sobrien strcpy (matchlist[matches], ptr->name); 142698944Sobrien else if (word > text) 142798944Sobrien { 142898944Sobrien /* Return some portion of ptr->name. */ 142998944Sobrien strcpy (matchlist[matches], ptr->name + (word - text)); 143098944Sobrien } 143198944Sobrien else 143298944Sobrien { 143398944Sobrien /* Return some of text plus ptr->name. */ 143498944Sobrien strncpy (matchlist[matches], word, text - word); 143598944Sobrien matchlist[matches][text - word] = '\0'; 143698944Sobrien strcat (matchlist[matches], ptr->name); 143798944Sobrien } 143898944Sobrien ++matches; 143998944Sobrien } 144098944Sobrien 144198944Sobrien if (matches == 0) 144298944Sobrien { 144398944Sobrien xfree (matchlist); 144498944Sobrien matchlist = 0; 144598944Sobrien } 144698944Sobrien else 144798944Sobrien { 144898944Sobrien matchlist = (char **) xrealloc ((char *) matchlist, ((matches + 1) 144998944Sobrien * sizeof (char *))); 145098944Sobrien matchlist[matches] = (char *) 0; 145198944Sobrien } 145298944Sobrien 145398944Sobrien return matchlist; 145498944Sobrien} 145598944Sobrien 145698944Sobrien/* Helper function for SYMBOL_COMPLETION_FUNCTION. */ 145798944Sobrien 145898944Sobrien/* Return a vector of char pointers which point to the different 145998944Sobrien possible completions in CMD of TEXT. 146098944Sobrien 146198944Sobrien WORD points in the same buffer as TEXT, and completions should be 146298944Sobrien returned relative to this position. For example, suppose TEXT is "foo" 146398944Sobrien and we want to complete to "foobar". If WORD is "oo", return 146498944Sobrien "oobar"; if WORD is "baz/foo", return "baz/foobar". */ 146598944Sobrien 146698944Sobrienchar ** 146798944Sobriencomplete_on_enum (const char *enumlist[], 146898944Sobrien char *text, 146998944Sobrien char *word) 147098944Sobrien{ 147198944Sobrien char **matchlist; 147298944Sobrien int sizeof_matchlist; 147398944Sobrien int matches; 147498944Sobrien int textlen = strlen (text); 147598944Sobrien int i; 147698944Sobrien const char *name; 147798944Sobrien 147898944Sobrien sizeof_matchlist = 10; 147998944Sobrien matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *)); 148098944Sobrien matches = 0; 148198944Sobrien 148298944Sobrien for (i = 0; (name = enumlist[i]) != NULL; i++) 148398944Sobrien if (strncmp (name, text, textlen) == 0) 148498944Sobrien { 148598944Sobrien if (matches == sizeof_matchlist) 148698944Sobrien { 148798944Sobrien sizeof_matchlist *= 2; 148898944Sobrien matchlist = (char **) xrealloc ((char *) matchlist, 148998944Sobrien (sizeof_matchlist 149098944Sobrien * sizeof (char *))); 149198944Sobrien } 149298944Sobrien 149398944Sobrien matchlist[matches] = (char *) 149498944Sobrien xmalloc (strlen (word) + strlen (name) + 1); 149598944Sobrien if (word == text) 149698944Sobrien strcpy (matchlist[matches], name); 149798944Sobrien else if (word > text) 149898944Sobrien { 149998944Sobrien /* Return some portion of name. */ 150098944Sobrien strcpy (matchlist[matches], name + (word - text)); 150198944Sobrien } 150298944Sobrien else 150398944Sobrien { 150498944Sobrien /* Return some of text plus name. */ 150598944Sobrien strncpy (matchlist[matches], word, text - word); 150698944Sobrien matchlist[matches][text - word] = '\0'; 150798944Sobrien strcat (matchlist[matches], name); 150898944Sobrien } 150998944Sobrien ++matches; 151098944Sobrien } 151198944Sobrien 151298944Sobrien if (matches == 0) 151398944Sobrien { 151498944Sobrien xfree (matchlist); 151598944Sobrien matchlist = 0; 151698944Sobrien } 151798944Sobrien else 151898944Sobrien { 151998944Sobrien matchlist = (char **) xrealloc ((char *) matchlist, ((matches + 1) 152098944Sobrien * sizeof (char *))); 152198944Sobrien matchlist[matches] = (char *) 0; 152298944Sobrien } 152398944Sobrien 152498944Sobrien return matchlist; 152598944Sobrien} 152698944Sobrien 1527130803Smarcel 1528130803Smarcel/* check function pointer */ 1529130803Smarcelint 1530130803Smarcelcmd_func_p (struct cmd_list_element *cmd) 1531130803Smarcel{ 1532130803Smarcel return (cmd->func != NULL); 1533130803Smarcel} 1534130803Smarcel 1535130803Smarcel 1536130803Smarcel/* call the command function */ 1537130803Smarcelvoid 1538130803Smarcelcmd_func (struct cmd_list_element *cmd, char *args, int from_tty) 1539130803Smarcel{ 1540130803Smarcel if (cmd_func_p (cmd)) 1541130803Smarcel (*cmd->func) (cmd, args, from_tty); 1542130803Smarcel else 1543130803Smarcel error ("Invalid command"); 1544130803Smarcel} 1545130803Smarcel 1546130803Smarcel 1547