Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / builtins / complete.def
index 732ba03..8499b7a 100644 (file)
@@ -1,35 +1,50 @@
 This file is complete.def, from which is created complete.c.
-It implements the builtins "complete" and "compgen" in Bash.
+It implements the builtins "complete", "compgen", and "compopt" in Bash.
 
-Copyright (C) 1999 Free Software Foundation, Inc.
+Copyright (C) 1999-2011 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
-Bash is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
+Bash is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
-Bash is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
+Bash is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License along
-with Bash; see the file COPYING.  If not, write to the Free Software
-Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+You should have received a copy of the GNU General Public License
+along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 
 $PRODUCES complete.c
 
 $BUILTIN complete
 $DEPENDS_ON PROGRAMMABLE_COMPLETION
 $FUNCTION complete_builtin
-$SHORT_DOC complete [-abcdefgjkvu] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]
-For each NAME, specify how arguments are to be completed.
-If the -p option is supplied, or if no options are supplied, existing
-completion specifications are printed in a way that allows them to be
-reused as input.  The -r option removes a completion specification for
-each NAME, or, if no NAMEs are supplied, all completion specifications.
+$SHORT_DOC complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]
+Specify how arguments are to be completed by Readline.
+
+For each NAME, specify how arguments are to be completed.  If no options
+are supplied, existing completion specifications are printed in a way that
+allows them to be reused as input.
+
+Options:
+  -p   print existing completion specifications in a reusable format
+  -r   remove a completion specification for each NAME, or, if no
+       NAMEs are supplied, all completion specifications
+  -D   apply the completions and actions as the default for commands
+       without any specific completion defined
+  -E   apply the completions and actions to "empty" commands --
+       completion attempted on a blank line
+
+When completion is attempted, the actions are applied in the order the
+uppercase-letter options are listed above.  The -D option takes
+precedence over -E.
+
+Exit Status:
+Returns success unless an invalid option is supplied or an error occurs.
 $END
 
 #include <config.h>
@@ -43,10 +58,12 @@ $END
 #endif
 
 #include "../bashansi.h"
+#include "../bashintl.h"
 
 #include "../shell.h"
 #include "../builtins.h"
 #include "../pcomplete.h"
+#include "../bashline.h"
 
 #include "common.h"
 #include "bashgetopt.h"
@@ -55,21 +72,32 @@ $END
 
 #define STRDUP(x)       ((x) ? savestring (x) : (char *)NULL)
 
+/* Structure containing all the non-action (binary) options; filled in by
+   build_actions(). */
+struct _optflags {
+  int pflag;
+  int rflag;
+  int Dflag;
+  int Eflag;
+};
+
 static int find_compact __P((char *));
 static int find_compopt __P((char *));
 
-static int build_actions __P((WORD_LIST *, int *, int *, unsigned long *, unsigned long *));
+static int build_actions __P((WORD_LIST *, struct _optflags *, unsigned long *, unsigned long *));
 
 static int remove_cmd_completions __P((WORD_LIST *));
 
-static void print_one_completion __P((char *, COMPSPEC *));
+static int print_one_completion __P((char *, COMPSPEC *));
+static int print_compitem __P((BUCKET_CONTENTS *));
+static void print_compopts __P((const char *, COMPSPEC *, int));
 static void print_all_completions __P((void));
 static int print_cmd_completions __P((WORD_LIST *));
 
-static char *Aarg, *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
+static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
 
-static struct _compacts {
-  char *actname;
+static const struct _compacts {
+  const char * const actname;
   int actflag;
   int actopt;
 } compacts[] = {
@@ -84,12 +112,13 @@ static struct _compacts {
   { "export",    CA_EXPORT,    'e' },
   { "file",      CA_FILE,      'f' },
   { "function",  CA_FUNCTION,   0 },
-  { "helptopic", CA_BUILTIN,  0 },     /* for now */
+  { "helptopic", CA_HELPTOPIC,  0 },
   { "hostname",  CA_HOSTNAME,   0 },
   { "group",     CA_GROUP,     'g' },
   { "job",       CA_JOB,       'j' },
   { "keyword",   CA_KEYWORD,   'k' },
   { "running",   CA_RUNNING,    0 },
+  { "service",   CA_SERVICE,   's' },
   { "setopt",    CA_SETOPT,     0 },
   { "shopt",     CA_SHOPT,      0 },
   { "signal",    CA_SIGNAL,     0 },
@@ -99,13 +128,18 @@ static struct _compacts {
   { (char *)NULL, 0, 0 },
 };
 
-static struct _compopt {
-  char *optname;
+/* This should be a STRING_INT_ALIST */
+static const struct _compopt {
+  const char * const optname;
   int optflag;
 } compopts[] = {
+  { "bashdefault", COPT_BASHDEFAULT },
   { "default", COPT_DEFAULT },
   { "dirnames", COPT_DIRNAMES },
   { "filenames",COPT_FILENAMES},
+  { "noquote", COPT_NOQUOTE },
+  { "nospace", COPT_NOSPACE },
+  { "plusdirs", COPT_PLUSDIRS },
   { (char *)NULL, 0 },
 };
 
@@ -148,9 +182,9 @@ find_compopt (name)
 */
 
 static int
-build_actions (list, pp, rp, actp, optp)
+build_actions (list, flagp, actp, optp)
      WORD_LIST *list;
-     int *pp, *rp;
+     struct _optflags *flagp;
      unsigned long *actp, *optp;
 {
   int opt, ind, opt_given;
@@ -160,33 +194,33 @@ build_actions (list, pp, rp, actp, optp)
   opt_given = 0;
 
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "abcdefgjko:pruvA:G:W:P:S:X:F:C:")) != -1)
+  while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:DE")) != -1)
     {
       opt_given = 1;
       switch (opt)
        {
        case 'r':
-         if (rp)
+         if (flagp)
            {
-             *rp = 1;
+             flagp->rflag = 1;
              break;
            }
          else
            {
-             builtin_error ("illegal option: -r");
+             sh_invalidopt ("-r");
              builtin_usage ();
              return (EX_USAGE);
            }
 
        case 'p':
-         if (pp)
+         if (flagp)
            {
-             *pp = 1;
+             flagp->pflag = 1;
              break;
            }
          else
            {
-             builtin_error ("illegal option: -p");
+             sh_invalidopt ("-p");
              builtin_usage ();
              return (EX_USAGE);
            }
@@ -218,6 +252,9 @@ build_actions (list, pp, rp, actp, optp)
        case 'k':
          acts |= CA_KEYWORD;
          break;
+       case 's':
+         acts |= CA_SERVICE;
+         break;
        case 'u':
          acts |= CA_USER;
          break;
@@ -228,7 +265,7 @@ build_actions (list, pp, rp, actp, optp)
          ind = find_compopt (list_optarg);
          if (ind < 0)
            {
-             builtin_error ("%s: invalid option name", list_optarg);
+             sh_invalidoptname (list_optarg);
              return (EX_USAGE);
            }
          copts |= compopts[ind].optflag;
@@ -237,7 +274,7 @@ build_actions (list, pp, rp, actp, optp)
          ind = find_compact (list_optarg);
          if (ind < 0)
            {
-             builtin_error ("%s: invalid action name", list_optarg);
+             builtin_error (_("%s: invalid action name"), list_optarg);
              return (EX_USAGE);
            }
          acts |= compacts[ind].actflag;
@@ -245,6 +282,30 @@ build_actions (list, pp, rp, actp, optp)
        case 'C':
          Carg = list_optarg;
          break;
+       case 'D':
+         if (flagp)
+           {
+             flagp->Dflag = 1;
+             break;
+           }
+         else
+           {
+             sh_invalidopt ("-D");
+             builtin_usage ();
+             return (EX_USAGE);
+           }
+       case 'E':
+         if (flagp)
+           {
+             flagp->Eflag = 1;
+             break;
+           }
+         else
+           {
+             sh_invalidopt ("-E");
+             builtin_usage ();
+             return (EX_USAGE);
+           }
        case 'F':
          Farg = list_optarg;
          break;
@@ -280,10 +341,11 @@ int
 complete_builtin (list)
      WORD_LIST *list;
 {
-  int opt_given, pflag, rflag, rval;
+  int opt_given, rval;
   unsigned long acts, copts;
-  char *cmd;
   COMPSPEC *cs;
+  struct _optflags oflags;
+  WORD_LIST *l, *wl;
 
   if (list == 0)
     {
@@ -291,24 +353,34 @@ complete_builtin (list)
       return (EXECUTION_SUCCESS);
     }
 
-  opt_given = pflag = rflag = 0;
+  opt_given = oflags.pflag = oflags.rflag = oflags.Dflag = oflags.Eflag = 0;
+
   acts = copts = (unsigned long)0L;
-  Aarg = Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
+  Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
   cs = (COMPSPEC *)NULL;
 
   /* Build the actions from the arguments.  Also sets the [A-Z]arg variables
      as a side effect if they are supplied as options. */
-  rval = build_actions (list, &pflag, &rflag, &acts, &copts);
+  rval = build_actions (list, &oflags, &acts, &copts);
   if (rval == EX_USAGE)
     return (rval);
   opt_given = rval != EXECUTION_FAILURE;
 
   list = loptend;
 
+  wl = oflags.Dflag ? make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL)
+                   : (oflags.Eflag ? make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL) : 0);
+
   /* -p overrides everything else */
-  if (pflag || (list == 0 && opt_given == 0))
+  if (oflags.pflag || (list == 0 && opt_given == 0))
     {
-      if (list == 0)
+      if (wl)
+       {
+         rval = print_cmd_completions (wl);
+         dispose_words (wl);
+         return rval;
+       }
+      else if (list == 0)
        {
          print_all_completions ();
          return (EXECUTION_SUCCESS);
@@ -317,17 +389,23 @@ complete_builtin (list)
     }
 
   /* next, -r overrides everything else. */
-  if (rflag)
+  if (oflags.rflag)
     {
-      if (list == 0)
+      if (wl)
        {
-         clear_progcomps ();
+         rval = remove_cmd_completions (wl);
+         dispose_words (wl);
+         return rval;
+       }
+      else if (list == 0)
+       {
+         progcomp_flush ();
          return (EXECUTION_SUCCESS);
        }
       return (remove_cmd_completions (list));
     }
 
-  if (list == 0 && opt_given)
+  if (wl == 0 && list == 0 && opt_given)
     {
       builtin_usage ();
       return (EX_USAGE);
@@ -335,7 +413,7 @@ complete_builtin (list)
 
   /* If we get here, we need to build a compspec and add it for each
      remaining argument. */
-  cs = alloc_compspec ();
+  cs = compspec_create ();
   cs->actions = acts;
   cs->options = copts;
 
@@ -347,14 +425,14 @@ complete_builtin (list)
   cs->command = STRDUP (Carg);
   cs->filterpat = STRDUP (Xarg);
 
-  for (rval = EXECUTION_SUCCESS ; list; list = list->next)
+  for (rval = EXECUTION_SUCCESS, l = wl ? wl : list ; l; l = l->next)
     {
       /* Add CS as the compspec for the specified commands. */
-      cmd = list->word->word;
-      if (add_progcomp (cmd, cs) == 0)
+      if (progcomp_insert (l->word->word, cs) == 0)
        rval = EXECUTION_FAILURE;
     }
 
+  dispose_words (wl);
   return (rval);
 }
 
@@ -367,9 +445,9 @@ remove_cmd_completions (list)
 
   for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
     {
-      if (remove_progcomp (l->word->word) == 0)
+      if (progcomp_remove (l->word->word) == 0)
        {
-         builtin_error ("%s: no completion specification", l->word->word);
+         builtin_error (_("%s: no completion specification"), l->word->word);
          ret = EXECUTION_FAILURE;
        }
     }
@@ -410,7 +488,15 @@ remove_cmd_completions (list)
       printf ("-o %s ", f); \
   } while (0)
 
-static void
+#define XPRINTCOMPOPT(a, f) \
+  do { \
+    if (copts & a) \
+      printf ("-o %s ", f); \
+    else \
+      printf ("+o %s ", f); \
+  } while (0)
+
+static int
 print_one_completion (cmd, cs)
      char *cmd;
      COMPSPEC *cs;
@@ -423,9 +509,12 @@ print_one_completion (cmd, cs)
   copts = cs->options;
 
   /* First, print the -o options. */
+  PRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault");
   PRINTCOMPOPT (COPT_DEFAULT, "default");
   PRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
   PRINTCOMPOPT (COPT_FILENAMES, "filenames");
+  PRINTCOMPOPT (COPT_NOSPACE, "nospace");
+  PRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs");
 
   acts = cs->actions;
 
@@ -437,8 +526,9 @@ print_one_completion (cmd, cs)
   PRINTOPT (CA_EXPORT, "-e");
   PRINTOPT (CA_FILE, "-f");
   PRINTOPT (CA_GROUP, "-g");
-  PRINTOPT (CA_KEYWORD, "-k");
   PRINTOPT (CA_JOB, "-j");
+  PRINTOPT (CA_KEYWORD, "-k");
+  PRINTOPT (CA_SERVICE, "-s");
   PRINTOPT (CA_USER, "-u");
   PRINTOPT (CA_VARIABLE, "-v");
 
@@ -465,17 +555,76 @@ print_one_completion (cmd, cs)
   SQPRINTARG (cs->suffix, "-S");
   SQPRINTARG (cs->filterpat, "-X");
 
+  SQPRINTARG (cs->command, "-C");
+
   /* simple arguments that don't require quoting */
   PRINTARG (cs->funcname, "-F");
-  PRINTARG (cs->command, "-C");
 
-  printf ("%s\n", cmd);
+  if (STREQ (cmd, EMPTYCMD))
+    printf ("-E\n");
+  else if (STREQ (cmd, DEFAULTCMD))
+    printf ("-D\n");
+  else
+    printf ("%s\n", cmd);
+
+  return (0);
+}
+
+static void
+print_compopts (cmd, cs, full)
+     const char *cmd;
+     COMPSPEC *cs;
+     int full;
+{
+  int copts;
+
+  printf ("compopt ");
+  copts = cs->options;
+
+  if (full)
+    {
+      XPRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault");
+      XPRINTCOMPOPT (COPT_DEFAULT, "default");
+      XPRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
+      XPRINTCOMPOPT (COPT_FILENAMES, "filenames");
+      XPRINTCOMPOPT (COPT_NOSPACE, "nospace");
+      XPRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs");
+    }
+  else
+    {
+      PRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault");
+      PRINTCOMPOPT (COPT_DEFAULT, "default");
+      PRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
+      PRINTCOMPOPT (COPT_FILENAMES, "filenames");
+      PRINTCOMPOPT (COPT_NOSPACE, "nospace");
+      PRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs");
+    }
+
+  if (STREQ (cmd, EMPTYCMD))
+    printf ("-E\n");
+  else if (STREQ (cmd, DEFAULTCMD))
+    printf ("-D\n");
+  else
+    printf ("%s\n", cmd);
+}
+
+static int
+print_compitem (item)
+     BUCKET_CONTENTS *item;
+{
+  COMPSPEC *cs;
+  char *cmd;
+
+  cmd = item->key;
+  cs = (COMPSPEC *)item->data;
+
+  return (print_one_completion (cmd, cs));
 }
 
 static void
 print_all_completions ()
 {
-  print_all_compspecs (print_one_completion);
+  progcomp_walk (print_compitem);
 }
 
 static int
@@ -488,26 +637,31 @@ print_cmd_completions (list)
 
   for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
     {
-      cs = find_compspec (l->word->word);
+      cs = progcomp_search (l->word->word);
       if (cs)
        print_one_completion (l->word->word, cs);
       else
        {
-         builtin_error ("%s: no completion specification", l->word->word);
+         builtin_error (_("%s: no completion specification"), l->word->word);
          ret = EXECUTION_FAILURE;
        }
     }
-  return (ret);
+
+  return (sh_chkwrite (ret));
 }
 
 $BUILTIN compgen
 $DEPENDS_ON PROGRAMMABLE_COMPLETION
 $FUNCTION compgen_builtin
-$SHORT_DOC compgen [-abcdefgjkvu] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [word]
-Display the possible completions depending on the options.  Intended
-to be used from within a shell function generating possible completions.
-If the optional WORD argument is supplied, matches against WORD are
-generated.
+$SHORT_DOC compgen [-abcdefgjksuv] [-o option]  [-A action] [-G globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
+Display possible completions depending on the options.
+
+Intended to be used from within a shell function generating possible
+completions.  If the optional WORD argument is supplied, matches against
+WORD are generated.
+
+Exit Status:
+Returns success unless an invalid option is supplied or an error occurs.
 $END
 
 int
@@ -518,18 +672,18 @@ compgen_builtin (list)
   unsigned long acts, copts;
   COMPSPEC *cs;
   STRINGLIST *sl;
-  char *word;
+  char *word, **matches;
 
   if (list == 0)
     return (EXECUTION_SUCCESS);
 
   acts = copts = (unsigned long)0L;
-  Aarg = Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
+  Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
   cs = (COMPSPEC *)NULL;
 
   /* Build the actions from the arguments.  Also sets the [A-Z]arg variables
      as a side effect if they are supplied as options. */
-  rval = build_actions (list, (int *)NULL, (int *)NULL, &acts, &copts);
+  rval = build_actions (list, (struct _optflags *)NULL, &acts, &copts);
   if (rval == EX_USAGE)
     return (rval);
   if (rval == EXECUTION_FAILURE)
@@ -540,12 +694,12 @@ compgen_builtin (list)
   word = (list && list->word) ? list->word->word : "";
 
   if (Farg)
-    internal_warning ("compgen: -F option may not work as you expect");
+    builtin_error (_("warning: -F option may not work as you expect"));
   if (Carg)
-    internal_warning ("compgen: -C option may not work as you expect");
+    builtin_error (_("warning: -C option may not work as you expect"));
 
   /* If we get here, we need to build a compspec and evaluate it. */
-  cs = alloc_compspec ();
+  cs = compspec_create ();
   cs->actions = acts;
   cs->options = copts;
   cs->refcount = 1;
@@ -559,17 +713,25 @@ compgen_builtin (list)
   cs->filterpat = STRDUP (Xarg);
 
   rval = EXECUTION_FAILURE;
-  sl = gen_compspec_completions (cs, "compgen", word, 0, 0);
+  sl = gen_compspec_completions (cs, "compgen", word, 0, 0, 0);
+
+  /* If the compspec wants the bash default completions, temporarily
+     turn off programmable completion and call the bash completion code. */
+  if ((sl == 0 || sl->list_len == 0) && (copts & COPT_BASHDEFAULT))
+    {
+      matches = bash_default_completion (word, 0, 0, 0, 0);
+      sl = completions_to_stringlist (matches);
+      strvec_dispose (matches);
+    }
 
   /* This isn't perfect, but it's the best we can do, given what readline
      exports from its set of completion utility functions. */
   if ((sl == 0 || sl->list_len == 0) && (copts & COPT_DEFAULT))
     {
-      char **matches;
-
       matches = rl_completion_matches (word, rl_filename_completion_function);
+      strlist_dispose (sl);
       sl = completions_to_stringlist (matches);
-      free_array (matches);
+      strvec_dispose (matches);
     }
 
   if (sl)
@@ -577,11 +739,133 @@ compgen_builtin (list)
       if (sl->list && sl->list_len)
        {
          rval = EXECUTION_SUCCESS;
-         print_stringlist (sl, (char *)NULL);
+         strlist_print (sl, (char *)NULL);
        }
-      free_stringlist (sl);
+      strlist_dispose (sl);
     }
 
-  free_compspec (cs);
+  compspec_dispose (cs);
   return (rval);
 }
+
+$BUILTIN compopt
+$DEPENDS_ON PROGRAMMABLE_COMPLETION
+$FUNCTION compopt_builtin
+$SHORT_DOC compopt [-o|+o option] [-DE] [name ...]
+Modify or display completion options.
+
+Modify the completion options for each NAME, or, if no NAMEs are supplied,
+the completion currently being executed.  If no OPTIONs are given, print
+the completion options for each NAME or the current completion specification.
+
+Options:
+       -o option       Set completion option OPTION for each NAME
+       -D              Change options for the "default" command completion
+       -E              Change options for the "empty" command completion
+
+Using `+o' instead of `-o' turns off the specified option.
+
+Arguments:
+
+Each NAME refers to a command for which a completion specification must
+have previously been defined using the `complete' builtin.  If no NAMEs
+are supplied, compopt must be called by a function currently generating
+completions, and the options for that currently-executing completion
+generator are modified.
+
+Exit Status:
+Returns success unless an invalid option is supplied or NAME does not
+have a completion specification defined.
+$END
+
+int
+compopt_builtin (list)
+     WORD_LIST *list;
+{
+  int opts_on, opts_off, *opts, opt, oind, ret, Dflag, Eflag;
+  WORD_LIST *l, *wl;
+  COMPSPEC *cs;
+
+  opts_on = opts_off = Eflag = Dflag = 0;
+  ret = EXECUTION_SUCCESS;
+
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "+o:DE")) != EOF)
+    {
+      opts = (list_opttype == '-') ? &opts_on : &opts_off;
+
+      switch (opt)
+       {
+       case 'o':
+         oind = find_compopt (list_optarg);
+         if (oind < 0)
+           {
+             sh_invalidoptname (list_optarg);
+             return (EX_USAGE);
+           }
+         *opts |= compopts[oind].optflag;
+         break;
+       case 'D':
+         Dflag = 1;
+         break;
+       case 'E':
+         Eflag = 1;
+         break;
+       default:
+         builtin_usage ();
+         return (EX_USAGE);
+       }
+    }
+  list = loptend;
+
+  wl = Dflag ? make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL)
+            : (Eflag ? make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL) : 0);
+
+  if (list == 0 && wl == 0)
+    {
+      if (RL_ISSTATE (RL_STATE_COMPLETING) == 0 || pcomp_curcs == 0)
+       {
+         builtin_error (_("not currently executing completion function"));
+         return (EXECUTION_FAILURE);
+       }
+      cs = pcomp_curcs;
+
+      if (opts_on == 0 && opts_off == 0)
+       {
+         print_compopts (pcomp_curcmd, cs, 1);
+          return (sh_chkwrite (ret));
+       }
+
+      /* Set the compspec options */
+      pcomp_set_compspec_options (cs, opts_on, 1);
+      pcomp_set_compspec_options (cs, opts_off, 0);
+
+      /* And change the readline variables the options control */
+      pcomp_set_readline_variables (opts_on, 1);
+      pcomp_set_readline_variables (opts_off, 0);
+
+      return (ret);
+    }
+
+  for (l = wl ? wl : list; l; l = l->next)
+    {
+      cs = progcomp_search (l->word->word);
+      if (cs == 0)
+       {
+         builtin_error (_("%s: no completion specification"), l->word->word);
+         ret = EXECUTION_FAILURE;
+         continue;
+       }
+      if (opts_on == 0 && opts_off == 0)
+       {
+         print_compopts (l->word->word, cs, 1);
+         continue;                     /* XXX -- fill in later */
+       }
+
+      /* Set the compspec options */
+      pcomp_set_compspec_options (cs, opts_on, 1);
+      pcomp_set_compspec_options (cs, opts_off, 0);
+    }
+
+  return (ret);
+}