1This file is complete.def, from which is created complete.c.
2It implements the builtins "complete", "compgen", and "compopt" in Bash.
3
4Copyright (C) 1999-2020 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
12
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with Bash.  If not, see <http://www.gnu.org/licenses/>.
20
21$PRODUCES complete.c
22
23$BUILTIN complete
24$DEPENDS_ON PROGRAMMABLE_COMPLETION
25$FUNCTION complete_builtin
26$SHORT_DOC complete [-abcdefgjksuv] [-pr] [-DEI] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]
27Specify how arguments are to be completed by Readline.
28
29For each NAME, specify how arguments are to be completed.  If no options
30are supplied, existing completion specifications are printed in a way that
31allows them to be reused as input.
32
33Options:
34  -p	print existing completion specifications in a reusable format
35  -r	remove a completion specification for each NAME, or, if no
36		NAMEs are supplied, all completion specifications
37  -D	apply the completions and actions as the default for commands
38		without any specific completion defined
39  -E	apply the completions and actions to "empty" commands --
40		completion attempted on a blank line
41  -I	apply the completions and actions to the initial (usually the
42		command) word
43
44When completion is attempted, the actions are applied in the order the
45uppercase-letter options are listed above. If multiple options are supplied,
46the -D option takes precedence over -E, and both take precedence over -I.
47
48Exit Status:
49Returns success unless an invalid option is supplied or an error occurs.
50$END
51
52#include <config.h>
53
54#include <stdio.h>
55
56#include "../bashtypes.h"
57
58#if defined (HAVE_UNISTD_H)
59#  include <unistd.h>
60#endif
61
62#include "../bashansi.h"
63#include "../bashintl.h"
64
65#include "../shell.h"
66#include "../builtins.h"
67#include "../pcomplete.h"
68#include "../bashline.h"
69
70#include "common.h"
71#include "bashgetopt.h"
72
73#include <readline/readline.h>
74
75#define STRDUP(x)       ((x) ? savestring (x) : (char *)NULL)
76
77/* Structure containing all the non-action (binary) options; filled in by
78   build_actions(). */
79struct _optflags {
80  int pflag;
81  int rflag;
82  int Dflag;
83  int Eflag;
84  int Iflag;
85};
86
87static int find_compact PARAMS((char *));
88static int find_compopt PARAMS((char *));
89
90static int build_actions PARAMS((WORD_LIST *, struct _optflags *, unsigned long *, unsigned long *));
91
92static int remove_cmd_completions PARAMS((WORD_LIST *));
93
94static int print_one_completion PARAMS((char *, COMPSPEC *));
95static int print_compitem PARAMS((BUCKET_CONTENTS *));
96static void print_compopts PARAMS((const char *, COMPSPEC *, int));
97static void print_all_completions PARAMS((void));
98static int print_cmd_completions PARAMS((WORD_LIST *));
99
100static void print_compoptions PARAMS((unsigned long, int));
101static void print_compactions PARAMS((unsigned long));
102static void print_arg PARAMS((const char *, const char *, int));
103static void print_cmd_name PARAMS((const char *));
104
105static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
106
107static const struct _compacts {
108  const char * const actname;
109  unsigned long actflag;
110  int actopt;
111} compacts[] = {
112  { "alias",     CA_ALIAS,     'a' },
113  { "arrayvar",  CA_ARRAYVAR,   0 },
114  { "binding",   CA_BINDING,    0 },
115  { "builtin",   CA_BUILTIN,   'b' },
116  { "command",   CA_COMMAND,   'c' },
117  { "directory", CA_DIRECTORY, 'd' },
118  { "disabled",  CA_DISABLED,   0 },
119  { "enabled",   CA_ENABLED,    0 },
120  { "export",    CA_EXPORT,    'e' },
121  { "file",      CA_FILE,      'f' },
122  { "function",  CA_FUNCTION,   0 },
123  { "helptopic", CA_HELPTOPIC,  0 },
124  { "hostname",  CA_HOSTNAME,   0 },
125  { "group",     CA_GROUP,     'g' },
126  { "job",       CA_JOB,       'j' },
127  { "keyword",   CA_KEYWORD,   'k' },
128  { "running",   CA_RUNNING,    0 },
129  { "service",   CA_SERVICE,   's' },
130  { "setopt",    CA_SETOPT,     0 },
131  { "shopt",     CA_SHOPT,      0 },
132  { "signal",    CA_SIGNAL,     0 },
133  { "stopped",   CA_STOPPED,    0 },
134  { "user",      CA_USER,      'u' },
135  { "variable",  CA_VARIABLE,  'v' },
136  { (char *)NULL, 0, 0 },
137};
138
139/* This should be a STRING_INT_ALIST */
140static const struct _compopt {
141  const char * const optname;
142  unsigned long optflag;
143} compopts[] = {
144  { "bashdefault", COPT_BASHDEFAULT },
145  { "default",	COPT_DEFAULT },
146  { "dirnames", COPT_DIRNAMES },
147  { "filenames",COPT_FILENAMES},
148  { "noquote", COPT_NOQUOTE },
149  { "nosort", COPT_NOSORT },
150  { "nospace",	COPT_NOSPACE },
151  { "plusdirs", COPT_PLUSDIRS },
152  { (char *)NULL, 0 },
153};
154
155static int
156find_compact (name)
157     char *name;
158{
159  register int i;
160
161  for (i = 0; compacts[i].actname; i++)
162    if (STREQ (name, compacts[i].actname))
163      return i;
164  return -1;
165}
166
167static int
168find_compopt (name)
169     char *name;
170{
171  register int i;
172
173  for (i = 0; compopts[i].optname; i++)
174    if (STREQ (name, compopts[i].optname))
175      return i;
176  return -1;
177}
178
179/* Build the actions and compspec options from the options specified in LIST.
180   ACTP is a pointer to an unsigned long in which to place the bitmap of
181   actions.  OPTP is a pointer to an unsigned long in which to place the
182   bitmap of compspec options (arguments to `-o').  PP, if non-null, gets 1
183   if -p is supplied; RP, if non-null, gets 1 if -r is supplied.
184   If either is null, the corresponding option generates an error.
185   This also sets variables corresponding to options that take arguments as
186   a side effect; the caller should ensure that those variables are set to
187   NULL before calling build_actions.  Return value:
188   	EX_USAGE = bad option
189   	EXECUTION_SUCCESS = some options supplied
190   	EXECUTION_FAILURE = no options supplied
191*/
192
193static int
194build_actions (list, flagp, actp, optp)
195     WORD_LIST *list;
196     struct _optflags *flagp;
197     unsigned long *actp, *optp;
198{
199  int opt, ind, opt_given;
200  unsigned long acts, copts;
201  WORD_DESC w;
202
203  acts = copts = (unsigned long)0L;
204  opt_given = 0;
205
206  reset_internal_getopt ();
207  while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:DEI")) != -1)
208    {
209      opt_given = 1;
210      switch (opt)
211	{
212	case 'r':
213	  if (flagp)
214	    {
215	      flagp->rflag = 1;
216	      break;
217	    }
218	  else
219	    {
220	      sh_invalidopt ("-r");
221	      builtin_usage ();
222	      return (EX_USAGE);
223	    }
224
225	case 'p':
226	  if (flagp)
227	    {
228	      flagp->pflag = 1;
229	      break;
230	    }
231	  else
232	    {
233	      sh_invalidopt ("-p");
234	      builtin_usage ();
235	      return (EX_USAGE);
236	    }
237
238	case 'a':
239	  acts |= CA_ALIAS;
240	  break;
241	case 'b':
242	  acts |= CA_BUILTIN;
243	  break;
244	case 'c':
245	  acts |= CA_COMMAND;
246	  break;
247	case 'd':
248	  acts |= CA_DIRECTORY;
249	  break;
250	case 'e':
251	  acts |= CA_EXPORT;
252	  break;
253	case 'f':
254	  acts |= CA_FILE;
255	  break;
256	case 'g':
257	  acts |= CA_GROUP;
258	  break;
259	case 'j':
260	  acts |= CA_JOB;
261	  break;
262	case 'k':
263	  acts |= CA_KEYWORD;
264	  break;
265	case 's':
266	  acts |= CA_SERVICE;
267	  break;
268	case 'u':
269	  acts |= CA_USER;
270	  break;
271	case 'v':
272	  acts |= CA_VARIABLE;
273	  break;
274	case 'o':
275	  ind = find_compopt (list_optarg);
276	  if (ind < 0)
277	    {
278	      sh_invalidoptname (list_optarg);
279	      return (EX_USAGE);
280	    }
281	  copts |= compopts[ind].optflag;
282	  break;
283	case 'A':
284	  ind = find_compact (list_optarg);
285	  if (ind < 0)
286	    {
287	      builtin_error (_("%s: invalid action name"), list_optarg);
288	      return (EX_USAGE);
289	    }
290	  acts |= compacts[ind].actflag;
291	  break;
292	case 'C':
293	  Carg = list_optarg;
294	  break;
295	case 'D':
296	  if (flagp)
297	    {
298	      flagp->Dflag = 1;
299	      break;
300	    }
301	  else
302	    {
303	      sh_invalidopt ("-D");
304	      builtin_usage ();
305	      return (EX_USAGE);
306	    }
307	case 'E':
308	  if (flagp)
309	    {
310	      flagp->Eflag = 1;
311	      break;
312	    }
313	  else
314	    {
315	      sh_invalidopt ("-E");
316	      builtin_usage ();
317	      return (EX_USAGE);
318	    }
319	case 'I':
320	  if (flagp)
321	    {
322	      flagp->Iflag = 1;
323	      break;
324	    }
325	  else
326	    {
327	      sh_invalidopt ("-I");
328	      builtin_usage ();
329	      return (EX_USAGE);
330	    }
331	case 'F':
332	  w.word = Farg = list_optarg;
333	  w.flags = 0;
334	  if (check_identifier (&w, posixly_correct) == 0 || strpbrk (Farg, shell_break_chars) != 0)
335	    {
336	      sh_invalidid (Farg);
337	      return (EX_USAGE);
338	    }
339	  break;
340	case 'G':
341	  Garg = list_optarg;
342	  break;
343	case 'P':
344	  Parg = list_optarg;
345	  break;
346	case 'S':
347	  Sarg = list_optarg;
348	  break;
349	case 'W':
350	  Warg = list_optarg;
351	  break;
352	case 'X':
353	  Xarg = list_optarg;
354	  break;
355	CASE_HELPOPT;
356	default:
357	  builtin_usage ();
358	  return (EX_USAGE);
359	}
360    }
361
362  *actp = acts;
363  *optp = copts;
364
365  return (opt_given ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
366}
367
368/* Add, remove, and display completion specifiers. */
369int
370complete_builtin (list)
371     WORD_LIST *list;
372{
373  int opt_given, rval;
374  unsigned long acts, copts;
375  COMPSPEC *cs;
376  struct _optflags oflags;
377  WORD_LIST *l, *wl;
378
379  if (list == 0)
380    {
381      print_all_completions ();
382      return (EXECUTION_SUCCESS);
383    }
384
385  opt_given = oflags.pflag = oflags.rflag = 0;
386  oflags.Dflag = oflags.Eflag = oflags.Iflag = 0;
387
388  acts = copts = (unsigned long)0L;
389  Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
390  cs = (COMPSPEC *)NULL;
391
392  /* Build the actions from the arguments.  Also sets the [A-Z]arg variables
393     as a side effect if they are supplied as options. */
394  rval = build_actions (list, &oflags, &acts, &copts);
395  if (rval == EX_USAGE)
396    return (rval);
397  opt_given = rval != EXECUTION_FAILURE;
398
399  list = loptend;
400
401  if (oflags.Dflag)
402    wl = make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL);
403  else if (oflags.Eflag)
404    wl = make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL);
405  else if (oflags.Iflag)
406    wl = make_word_list (make_bare_word (INITIALWORD), (WORD_LIST *)NULL);
407  else
408    wl = (WORD_LIST *)NULL;
409
410  /* -p overrides everything else */
411  if (oflags.pflag || (list == 0 && opt_given == 0))
412    {
413      if (wl)
414	{
415	  rval = print_cmd_completions (wl);
416	  dispose_words (wl);
417	  return rval;
418	}
419      else if (list == 0)
420	{
421	  print_all_completions ();
422	  return (EXECUTION_SUCCESS);
423	}
424      return (print_cmd_completions (list));
425    }
426
427  /* next, -r overrides everything else. */
428  if (oflags.rflag)
429    {
430      if (wl)
431	{
432	  rval = remove_cmd_completions (wl);
433	  dispose_words (wl);
434	  return rval;
435	}
436      else if (list == 0)
437	{
438	  progcomp_flush ();
439	  return (EXECUTION_SUCCESS);
440	}
441      return (remove_cmd_completions (list));
442    }
443
444  if (wl == 0 && list == 0 && opt_given)
445    {
446      builtin_usage ();
447      return (EX_USAGE);
448    }
449
450  /* If we get here, we need to build a compspec and add it for each
451     remaining argument. */
452  cs = compspec_create ();
453  cs->actions = acts;
454  cs->options = copts;
455
456  cs->globpat = STRDUP (Garg);
457  cs->words = STRDUP (Warg);
458  cs->prefix = STRDUP (Parg);
459  cs->suffix = STRDUP (Sarg);
460  cs->funcname = STRDUP (Farg);
461  cs->command = STRDUP (Carg);
462  cs->filterpat = STRDUP (Xarg);
463
464  for (rval = EXECUTION_SUCCESS, l = wl ? wl : list ; l; l = l->next)
465    {
466      /* Add CS as the compspec for the specified commands. */
467      if (progcomp_insert (l->word->word, cs) == 0)
468	rval = EXECUTION_FAILURE;
469    }
470
471  dispose_words (wl);
472  return (rval);
473}
474
475static int
476remove_cmd_completions (list)
477     WORD_LIST *list;
478{
479  WORD_LIST *l;
480  int ret;
481
482  for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
483    {
484      if (progcomp_remove (l->word->word) == 0)
485	{
486	  builtin_error (_("%s: no completion specification"), l->word->word);
487	  ret = EXECUTION_FAILURE;
488	}
489    }
490  return ret;
491}
492
493static void
494print_compoptions (copts, full)
495     unsigned long copts;
496     int full;
497{
498  const struct _compopt *co;
499
500  for (co = compopts; co->optname; co++)
501    if (copts & co->optflag)
502      printf ("-o %s ", co->optname);
503    else if (full)
504      printf ("+o %s ", co->optname);
505}
506
507static void
508print_compactions (acts)
509     unsigned long acts;
510{
511  const struct _compacts *ca;
512
513  /* simple flags first */
514  for (ca = compacts; ca->actname; ca++)
515    if (ca->actopt && (acts & ca->actflag))
516      printf ("-%c ", ca->actopt);
517
518  /* then the rest of the actions */
519  for (ca = compacts; ca->actname; ca++)
520    if (ca->actopt == 0 && (acts & ca->actflag))
521      printf ("-A %s ", ca->actname);
522}
523
524static void
525print_arg (arg, flag, quote)
526     const char *arg, *flag;
527     int quote;
528{
529  char *x;
530
531  if (arg)
532    {
533      x = quote ? sh_single_quote (arg) : (char *)arg;
534      printf ("%s %s ", flag, x);
535      if (x != arg)
536	free (x);
537    }
538}
539
540static void
541print_cmd_name (cmd)
542     const char *cmd;
543{
544  if (STREQ (cmd, DEFAULTCMD))
545    printf ("-D");
546  else if (STREQ (cmd, EMPTYCMD))
547    printf ("-E");
548  else if (STREQ (cmd, INITIALWORD))
549    printf ("-I");
550  else if (*cmd == 0)		/* XXX - can this happen? */
551    printf ("''");
552  else
553    printf ("%s", cmd);
554}
555
556static int
557print_one_completion (cmd, cs)
558     char *cmd;
559     COMPSPEC *cs;
560{
561  printf ("complete ");
562
563  print_compoptions (cs->options, 0);
564  print_compactions (cs->actions);
565
566  /* now the rest of the arguments */
567
568  /* arguments that require quoting */
569  print_arg (cs->globpat, "-G", 1);
570  print_arg (cs->words, "-W", 1);
571  print_arg (cs->prefix, "-P", 1);
572  print_arg (cs->suffix, "-S", 1);
573  print_arg (cs->filterpat, "-X", 1);
574
575  print_arg (cs->command, "-C", 1);
576
577  /* simple arguments that don't require quoting */
578  print_arg (cs->funcname, "-F", 0);
579
580  print_cmd_name (cmd);
581  printf ("\n");
582
583  return (0);
584}
585
586static void
587print_compopts (cmd, cs, full)
588     const char *cmd;
589     COMPSPEC *cs;
590     int full;
591{
592  printf ("compopt ");
593
594  print_compoptions (cs->options, full);
595  print_cmd_name (cmd);
596
597  printf ("\n");
598}
599
600static int
601print_compitem (item)
602     BUCKET_CONTENTS *item;
603{
604  COMPSPEC *cs;
605  char *cmd;
606
607  cmd = item->key;
608  cs = (COMPSPEC *)item->data;
609
610  return (print_one_completion (cmd, cs));
611}
612
613static void
614print_all_completions ()
615{
616  progcomp_walk (print_compitem);
617}
618
619static int
620print_cmd_completions (list)
621     WORD_LIST *list;
622{
623  WORD_LIST *l;
624  COMPSPEC *cs;
625  int ret;
626
627  for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
628    {
629      cs = progcomp_search (l->word->word);
630      if (cs)
631	print_one_completion (l->word->word, cs);
632      else
633	{
634	  builtin_error (_("%s: no completion specification"), l->word->word);
635	  ret = EXECUTION_FAILURE;
636	}
637    }
638
639  return (sh_chkwrite (ret));
640}
641
642$BUILTIN compgen
643$DEPENDS_ON PROGRAMMABLE_COMPLETION
644$FUNCTION compgen_builtin
645$SHORT_DOC compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
646Display possible completions depending on the options.
647
648Intended to be used from within a shell function generating possible
649completions.  If the optional WORD argument is supplied, matches against
650WORD are generated.
651
652Exit Status:
653Returns success unless an invalid option is supplied or an error occurs.
654$END
655
656int
657compgen_builtin (list)
658     WORD_LIST *list;
659{
660  int rval;
661  unsigned long acts, copts;
662  COMPSPEC *cs;
663  STRINGLIST *sl;
664  char *word, **matches;
665  char *old_line;
666  int old_ind;
667
668  if (list == 0)
669    return (EXECUTION_SUCCESS);
670
671  acts = copts = (unsigned long)0L;
672  Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
673  cs = (COMPSPEC *)NULL;
674
675  /* Build the actions from the arguments.  Also sets the [A-Z]arg variables
676     as a side effect if they are supplied as options. */
677  rval = build_actions (list, (struct _optflags *)NULL, &acts, &copts);
678  if (rval == EX_USAGE)
679    return (rval);
680  if (rval == EXECUTION_FAILURE)
681    return (EXECUTION_SUCCESS);
682
683  list = loptend;
684
685  word = (list && list->word) ? list->word->word : "";
686
687  if (Farg)
688    builtin_error (_("warning: -F option may not work as you expect"));
689  if (Carg)
690    builtin_error (_("warning: -C option may not work as you expect"));
691
692  /* If we get here, we need to build a compspec and evaluate it. */
693  cs = compspec_create ();
694  cs->actions = acts;
695  cs->options = copts;
696  cs->refcount = 1;
697
698  cs->globpat = STRDUP (Garg);
699  cs->words = STRDUP (Warg);
700  cs->prefix = STRDUP (Parg);
701  cs->suffix = STRDUP (Sarg);
702  cs->funcname = STRDUP (Farg);
703  cs->command = STRDUP (Carg);
704  cs->filterpat = STRDUP (Xarg);
705
706  rval = EXECUTION_FAILURE;
707
708  /* probably don't have to save these, just being safe */
709  old_line = pcomp_line;
710  old_ind = pcomp_ind;
711  pcomp_line = (char *)NULL;
712  pcomp_ind = 0;
713  sl = gen_compspec_completions (cs, "compgen", word, 0, 0, 0);
714  pcomp_line = old_line;
715  pcomp_ind = old_ind;
716
717  /* If the compspec wants the bash default completions, temporarily
718     turn off programmable completion and call the bash completion code. */
719  if ((sl == 0 || sl->list_len == 0) && (copts & COPT_BASHDEFAULT))
720    {
721      matches = bash_default_completion (word, 0, 0, 0, 0);
722      sl = completions_to_stringlist (matches);
723      strvec_dispose (matches);
724    }
725
726  /* This isn't perfect, but it's the best we can do, given what readline
727     exports from its set of completion utility functions. */
728  if ((sl == 0 || sl->list_len == 0) && (copts & COPT_DEFAULT))
729    {
730      matches = rl_completion_matches (word, rl_filename_completion_function);
731      strlist_dispose (sl);
732      sl = completions_to_stringlist (matches);
733      strvec_dispose (matches);
734    }
735
736  if (sl)
737    {
738      if (sl->list && sl->list_len)
739	{
740	  rval = EXECUTION_SUCCESS;
741	  strlist_print (sl, (char *)NULL);
742	}
743      strlist_dispose (sl);
744    }
745
746  compspec_dispose (cs);
747  return (rval);
748}
749
750$BUILTIN compopt
751$DEPENDS_ON PROGRAMMABLE_COMPLETION
752$FUNCTION compopt_builtin
753$SHORT_DOC compopt [-o|+o option] [-DEI] [name ...]
754Modify or display completion options.
755
756Modify the completion options for each NAME, or, if no NAMEs are supplied,
757the completion currently being executed.  If no OPTIONs are given, print
758the completion options for each NAME or the current completion specification.
759
760Options:
761	-o option	Set completion option OPTION for each NAME
762	-D		Change options for the "default" command completion
763	-E		Change options for the "empty" command completion
764	-I		Change options for completion on the initial word
765
766Using `+o' instead of `-o' turns off the specified option.
767
768Arguments:
769
770Each NAME refers to a command for which a completion specification must
771have previously been defined using the `complete' builtin.  If no NAMEs
772are supplied, compopt must be called by a function currently generating
773completions, and the options for that currently-executing completion
774generator are modified.
775
776Exit Status:
777Returns success unless an invalid option is supplied or NAME does not
778have a completion specification defined.
779$END
780
781int
782compopt_builtin (list)
783     WORD_LIST *list;
784{
785  int opts_on, opts_off, *opts, opt, oind, ret, Dflag, Eflag, Iflag;
786  WORD_LIST *l, *wl;
787  COMPSPEC *cs;
788
789  opts_on = opts_off = Eflag = Dflag = Iflag = 0;
790  ret = EXECUTION_SUCCESS;
791
792  reset_internal_getopt ();
793  while ((opt = internal_getopt (list, "+o:DEI")) != -1)
794    {
795      opts = (list_opttype == '-') ? &opts_on : &opts_off;
796
797      switch (opt)
798	{
799	case 'o':
800	  oind = find_compopt (list_optarg);
801	  if (oind < 0)
802	    {
803	      sh_invalidoptname (list_optarg);
804	      return (EX_USAGE);
805	    }
806	  *opts |= compopts[oind].optflag;
807	  break;
808	case 'D':
809	  Dflag = 1;
810	  break;
811	case 'E':
812	  Eflag = 1;
813	  break;
814	case 'I':
815	  Iflag = 1;
816	  break;
817	CASE_HELPOPT;
818	default:
819	  builtin_usage ();
820	  return (EX_USAGE);
821	}
822    }
823  list = loptend;
824
825  if (Dflag)
826    wl = make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL);
827  else if (Eflag)
828    wl = make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL);
829  else if (Iflag)
830    wl = make_word_list (make_bare_word (INITIALWORD), (WORD_LIST *)NULL);
831  else
832    wl = (WORD_LIST *)NULL;
833
834  if (list == 0 && wl == 0)
835    {
836      if (RL_ISSTATE (RL_STATE_COMPLETING) == 0 || pcomp_curcs == 0)
837	{
838	  builtin_error (_("not currently executing completion function"));
839	  return (EXECUTION_FAILURE);
840	}
841      cs = pcomp_curcs;
842
843      if (opts_on == 0 && opts_off == 0)
844	{
845	  print_compopts (pcomp_curcmd, cs, 1);
846          return (sh_chkwrite (ret));
847	}
848
849      /* Set the compspec options */
850      pcomp_set_compspec_options (cs, opts_on, 1);
851      pcomp_set_compspec_options (cs, opts_off, 0);
852
853      /* And change the readline variables the options control */
854      pcomp_set_readline_variables (opts_on, 1);
855      pcomp_set_readline_variables (opts_off, 0);
856
857      return (ret);
858    }
859
860  for (l = wl ? wl : list; l; l = l->next)
861    {
862      cs = progcomp_search (l->word->word);
863      if (cs == 0)
864	{
865	  builtin_error (_("%s: no completion specification"), l->word->word);
866	  ret = EXECUTION_FAILURE;
867	  continue;
868	}
869      if (opts_on == 0 && opts_off == 0)
870	{
871	  print_compopts (l->word->word, cs, 1);
872	  continue;			/* XXX -- fill in later */
873	}
874
875      /* Set the compspec options */
876      pcomp_set_compspec_options (cs, opts_on, 1);
877      pcomp_set_compspec_options (cs, opts_off, 0);
878    }
879
880  if (wl)
881    dispose_words (wl);
882
883  return (ret);
884}
885