Update copyright year in gdb/gdbserver/gdbreplay version output.
[deliverable/binutils-gdb.git] / gdb / cli / cli-decode.c
index b2c6f4efd4e236de094149cead152819b7dd7bf0..6dd418014916ca8b99ac984fed9b7897b4465d4f 100644 (file)
@@ -1,7 +1,7 @@
 /* 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 Free Software Foundation, Inc.
+   Copyright (c) 1986, 1989-1991, 1998, 2000-2002, 2004, 2007-2012 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 +52,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 +166,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 +240,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 +306,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 +323,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;
 }
 
@@ -279,16 +334,28 @@ add_alias_cmd (char *name, char *oldname, enum command_class class,
    containing that list.  */
 
 struct cmd_list_element *
-add_prefix_cmd (char *name, enum command_class class, void (*fun) (char *, int),
+add_prefix_cmd (char *name, enum command_class class,
+               void (*fun) (char *, int),
                char *doc, struct cmd_list_element **prefixlist,
                char *prefixname, int allow_unknown,
                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;
 }
 
@@ -391,10 +458,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)
@@ -411,7 +484,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,
@@ -431,6 +504,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
@@ -446,7 +521,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,
@@ -568,7 +642,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,
@@ -628,6 +703,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,
+                                    unsigned 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
@@ -685,6 +779,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;
 
@@ -1004,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)
     {
@@ -1017,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.
@@ -1126,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
@@ -1227,7 +1359,7 @@ lookup_cmd_1 (char **text, struct cmd_list_element *clist,
        /* Will be modified in calling routine
           if we know what the prefix command is.  */
        *result_list = 0;
-      return (struct cmd_list_element *) -1;   /* Ambiguous.  */
+      return CMD_LIST_AMBIGUOUS;       /* Ambiguous.  */
     }
 
   /* We've matched something on this list.  Move text pointer forward.  */
@@ -1260,7 +1392,7 @@ lookup_cmd_1 (char **text, struct cmd_list_element *clist,
            *result_list = clist;
          return found;
        }
-      else if (c == (struct cmd_list_element *) -1)
+      else if (c == CMD_LIST_AMBIGUOUS)
        {
          /* We've gotten this far properly, but the next step is
             ambiguous.  We need to set the result list to the best
@@ -1345,7 +1477,7 @@ lookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype,
       else
        return 0;
     }
-  else if (c == (struct cmd_list_element *) -1)
+  else if (c == CMD_LIST_AMBIGUOUS)
     {
       /* Ambigous.  Local values should be off prefixlist or called
          values.  */
@@ -1378,7 +1510,8 @@ lookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype,
          for (c = local_list; c; c = c->next)
            if (!strncmp (*line, c->name, amb_len))
              {
-               if (strlen (ambbuf) + strlen (c->name) + 6 < (int) sizeof ambbuf)
+               if (strlen (ambbuf) + strlen (c->name) + 6
+                   < (int) sizeof ambbuf)
                  {
                    if (strlen (ambbuf))
                      strcat (ambbuf, ", ");
@@ -1498,7 +1631,7 @@ deprecated_cmd_warning (char **text)
    
    If LINE refers to an alias, *alias will point to that alias.
    
-   If LINE is a postfix command (i.e. one that is preceeded by a prefix
+   If LINE is a postfix command (i.e. one that is preceded by a prefix
    command) set *prefix_cmd.
    
    Set *cmd to point to the command LINE indicates.
@@ -1526,7 +1659,7 @@ lookup_cmd_composition (char *text,
   
   while (1)
     { 
-      /* Go through as many command lists as we need to 
+      /* Go through as many command lists as we need to,
         to find the command TEXT refers to.  */
       
       prev_cmd = *cmd;
@@ -1567,7 +1700,7 @@ lookup_cmd_composition (char *text,
          *cmd = find_cmd (command, len, cur_list, 1, &nfound);
        }
       
-      if (*cmd == (struct cmd_list_element *) -1)
+      if (*cmd == CMD_LIST_AMBIGUOUS)
        {
          return 0;              /* ambiguous */
        }
@@ -1604,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)
@@ -1640,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.  */
@@ -1672,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;
 }
 
@@ -1697,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;
 }
 
This page took 0.031097 seconds and 4 git commands to generate.