gdb/
[binutils-gdb.git] / gdb / cli / cli-decode.c
index 744d52e1872b987db0a04f92ed27ce41d9253210..a8f7747ea6e71a9294e00ed954b1e8d40f3865b9 100644 (file)
@@ -1,7 +1,6 @@
 /* Handle lists of commands, their decoding and documentation, for GDB.
 
-   Copyright (c) 1986, 1989, 1990, 1991, 1998, 2000, 2001, 2002, 2004, 2007,
-   2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1986-2013 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -52,6 +51,53 @@ static struct cmd_list_element *find_cmd (char *command,
 
 static void help_all (struct ui_file *stream);
 
+/* Look up a command whose 'prefixlist' is KEY.  Return the command if found,
+   otherwise return NULL.  */
+
+static struct cmd_list_element *
+lookup_cmd_for_prefixlist (struct cmd_list_element **key,
+                          struct cmd_list_element *list)
+{
+  struct cmd_list_element *p = NULL;
+
+  for (p = list; p != NULL; p = p->next)
+    {
+      struct cmd_list_element *q;
+
+      if (p->prefixlist == NULL)
+       continue;
+      else if (p->prefixlist == key)
+       return p;
+
+      q = lookup_cmd_for_prefixlist (key, *(p->prefixlist));
+      if (q != NULL)
+       return q;
+    }
+
+  return NULL;
+}
+
+static void
+set_cmd_prefix (struct cmd_list_element *c, struct cmd_list_element **list)
+{
+  struct cmd_list_element *p;
+
+  /* Check to see if *LIST contains any element other than C.  */
+  for (p = *list; p != NULL; p = p->next)
+    if (p != c)
+      break;
+
+  if (p == NULL)
+    {
+      /* *SET_LIST only contains SET.  */
+      p = lookup_cmd_for_prefixlist (list, setlist);
+
+      c->prefix = p ? (p->cmd_pointer ? p->cmd_pointer : p) : p;
+    }
+  else
+    c->prefix = p->prefix;
+}
+
 static void
 print_help_for_command (struct cmd_list_element *c, char *prefix, int recurse,
                        struct ui_file *stream);
@@ -119,15 +165,13 @@ cmd_type (struct cmd_list_element *cmd)
 }
 
 void
-set_cmd_completer (struct cmd_list_element *cmd,
-                  char **(*completer) (struct cmd_list_element *self,
-                                       char *text, char *word))
+set_cmd_completer (struct cmd_list_element *cmd, completer_ftype *completer)
 {
   cmd->completer = completer; /* Ok.  */
 }
 
-
 /* Add element named NAME.
+   Space for NAME and DOC must be allocated by the caller.
    CLASS is the top level category into which commands are broken down
    for "help" purposes.
    FUN should be the function to execute the command;
@@ -195,6 +239,7 @@ add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
   c->prefixlist = NULL;
   c->prefixname = NULL;
   c->allow_unknown = 0;
+  c->prefix = NULL;
   c->abbrev_flag = 0;
   set_cmd_completer (c, make_symbol_completion_list_fn);
   c->destroyer = NULL;
@@ -260,6 +305,13 @@ add_alias_cmd (char *name, char *oldname, enum command_class class,
     }
 
   c = add_cmd (name, class, NULL, old->doc, list);
+
+  /* If OLD->DOC can be freed, we should make another copy.  */
+  if ((old->flags & DOC_ALLOCATED) != 0)
+    {
+      c->doc = xstrdup (old->doc);
+      c->flags |= DOC_ALLOCATED;
+    }
   /* NOTE: Both FUNC and all the FUNCTIONs need to be copied.  */
   c->func = old->func;
   c->function = old->function;
@@ -270,6 +322,8 @@ add_alias_cmd (char *name, char *oldname, enum command_class class,
   c->cmd_pointer = old;
   c->alias_chain = old->aliases;
   old->aliases = c;
+
+  set_cmd_prefix (c, list);
   return c;
 }
 
@@ -286,10 +340,21 @@ add_prefix_cmd (char *name, enum command_class class,
                struct cmd_list_element **list)
 {
   struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+  struct cmd_list_element *p;
 
   c->prefixlist = prefixlist;
   c->prefixname = prefixname;
   c->allow_unknown = allow_unknown;
+
+  if (list == &cmdlist)
+    c->prefix = NULL;
+  else
+    set_cmd_prefix (c, list);
+
+  /* Update the field 'prefix' of each cmd_list_element in *PREFIXLIST.  */
+  for (p = *prefixlist; p != NULL; p = p->next)
+    p->prefix = c;
+
   return c;
 }
 
@@ -392,10 +457,16 @@ add_setshow_cmd_full (char *name,
     }
   set = add_set_or_show_cmd (name, set_cmd, class, var_type, var,
                             full_set_doc, set_list);
+  set->flags |= DOC_ALLOCATED;
+
   if (set_func != NULL)
     set_cmd_sfunc (set, set_func);
+
+  set_cmd_prefix (set, set_list);
+
   show = add_set_or_show_cmd (name, show_cmd, class, var_type, var,
                              full_show_doc, show_list);
+  show->flags |= DOC_ALLOCATED;
   show->show_value_func = show_func;
 
   if (set_result != NULL)
@@ -412,7 +483,7 @@ add_setshow_cmd_full (char *name,
 void
 add_setshow_enum_cmd (char *name,
                      enum command_class class,
-                     const char *enumlist[],
+                     const char *const *enumlist,
                      const char **var,
                      const char *set_doc,
                      const char *show_doc,
@@ -432,6 +503,8 @@ add_setshow_enum_cmd (char *name,
   c->enums = enumlist;
 }
 
+const char * const auto_boolean_enums[] = { "on", "off", "auto", NULL };
+
 /* Add an auto-boolean command named NAME to both the set and show
    command list lists.  CLASS is as in add_cmd.  VAR is address of the
    variable which will contain the value.  DOC is the documentation
@@ -447,7 +520,6 @@ add_setshow_auto_boolean_cmd (char *name,
                              struct cmd_list_element **set_list,
                              struct cmd_list_element **show_list)
 {
-  static const char *auto_boolean_enums[] = { "on", "off", "auto", NULL };
   struct cmd_list_element *c;
 
   add_setshow_cmd_full (name, class, var_auto_boolean, var,
@@ -525,7 +597,7 @@ add_setshow_string_cmd (char *name, enum command_class class,
 
 /* Add element named NAME to both the set and show command LISTs (the
    list for set/show or some sublist thereof).  */
-void
+struct cmd_list_element *
 add_setshow_string_noescape_cmd (char *name, enum command_class class,
                                 char **var,
                                 const char *set_doc, const char *show_doc,
@@ -535,11 +607,14 @@ add_setshow_string_noescape_cmd (char *name, enum command_class class,
                                 struct cmd_list_element **set_list,
                                 struct cmd_list_element **show_list)
 {
+  struct cmd_list_element *set_cmd;
+
   add_setshow_cmd_full (name, class, var_string_noescape, var,
                        set_doc, show_doc, help_doc,
                        set_func, show_func,
                        set_list, show_list,
-                       NULL, NULL);
+                       &set_cmd, NULL);
+  return set_cmd;
 }
 
 /* Add element named NAME to both the set and show command LISTs (the
@@ -569,7 +644,8 @@ add_setshow_optional_filename_cmd (char *name, enum command_class class,
 /* Add element named NAME to both the set and show command LISTs (the
    list for set/show or some sublist thereof).  CLASS is as in
    add_cmd.  VAR is address of the variable which will contain the
-   value.  SET_DOC and SHOW_DOC are the documentation strings.  */
+   value.  SET_DOC and SHOW_DOC are the documentation strings.  This
+   function is only used in Python API.  Please don't use it elsewhere.  */
 void
 add_setshow_integer_cmd (char *name, enum command_class class,
                         int *var,
@@ -629,6 +705,25 @@ add_setshow_zinteger_cmd (char *name, enum command_class class,
                        NULL, NULL);
 }
 
+void
+add_setshow_zuinteger_unlimited_cmd (char *name,
+                                    enum command_class class,
+                                    int *var,
+                                    const char *set_doc,
+                                    const char *show_doc,
+                                    const char *help_doc,
+                                    cmd_sfunc_ftype *set_func,
+                                    show_value_ftype *show_func,
+                                    struct cmd_list_element **set_list,
+                                    struct cmd_list_element **show_list)
+{
+  add_setshow_cmd_full (name, class, var_zuinteger_unlimited, var,
+                       set_doc, show_doc, help_doc,
+                       set_func, show_func,
+                       set_list, show_list,
+                       NULL, NULL);
+}
+
 /* Add element named NAME to both the set and show command LISTs (the
    list for set/show or some sublist thereof).  CLASS is as in
    add_cmd.  VAR is address of the variable which will contain the
@@ -686,6 +781,8 @@ delete_cmd (char *name, struct cmd_list_element **list,
          *prehookee = iter->hookee_pre;
          if (iter->hookee_post)
            iter->hookee_post->hook_post = 0;
+         if (iter->doc && (iter->flags & DOC_ALLOCATED) != 0)
+           xfree (iter->doc);
          *posthook = iter->hook_post;
          *posthookee = iter->hookee_post;
 
@@ -820,7 +917,6 @@ void
 help_cmd (char *command, struct ui_file *stream)
 {
   struct cmd_list_element *c;
-  extern struct cmd_list_element *cmdlist;
 
   if (!command)
     {
@@ -952,7 +1048,6 @@ static void
 help_all (struct ui_file *stream)
 {
   struct cmd_list_element *c;
-  extern struct cmd_list_element *cmdlist;
   int seen_unclassified = 0;
 
   for (c = cmdlist; c; c = c->next)
@@ -1005,8 +1100,11 @@ print_doc_line (struct ui_file *stream, char *str)
       line_buffer = (char *) xmalloc (line_size);
     }
 
+  /* Keep printing '.' or ',' not followed by a whitespace for embedded strings
+     like '.gdbinit'.  */
   p = str;
-  while (*p && *p != '\n' && *p != '.' && *p != ',')
+  while (*p && *p != '\n'
+        && ((*p != '.' && *p != ',') || (p[1] && !isspace (p[1]))))
     p++;
   if (p - str > line_size - 1)
     {
@@ -1018,7 +1116,7 @@ print_doc_line (struct ui_file *stream, char *str)
   line_buffer[p - str] = '\0';
   if (islower (line_buffer[0]))
     line_buffer[0] = toupper (line_buffer[0]);
-  ui_out_text (uiout, line_buffer);
+  fputs_filtered (line_buffer, stream);
 }
 
 /* Print one-line help for command C.
@@ -1127,16 +1225,49 @@ find_command_name_length (const char *text)
      Note that this is larger than the character set allowed when
      creating user-defined commands.  */
 
+  /* Recognize '!' as a single character command so that, e.g., "!ls"
+     works as expected.  */
+  if (*p == '!')
+    return 1;
+
   while (isalnum (*p) || *p == '-' || *p == '_'
         /* Characters used by TUI specific commands.  */
         || *p == '+' || *p == '<' || *p == '>' || *p == '$'
         /* Characters used for XDB compatibility.  */
-        || (xdb_commands && (*p == '!' || *p == '/' || *p == '?')))
+        || (xdb_commands && (*p == '/' || *p == '?')))
     p++;
 
   return p - text;
 }
 
+/* Return TRUE if NAME is a valid user-defined command name.
+   This is a stricter subset of all gdb commands,
+   see find_command_name_length.  */
+
+int
+valid_user_defined_cmd_name_p (const char *name)
+{
+  const char *p;
+
+  if (*name == '\0')
+    return FALSE;
+
+  /* Alas "42" is a legitimate user-defined command.
+     In the interests of not breaking anything we preserve that.  */
+
+  for (p = name; *p != '\0'; ++p)
+    {
+      if (isalnum (*p)
+         || *p == '-'
+         || *p == '_')
+       ; /* Ok.  */
+      else
+       return FALSE;
+    }
+
+  return TRUE;
+}
+
 /* This routine takes a line of TEXT and a CLIST in which to start the
    lookup.  When it returns it will have incremented the text pointer past
    the section of text it matched, set *RESULT_LIST to point to the list in
@@ -1606,33 +1737,30 @@ lookup_cmd_composition (char *text,
    "foo" and we want to complete to "foobar".  If WORD is "oo", return
    "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
 
-char **
-complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
+VEC (char_ptr) *
+complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word,
+                    int ignore_help_classes)
 {
   struct cmd_list_element *ptr;
-  char **matchlist;
-  int sizeof_matchlist;
-  int matches;
+  VEC (char_ptr) *matchlist = NULL;
   int textlen = strlen (text);
   int pass;
   int saw_deprecated_match = 0;
 
-  sizeof_matchlist = 10;
-  matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
-  matches = 0;
-
   /* We do one or two passes.  In the first pass, we skip deprecated
      commands.  If we see no matching commands in the first pass, and
      if we did happen to see a matching deprecated command, we do
      another loop to collect those.  */
-  for (pass = 0; matches == 0 && pass < 2; ++pass)
+  for (pass = 0; matchlist == 0 && pass < 2; ++pass)
     {
       for (ptr = list; ptr; ptr = ptr->next)
        if (!strncmp (ptr->name, text, textlen)
            && !ptr->abbrev_flag
-           && (ptr->func
+           && (!ignore_help_classes || ptr->func
                || ptr->prefixlist))
          {
+           char *match;
+
            if (pass == 0)
              {
                if ((ptr->flags & CMD_DEPRECATED) != 0)
@@ -1642,31 +1770,22 @@ complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
                  }
              }
 
-           if (matches == sizeof_matchlist)
-             {
-               sizeof_matchlist *= 2;
-               matchlist = (char **) xrealloc ((char *) matchlist,
-                                               (sizeof_matchlist
-                                                * sizeof (char *)));
-             }
-
-           matchlist[matches] = (char *)
-             xmalloc (strlen (word) + strlen (ptr->name) + 1);
+           match = (char *) xmalloc (strlen (word) + strlen (ptr->name) + 1);
            if (word == text)
-             strcpy (matchlist[matches], ptr->name);
+             strcpy (match, ptr->name);
            else if (word > text)
              {
                /* Return some portion of ptr->name.  */
-               strcpy (matchlist[matches], ptr->name + (word - text));
+               strcpy (match, ptr->name + (word - text));
              }
            else
              {
                /* Return some of text plus ptr->name.  */
-               strncpy (matchlist[matches], word, text - word);
-               matchlist[matches][text - word] = '\0';
-               strcat (matchlist[matches], ptr->name);
+               strncpy (match, word, text - word);
+               match[text - word] = '\0';
+               strcat (match, ptr->name);
              }
-           ++matches;
+           VEC_safe_push (char_ptr, matchlist, match);
          }
       /* If we saw no matching deprecated commands in the first pass,
         just bail out.  */
@@ -1674,18 +1793,6 @@ complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
        break;
     }
 
-  if (matches == 0)
-    {
-      xfree (matchlist);
-      matchlist = 0;
-    }
-  else
-    {
-      matchlist = (char **) xrealloc ((char *) matchlist, ((matches + 1)
-                                                       * sizeof (char *)));
-      matchlist[matches] = (char *) 0;
-    }
-
   return matchlist;
 }
 
@@ -1699,64 +1806,39 @@ complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
    and we want to complete to "foobar".  If WORD is "oo", return
    "oobar"; if WORD is "baz/foo", return "baz/foobar".  */
 
-char **
-complete_on_enum (const char *enumlist[],
+VEC (char_ptr) *
+complete_on_enum (const char *const *enumlist,
                  char *text,
                  char *word)
 {
-  char **matchlist;
-  int sizeof_matchlist;
-  int matches;
+  VEC (char_ptr) *matchlist = NULL;
   int textlen = strlen (text);
   int i;
   const char *name;
 
-  sizeof_matchlist = 10;
-  matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
-  matches = 0;
-
   for (i = 0; (name = enumlist[i]) != NULL; i++)
     if (strncmp (name, text, textlen) == 0)
       {
-       if (matches == sizeof_matchlist)
-         {
-           sizeof_matchlist *= 2;
-           matchlist = (char **) xrealloc ((char *) matchlist,
-                                           (sizeof_matchlist
-                                            * sizeof (char *)));
-         }
+       char *match;
 
-       matchlist[matches] = (char *)
-         xmalloc (strlen (word) + strlen (name) + 1);
+       match = (char *) xmalloc (strlen (word) + strlen (name) + 1);
        if (word == text)
-         strcpy (matchlist[matches], name);
+         strcpy (match, name);
        else if (word > text)
          {
            /* Return some portion of name.  */
-           strcpy (matchlist[matches], name + (word - text));
+           strcpy (match, name + (word - text));
          }
        else
          {
            /* Return some of text plus name.  */
-           strncpy (matchlist[matches], word, text - word);
-           matchlist[matches][text - word] = '\0';
-           strcat (matchlist[matches], name);
+           strncpy (match, word, text - word);
+           match[text - word] = '\0';
+           strcat (match, name);
          }
-       ++matches;
+       VEC_safe_push (char_ptr, matchlist, match);
       }
 
-  if (matches == 0)
-    {
-      xfree (matchlist);
-      matchlist = 0;
-    }
-  else
-    {
-      matchlist = (char **) xrealloc ((char *) matchlist, ((matches + 1)
-                                                          * sizeof (char *)));
-      matchlist[matches] = (char *) 0;
-    }
-
   return matchlist;
 }