blob: 6940feb72b50e0f0bd5e035e4457edcf5321cdf1 [file] [log] [blame]
Dan Pasanenc6e37862014-10-02 14:08:59 -05001/* complete.c, created from complete.def. */
2#line 22 "./complete.def"
3
4#line 49 "./complete.def"
5
6#include <config.h>
7
8#include <stdio.h>
9
10#include "../bashtypes.h"
11
12#if defined (HAVE_UNISTD_H)
13# include <unistd.h>
14#endif
15
16#include "../bashansi.h"
17#include "../bashintl.h"
18
19#include "../shell.h"
20#include "../builtins.h"
21#include "../pcomplete.h"
22#include "../bashline.h"
23
24#include "common.h"
25#include "bashgetopt.h"
26
27#include <readline/readline.h>
28
29#define STRDUP(x) ((x) ? savestring (x) : (char *)NULL)
30
31/* Structure containing all the non-action (binary) options; filled in by
32 build_actions(). */
33struct _optflags {
34 int pflag;
35 int rflag;
36 int Dflag;
37 int Eflag;
38};
39
40static int find_compact __P((char *));
41static int find_compopt __P((char *));
42
43static int build_actions __P((WORD_LIST *, struct _optflags *, unsigned long *, unsigned long *));
44
45static int remove_cmd_completions __P((WORD_LIST *));
46
47static int print_one_completion __P((char *, COMPSPEC *));
48static int print_compitem __P((BUCKET_CONTENTS *));
49static void print_compopts __P((const char *, COMPSPEC *, int));
50static void print_all_completions __P((void));
51static int print_cmd_completions __P((WORD_LIST *));
52
53static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
54
55static const struct _compacts {
56 const char * const actname;
57 int actflag;
58 int actopt;
59} compacts[] = {
60 { "alias", CA_ALIAS, 'a' },
61 { "arrayvar", CA_ARRAYVAR, 0 },
62 { "binding", CA_BINDING, 0 },
63 { "builtin", CA_BUILTIN, 'b' },
64 { "command", CA_COMMAND, 'c' },
65 { "directory", CA_DIRECTORY, 'd' },
66 { "disabled", CA_DISABLED, 0 },
67 { "enabled", CA_ENABLED, 0 },
68 { "export", CA_EXPORT, 'e' },
69 { "file", CA_FILE, 'f' },
70 { "function", CA_FUNCTION, 0 },
71 { "helptopic", CA_HELPTOPIC, 0 },
72 { "hostname", CA_HOSTNAME, 0 },
73 { "group", CA_GROUP, 'g' },
74 { "job", CA_JOB, 'j' },
75 { "keyword", CA_KEYWORD, 'k' },
76 { "running", CA_RUNNING, 0 },
77 { "service", CA_SERVICE, 's' },
78 { "setopt", CA_SETOPT, 0 },
79 { "shopt", CA_SHOPT, 0 },
80 { "signal", CA_SIGNAL, 0 },
81 { "stopped", CA_STOPPED, 0 },
82 { "user", CA_USER, 'u' },
83 { "variable", CA_VARIABLE, 'v' },
84 { (char *)NULL, 0, 0 },
85};
86
87/* This should be a STRING_INT_ALIST */
88static const struct _compopt {
89 const char * const optname;
90 int optflag;
91} compopts[] = {
92 { "bashdefault", COPT_BASHDEFAULT },
93 { "default", COPT_DEFAULT },
94 { "dirnames", COPT_DIRNAMES },
95 { "filenames",COPT_FILENAMES},
96 { "noquote", COPT_NOQUOTE },
97 { "nospace", COPT_NOSPACE },
98 { "plusdirs", COPT_PLUSDIRS },
99 { (char *)NULL, 0 },
100};
101
102static int
103find_compact (name)
104 char *name;
105{
106 register int i;
107
108 for (i = 0; compacts[i].actname; i++)
109 if (STREQ (name, compacts[i].actname))
110 return i;
111 return -1;
112}
113
114static int
115find_compopt (name)
116 char *name;
117{
118 register int i;
119
120 for (i = 0; compopts[i].optname; i++)
121 if (STREQ (name, compopts[i].optname))
122 return i;
123 return -1;
124}
125
126/* Build the actions and compspec options from the options specified in LIST.
127 ACTP is a pointer to an unsigned long in which to place the bitmap of
128 actions. OPTP is a pointer to an unsigned long in which to place the
129 btmap of compspec options (arguments to `-o'). PP, if non-null, gets 1
130 if -p is supplied; RP, if non-null, gets 1 if -r is supplied.
131 If either is null, the corresponding option generates an error.
132 This also sets variables corresponding to options that take arguments as
133 a side effect; the caller should ensure that those variables are set to
134 NULL before calling build_actions. Return value:
135 EX_USAGE = bad option
136 EXECUTION_SUCCESS = some options supplied
137 EXECUTION_FAILURE = no options supplied
138*/
139
140static int
141build_actions (list, flagp, actp, optp)
142 WORD_LIST *list;
143 struct _optflags *flagp;
144 unsigned long *actp, *optp;
145{
146 int opt, ind, opt_given;
147 unsigned long acts, copts;
148
149 acts = copts = (unsigned long)0L;
150 opt_given = 0;
151
152 reset_internal_getopt ();
153 while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:DE")) != -1)
154 {
155 opt_given = 1;
156 switch (opt)
157 {
158 case 'r':
159 if (flagp)
160 {
161 flagp->rflag = 1;
162 break;
163 }
164 else
165 {
166 sh_invalidopt ("-r");
167 builtin_usage ();
168 return (EX_USAGE);
169 }
170
171 case 'p':
172 if (flagp)
173 {
174 flagp->pflag = 1;
175 break;
176 }
177 else
178 {
179 sh_invalidopt ("-p");
180 builtin_usage ();
181 return (EX_USAGE);
182 }
183
184 case 'a':
185 acts |= CA_ALIAS;
186 break;
187 case 'b':
188 acts |= CA_BUILTIN;
189 break;
190 case 'c':
191 acts |= CA_COMMAND;
192 break;
193 case 'd':
194 acts |= CA_DIRECTORY;
195 break;
196 case 'e':
197 acts |= CA_EXPORT;
198 break;
199 case 'f':
200 acts |= CA_FILE;
201 break;
202 case 'g':
203 acts |= CA_GROUP;
204 break;
205 case 'j':
206 acts |= CA_JOB;
207 break;
208 case 'k':
209 acts |= CA_KEYWORD;
210 break;
211 case 's':
212 acts |= CA_SERVICE;
213 break;
214 case 'u':
215 acts |= CA_USER;
216 break;
217 case 'v':
218 acts |= CA_VARIABLE;
219 break;
220 case 'o':
221 ind = find_compopt (list_optarg);
222 if (ind < 0)
223 {
224 sh_invalidoptname (list_optarg);
225 return (EX_USAGE);
226 }
227 copts |= compopts[ind].optflag;
228 break;
229 case 'A':
230 ind = find_compact (list_optarg);
231 if (ind < 0)
232 {
233 builtin_error (_("%s: invalid action name"), list_optarg);
234 return (EX_USAGE);
235 }
236 acts |= compacts[ind].actflag;
237 break;
238 case 'C':
239 Carg = list_optarg;
240 break;
241 case 'D':
242 if (flagp)
243 {
244 flagp->Dflag = 1;
245 break;
246 }
247 else
248 {
249 sh_invalidopt ("-D");
250 builtin_usage ();
251 return (EX_USAGE);
252 }
253 case 'E':
254 if (flagp)
255 {
256 flagp->Eflag = 1;
257 break;
258 }
259 else
260 {
261 sh_invalidopt ("-E");
262 builtin_usage ();
263 return (EX_USAGE);
264 }
265 case 'F':
266 Farg = list_optarg;
267 break;
268 case 'G':
269 Garg = list_optarg;
270 break;
271 case 'P':
272 Parg = list_optarg;
273 break;
274 case 'S':
275 Sarg = list_optarg;
276 break;
277 case 'W':
278 Warg = list_optarg;
279 break;
280 case 'X':
281 Xarg = list_optarg;
282 break;
283 default:
284 builtin_usage ();
285 return (EX_USAGE);
286 }
287 }
288
289 *actp = acts;
290 *optp = copts;
291
292 return (opt_given ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
293}
294
295/* Add, remove, and display completion specifiers. */
296int
297complete_builtin (list)
298 WORD_LIST *list;
299{
300 int opt_given, rval;
301 unsigned long acts, copts;
302 COMPSPEC *cs;
303 struct _optflags oflags;
304 WORD_LIST *l, *wl;
305
306 if (list == 0)
307 {
308 print_all_completions ();
309 return (EXECUTION_SUCCESS);
310 }
311
312 opt_given = oflags.pflag = oflags.rflag = oflags.Dflag = oflags.Eflag = 0;
313
314 acts = copts = (unsigned long)0L;
315 Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
316 cs = (COMPSPEC *)NULL;
317
318 /* Build the actions from the arguments. Also sets the [A-Z]arg variables
319 as a side effect if they are supplied as options. */
320 rval = build_actions (list, &oflags, &acts, &copts);
321 if (rval == EX_USAGE)
322 return (rval);
323 opt_given = rval != EXECUTION_FAILURE;
324
325 list = loptend;
326
327 wl = oflags.Dflag ? make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL)
328 : (oflags.Eflag ? make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL) : 0);
329
330 /* -p overrides everything else */
331 if (oflags.pflag || (list == 0 && opt_given == 0))
332 {
333 if (wl)
334 {
335 rval = print_cmd_completions (wl);
336 dispose_words (wl);
337 return rval;
338 }
339 else if (list == 0)
340 {
341 print_all_completions ();
342 return (EXECUTION_SUCCESS);
343 }
344 return (print_cmd_completions (list));
345 }
346
347 /* next, -r overrides everything else. */
348 if (oflags.rflag)
349 {
350 if (wl)
351 {
352 rval = remove_cmd_completions (wl);
353 dispose_words (wl);
354 return rval;
355 }
356 else if (list == 0)
357 {
358 progcomp_flush ();
359 return (EXECUTION_SUCCESS);
360 }
361 return (remove_cmd_completions (list));
362 }
363
364 if (wl == 0 && list == 0 && opt_given)
365 {
366 builtin_usage ();
367 return (EX_USAGE);
368 }
369
370 /* If we get here, we need to build a compspec and add it for each
371 remaining argument. */
372 cs = compspec_create ();
373 cs->actions = acts;
374 cs->options = copts;
375
376 cs->globpat = STRDUP (Garg);
377 cs->words = STRDUP (Warg);
378 cs->prefix = STRDUP (Parg);
379 cs->suffix = STRDUP (Sarg);
380 cs->funcname = STRDUP (Farg);
381 cs->command = STRDUP (Carg);
382 cs->filterpat = STRDUP (Xarg);
383
384 for (rval = EXECUTION_SUCCESS, l = wl ? wl : list ; l; l = l->next)
385 {
386 /* Add CS as the compspec for the specified commands. */
387 if (progcomp_insert (l->word->word, cs) == 0)
388 rval = EXECUTION_FAILURE;
389 }
390
391 dispose_words (wl);
392 return (rval);
393}
394
395static int
396remove_cmd_completions (list)
397 WORD_LIST *list;
398{
399 WORD_LIST *l;
400 int ret;
401
402 for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
403 {
404 if (progcomp_remove (l->word->word) == 0)
405 {
406 builtin_error (_("%s: no completion specification"), l->word->word);
407 ret = EXECUTION_FAILURE;
408 }
409 }
410 return ret;
411}
412
413#define SQPRINTARG(a, f) \
414 do { \
415 if (a) \
416 { \
417 x = sh_single_quote (a); \
418 printf ("%s %s ", f, x); \
419 free (x); \
420 } \
421 } while (0)
422
423#define PRINTARG(a, f) \
424 do { \
425 if (a) \
426 printf ("%s %s ", f, a); \
427 } while (0)
428
429#define PRINTOPT(a, f) \
430 do { \
431 if (acts & a) \
432 printf ("%s ", f); \
433 } while (0)
434
435#define PRINTACT(a, f) \
436 do { \
437 if (acts & a) \
438 printf ("-A %s ", f); \
439 } while (0)
440
441#define PRINTCOMPOPT(a, f) \
442 do { \
443 if (copts & a) \
444 printf ("-o %s ", f); \
445 } while (0)
446
447#define XPRINTCOMPOPT(a, f) \
448 do { \
449 if (copts & a) \
450 printf ("-o %s ", f); \
451 else \
452 printf ("+o %s ", f); \
453 } while (0)
454
455static int
456print_one_completion (cmd, cs)
457 char *cmd;
458 COMPSPEC *cs;
459{
460 unsigned long acts, copts;
461 char *x;
462
463 printf ("complete ");
464
465 copts = cs->options;
466
467 /* First, print the -o options. */
468 PRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault");
469 PRINTCOMPOPT (COPT_DEFAULT, "default");
470 PRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
471 PRINTCOMPOPT (COPT_FILENAMES, "filenames");
472 PRINTCOMPOPT (COPT_NOSPACE, "nospace");
473 PRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs");
474
475 acts = cs->actions;
476
477 /* simple flags next */
478 PRINTOPT (CA_ALIAS, "-a");
479 PRINTOPT (CA_BUILTIN, "-b");
480 PRINTOPT (CA_COMMAND, "-c");
481 PRINTOPT (CA_DIRECTORY, "-d");
482 PRINTOPT (CA_EXPORT, "-e");
483 PRINTOPT (CA_FILE, "-f");
484 PRINTOPT (CA_GROUP, "-g");
485 PRINTOPT (CA_JOB, "-j");
486 PRINTOPT (CA_KEYWORD, "-k");
487 PRINTOPT (CA_SERVICE, "-s");
488 PRINTOPT (CA_USER, "-u");
489 PRINTOPT (CA_VARIABLE, "-v");
490
491 /* now the rest of the actions */
492 PRINTACT (CA_ARRAYVAR, "arrayvar");
493 PRINTACT (CA_BINDING, "binding");
494 PRINTACT (CA_DISABLED, "disabled");
495 PRINTACT (CA_ENABLED, "enabled");
496 PRINTACT (CA_FUNCTION, "function");
497 PRINTACT (CA_HELPTOPIC, "helptopic");
498 PRINTACT (CA_HOSTNAME, "hostname");
499 PRINTACT (CA_RUNNING, "running");
500 PRINTACT (CA_SETOPT, "setopt");
501 PRINTACT (CA_SHOPT, "shopt");
502 PRINTACT (CA_SIGNAL, "signal");
503 PRINTACT (CA_STOPPED, "stopped");
504
505 /* now the rest of the arguments */
506
507 /* arguments that require quoting */
508 SQPRINTARG (cs->globpat, "-G");
509 SQPRINTARG (cs->words, "-W");
510 SQPRINTARG (cs->prefix, "-P");
511 SQPRINTARG (cs->suffix, "-S");
512 SQPRINTARG (cs->filterpat, "-X");
513
514 SQPRINTARG (cs->command, "-C");
515
516 /* simple arguments that don't require quoting */
517 PRINTARG (cs->funcname, "-F");
518
519 if (STREQ (cmd, EMPTYCMD))
520 printf ("-E\n");
521 else if (STREQ (cmd, DEFAULTCMD))
522 printf ("-D\n");
523 else
524 printf ("%s\n", cmd);
525
526 return (0);
527}
528
529static void
530print_compopts (cmd, cs, full)
531 const char *cmd;
532 COMPSPEC *cs;
533 int full;
534{
535 int copts;
536
537 printf ("compopt ");
538 copts = cs->options;
539
540 if (full)
541 {
542 XPRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault");
543 XPRINTCOMPOPT (COPT_DEFAULT, "default");
544 XPRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
545 XPRINTCOMPOPT (COPT_FILENAMES, "filenames");
546 XPRINTCOMPOPT (COPT_NOSPACE, "nospace");
547 XPRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs");
548 }
549 else
550 {
551 PRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault");
552 PRINTCOMPOPT (COPT_DEFAULT, "default");
553 PRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
554 PRINTCOMPOPT (COPT_FILENAMES, "filenames");
555 PRINTCOMPOPT (COPT_NOSPACE, "nospace");
556 PRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs");
557 }
558
559 if (STREQ (cmd, EMPTYCMD))
560 printf ("-E\n");
561 else if (STREQ (cmd, DEFAULTCMD))
562 printf ("-D\n");
563 else
564 printf ("%s\n", cmd);
565}
566
567static int
568print_compitem (item)
569 BUCKET_CONTENTS *item;
570{
571 COMPSPEC *cs;
572 char *cmd;
573
574 cmd = item->key;
575 cs = (COMPSPEC *)item->data;
576
577 return (print_one_completion (cmd, cs));
578}
579
580static void
581print_all_completions ()
582{
583 progcomp_walk (print_compitem);
584}
585
586static int
587print_cmd_completions (list)
588 WORD_LIST *list;
589{
590 WORD_LIST *l;
591 COMPSPEC *cs;
592 int ret;
593
594 for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
595 {
596 cs = progcomp_search (l->word->word);
597 if (cs)
598 print_one_completion (l->word->word, cs);
599 else
600 {
601 builtin_error (_("%s: no completion specification"), l->word->word);
602 ret = EXECUTION_FAILURE;
603 }
604 }
605
606 return (sh_chkwrite (ret));
607}
608
609#line 666 "./complete.def"
610
611int
612compgen_builtin (list)
613 WORD_LIST *list;
614{
615 int rval;
616 unsigned long acts, copts;
617 COMPSPEC *cs;
618 STRINGLIST *sl;
619 char *word, **matches;
620
621 if (list == 0)
622 return (EXECUTION_SUCCESS);
623
624 acts = copts = (unsigned long)0L;
625 Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
626 cs = (COMPSPEC *)NULL;
627
628 /* Build the actions from the arguments. Also sets the [A-Z]arg variables
629 as a side effect if they are supplied as options. */
630 rval = build_actions (list, (struct _optflags *)NULL, &acts, &copts);
631 if (rval == EX_USAGE)
632 return (rval);
633 if (rval == EXECUTION_FAILURE)
634 return (EXECUTION_SUCCESS);
635
636 list = loptend;
637
638 word = (list && list->word) ? list->word->word : "";
639
640 if (Farg)
641 builtin_error (_("warning: -F option may not work as you expect"));
642 if (Carg)
643 builtin_error (_("warning: -C option may not work as you expect"));
644
645 /* If we get here, we need to build a compspec and evaluate it. */
646 cs = compspec_create ();
647 cs->actions = acts;
648 cs->options = copts;
649 cs->refcount = 1;
650
651 cs->globpat = STRDUP (Garg);
652 cs->words = STRDUP (Warg);
653 cs->prefix = STRDUP (Parg);
654 cs->suffix = STRDUP (Sarg);
655 cs->funcname = STRDUP (Farg);
656 cs->command = STRDUP (Carg);
657 cs->filterpat = STRDUP (Xarg);
658
659 rval = EXECUTION_FAILURE;
660 sl = gen_compspec_completions (cs, "compgen", word, 0, 0, 0);
661
662 /* If the compspec wants the bash default completions, temporarily
663 turn off programmable completion and call the bash completion code. */
664 if ((sl == 0 || sl->list_len == 0) && (copts & COPT_BASHDEFAULT))
665 {
666 matches = bash_default_completion (word, 0, 0, 0, 0);
667 sl = completions_to_stringlist (matches);
668 strvec_dispose (matches);
669 }
670
671 /* This isn't perfect, but it's the best we can do, given what readline
672 exports from its set of completion utility functions. */
673 if ((sl == 0 || sl->list_len == 0) && (copts & COPT_DEFAULT))
674 {
675 matches = rl_completion_matches (word, rl_filename_completion_function);
676 strlist_dispose (sl);
677 sl = completions_to_stringlist (matches);
678 strvec_dispose (matches);
679 }
680
681 if (sl)
682 {
683 if (sl->list && sl->list_len)
684 {
685 rval = EXECUTION_SUCCESS;
686 strlist_print (sl, (char *)NULL);
687 }
688 strlist_dispose (sl);
689 }
690
691 compspec_dispose (cs);
692 return (rval);
693}
694
695#line 780 "./complete.def"
696
697int
698compopt_builtin (list)
699 WORD_LIST *list;
700{
701 int opts_on, opts_off, *opts, opt, oind, ret, Dflag, Eflag;
702 WORD_LIST *l, *wl;
703 COMPSPEC *cs;
704
705 opts_on = opts_off = Eflag = Dflag = 0;
706 ret = EXECUTION_SUCCESS;
707
708 reset_internal_getopt ();
709 while ((opt = internal_getopt (list, "+o:DE")) != EOF)
710 {
711 opts = (list_opttype == '-') ? &opts_on : &opts_off;
712
713 switch (opt)
714 {
715 case 'o':
716 oind = find_compopt (list_optarg);
717 if (oind < 0)
718 {
719 sh_invalidoptname (list_optarg);
720 return (EX_USAGE);
721 }
722 *opts |= compopts[oind].optflag;
723 break;
724 case 'D':
725 Dflag = 1;
726 break;
727 case 'E':
728 Eflag = 1;
729 break;
730 default:
731 builtin_usage ();
732 return (EX_USAGE);
733 }
734 }
735 list = loptend;
736
737 wl = Dflag ? make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL)
738 : (Eflag ? make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL) : 0);
739
740 if (list == 0 && wl == 0)
741 {
742 if (RL_ISSTATE (RL_STATE_COMPLETING) == 0 || pcomp_curcs == 0)
743 {
744 builtin_error (_("not currently executing completion function"));
745 return (EXECUTION_FAILURE);
746 }
747 cs = pcomp_curcs;
748
749 if (opts_on == 0 && opts_off == 0)
750 {
751 print_compopts (pcomp_curcmd, cs, 1);
752 return (sh_chkwrite (ret));
753 }
754
755 /* Set the compspec options */
756 pcomp_set_compspec_options (cs, opts_on, 1);
757 pcomp_set_compspec_options (cs, opts_off, 0);
758
759 /* And change the readline variables the options control */
760 pcomp_set_readline_variables (opts_on, 1);
761 pcomp_set_readline_variables (opts_off, 0);
762
763 return (ret);
764 }
765
766 for (l = wl ? wl : list; l; l = l->next)
767 {
768 cs = progcomp_search (l->word->word);
769 if (cs == 0)
770 {
771 builtin_error (_("%s: no completion specification"), l->word->word);
772 ret = EXECUTION_FAILURE;
773 continue;
774 }
775 if (opts_on == 0 && opts_off == 0)
776 {
777 print_compopts (l->word->word, cs, 1);
778 continue; /* XXX -- fill in later */
779 }
780
781 /* Set the compspec options */
782 pcomp_set_compspec_options (cs, opts_on, 1);
783 pcomp_set_compspec_options (cs, opts_off, 0);
784 }
785
786 return (ret);
787}