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