improve of cmpl.
[bush.git] / src / pcomplete.c
blob6a4db41147403839e03a2c52f4bd7d96abc4251d
1 /* pcomplete.c - functions to generate lists of matches for programmable completion. */
3 /* Copyright (C) 1999-2020 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne Again SHell.
7 Bush is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bush is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
23 #if defined (PROGRAMMABLE_COMPLETION)
25 #include "bushtypes.h"
26 #include "posixstat.h"
28 #if defined (HAVE_UNISTD_H)
29 # include <unistd.h>
30 #endif
32 #include <signal.h>
34 #if defined (PREFER_STDARG)
35 # include <stdarg.h>
36 #else
37 # include <varargs.h>
38 #endif
40 #include "posixtime.h"
42 #include <stdio.h>
43 #include "bushansi.h"
44 #include "bushintl.h"
46 #include "shell.h"
47 #include "pcomplete.h"
48 #include "impl/alias.h"
49 #include "input/bushline.h"
50 #include "runner/execute_cmd.h"
51 #include "impl/pathexp.h"
53 #if defined (JOB_CONTROL)
54 # include "jobs.h"
55 #endif
57 #if !defined (NSIG)
58 # include "trap.h"
59 #endif
61 #include "shmbutil.h"
63 #include "builtins.h"
64 #include "builtins/common.h"
65 #include "builtins/builtext.h"
67 #include <glob/glob.h>
68 #include <glob/strmatch.h>
70 #include <readline/rlconf.h>
71 #include <readline/readline.h>
72 #include <readline/history.h>
74 #ifdef STRDUP
75 # undef STRDUP
76 #endif
77 #define STRDUP(x) ((x) ? savestring (x) : (char *)NULL)
79 typedef SHELL_VAR **SVFUNC ();
81 #ifndef HAVE_STRPBRK
82 extern char *strpbrk PARAMS((char *, char *));
83 #endif
85 extern STRING_INT_ALIST word_token_alist[];
86 extern char *signal_names[];
88 #if defined (DEBUG)
89 #if defined (PREFER_STDARG)
90 static void debug_printf (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
91 #endif
92 #endif /* DEBUG */
94 static int it_init_joblist PARAMS((ITEMLIST *, int));
96 static int it_init_aliases PARAMS((ITEMLIST *));
97 static int it_init_arrayvars PARAMS((ITEMLIST *));
98 static int it_init_bindings PARAMS((ITEMLIST *));
99 static int it_init_builtins PARAMS((ITEMLIST *));
100 static int it_init_disabled PARAMS((ITEMLIST *));
101 static int it_init_enabled PARAMS((ITEMLIST *));
102 static int it_init_exported PARAMS((ITEMLIST *));
103 static int it_init_functions PARAMS((ITEMLIST *));
104 static int it_init_helptopics PARAMS((ITEMLIST *));
105 static int it_init_hostnames PARAMS((ITEMLIST *));
106 static int it_init_jobs PARAMS((ITEMLIST *));
107 static int it_init_running PARAMS((ITEMLIST *));
108 static int it_init_stopped PARAMS((ITEMLIST *));
109 static int it_init_keywords PARAMS((ITEMLIST *));
110 static int it_init_signals PARAMS((ITEMLIST *));
111 static int it_init_variables PARAMS((ITEMLIST *));
112 static int it_init_setopts PARAMS((ITEMLIST *));
113 static int it_init_shopts PARAMS((ITEMLIST *));
115 static int shouldexp_filterpat PARAMS((char *));
116 static char *preproc_filterpat PARAMS((char *, const char *));
118 static void init_itemlist_from_varlist PARAMS((ITEMLIST *, SVFUNC *));
120 static STRINGLIST *gen_matches_from_itemlist PARAMS((ITEMLIST *, const char *));
121 static STRINGLIST *gen_action_completions PARAMS((COMPSPEC *, const char *));
122 static STRINGLIST *gen_globpat_matches PARAMS((COMPSPEC *, const char *));
123 static STRINGLIST *gen_wordlist_matches PARAMS((COMPSPEC *, const char *));
124 static STRINGLIST *gen_shell_function_matches PARAMS((COMPSPEC *, const char *,
125 const char *,
126 char *, int, WORD_LIST *,
127 int, int, int *));
128 static STRINGLIST *gen_command_matches PARAMS((COMPSPEC *, const char *,
129 const char *,
130 char *, int, WORD_LIST *,
131 int, int));
133 static STRINGLIST *gen_progcomp_completions PARAMS((const char *, const char *,
134 const char *,
135 int, int, int *, int *,
136 COMPSPEC **));
138 static char *pcomp_filename_completion_function PARAMS((const char *, int));
140 #if defined (ARRAY_VARS)
141 static SHELL_VAR *bind_comp_words PARAMS((WORD_LIST *));
142 #endif
143 static void bind_compfunc_variables PARAMS((char *, int, WORD_LIST *, int, int));
144 static void unbind_compfunc_variables PARAMS((int));
145 static WORD_LIST *build_arg_list PARAMS((char *, const char *, const char *, WORD_LIST *, int));
146 static WORD_LIST *command_line_to_word_list PARAMS((char *, int, int, int *, int *));
148 #ifdef DEBUG
149 static int progcomp_debug = 0;
150 #endif
152 int prog_completion_enabled = 1;
154 #ifdef ALIAS
155 int progcomp_alias = 0; /* unavailable to user code for now */
156 #endif
158 /* These are used to manage the arrays of strings for possible completions. */
159 ITEMLIST it_aliases = { 0, it_init_aliases, (STRINGLIST *)0 };
160 ITEMLIST it_arrayvars = { LIST_DYNAMIC, it_init_arrayvars, (STRINGLIST *)0 };
161 ITEMLIST it_bindings = { 0, it_init_bindings, (STRINGLIST *)0 };
162 ITEMLIST it_builtins = { 0, it_init_builtins, (STRINGLIST *)0 };
163 ITEMLIST it_commands = { LIST_DYNAMIC }; /* unused */
164 ITEMLIST it_directories = { LIST_DYNAMIC }; /* unused */
165 ITEMLIST it_disabled = { 0, it_init_disabled, (STRINGLIST *)0 };
166 ITEMLIST it_enabled = { 0, it_init_enabled, (STRINGLIST *)0 };
167 ITEMLIST it_exports = { LIST_DYNAMIC, it_init_exported, (STRINGLIST *)0 };
168 ITEMLIST it_files = { LIST_DYNAMIC }; /* unused */
169 ITEMLIST it_functions = { 0, it_init_functions, (STRINGLIST *)0 };
170 ITEMLIST it_helptopics = { 0, it_init_helptopics, (STRINGLIST *)0 };
171 ITEMLIST it_hostnames = { LIST_DYNAMIC, it_init_hostnames, (STRINGLIST *)0 };
172 ITEMLIST it_groups = { LIST_DYNAMIC }; /* unused */
173 ITEMLIST it_jobs = { LIST_DYNAMIC, it_init_jobs, (STRINGLIST *)0 };
174 ITEMLIST it_keywords = { 0, it_init_keywords, (STRINGLIST *)0 };
175 ITEMLIST it_running = { LIST_DYNAMIC, it_init_running, (STRINGLIST *)0 };
176 ITEMLIST it_services = { LIST_DYNAMIC }; /* unused */
177 ITEMLIST it_setopts = { 0, it_init_setopts, (STRINGLIST *)0 };
178 ITEMLIST it_shopts = { 0, it_init_shopts, (STRINGLIST *)0 };
179 ITEMLIST it_signals = { 0, it_init_signals, (STRINGLIST *)0 };
180 ITEMLIST it_stopped = { LIST_DYNAMIC, it_init_stopped, (STRINGLIST *)0 };
181 ITEMLIST it_users = { LIST_DYNAMIC }; /* unused */
182 ITEMLIST it_variables = { LIST_DYNAMIC, it_init_variables, (STRINGLIST *)0 };
184 COMPSPEC *pcomp_curcs;
185 const char *pcomp_curcmd;
186 const char *pcomp_curtxt;
188 char *pcomp_line;
189 int pcomp_ind;
191 #ifdef DEBUG
192 /* Debugging code */
193 static void
194 #if defined (PREFER_STDARG)
195 debug_printf (const char *format, ...)
196 #else
197 debug_printf (format, va_alist)
198 const char *format;
199 va_dcl
200 #endif
202 va_list args;
204 if (progcomp_debug == 0)
205 return;
207 SH_VA_START (args, format);
209 fprintf (stdout, "DEBUG: ");
210 vfprintf (stdout, format, args);
211 fprintf (stdout, "\n");
213 rl_on_new_line ();
215 va_end (args);
217 #endif
219 /* Functions to manage the item lists */
221 void
222 set_itemlist_dirty (it)
223 ITEMLIST *it;
225 it->flags |= LIST_DIRTY;
228 void
229 initialize_itemlist (itp)
230 ITEMLIST *itp;
232 (*itp->list_getter) (itp);
233 itp->flags |= LIST_INITIALIZED;
234 itp->flags &= ~LIST_DIRTY;
237 void
238 clean_itemlist (itp)
239 ITEMLIST *itp;
241 STRINGLIST *sl;
243 sl = itp->slist;
244 if (sl)
246 if ((itp->flags & (LIST_DONTFREEMEMBERS|LIST_DONTFREE)) == 0)
247 strvec_flush (sl->list);
248 if ((itp->flags & LIST_DONTFREE) == 0)
249 free (sl->list);
250 free (sl);
252 itp->slist = (STRINGLIST *)NULL;
253 itp->flags &= ~(LIST_DONTFREE|LIST_DONTFREEMEMBERS|LIST_INITIALIZED|LIST_DIRTY);
257 static int
258 shouldexp_filterpat (s)
259 char *s;
261 register char *p;
263 for (p = s; p && *p; p++)
265 if (*p == '\\')
266 p++;
267 else if (*p == '&')
268 return 1;
270 return 0;
273 /* Replace any instance of `&' in PAT with TEXT. Backslash may be used to
274 quote a `&' and inhibit substitution. Returns a new string. This just
275 calls stringlib.c:strcreplace(). */
276 static char *
277 preproc_filterpat (pat, text)
278 char *pat;
279 const char *text;
281 char *ret;
283 ret = strcreplace (pat, '&', text, 1);
284 return ret;
287 /* Remove any match of FILTERPAT from SL. A `&' in FILTERPAT is replaced by
288 TEXT. A leading `!' in FILTERPAT negates the pattern; in this case
289 any member of SL->list that does *not* match will be removed. This returns
290 a new STRINGLIST with the matching members of SL *copied*. Any
291 non-matching members of SL->list are *freed*. */
292 STRINGLIST *
293 filter_stringlist (sl, filterpat, text)
294 STRINGLIST *sl;
295 char *filterpat;
296 const char *text;
298 int i, m, not;
299 STRINGLIST *ret;
300 char *npat, *t;
302 if (sl == 0 || sl->list == 0 || sl->list_len == 0)
303 return sl;
305 npat = shouldexp_filterpat (filterpat) ? preproc_filterpat (filterpat, text) : filterpat;
307 #if defined (EXTENDED_GLOB)
308 not = (npat[0] == '!' && (extended_glob == 0 || npat[1] != '(')); /*)*/
309 #else
310 not = (npat[0] == '!');
311 #endif
312 t = not ? npat + 1 : npat;
314 ret = strlist_create (sl->list_size);
315 for (i = 0; i < sl->list_len; i++)
317 m = strmatch (t, sl->list[i], FNMATCH_EXTFLAG | FNMATCH_IGNCASE);
318 if ((not && m == FNM_NOMATCH) || (not == 0 && m != FNM_NOMATCH))
319 free (sl->list[i]);
320 else
321 ret->list[ret->list_len++] = sl->list[i];
324 ret->list[ret->list_len] = (char *)NULL;
325 if (npat != filterpat)
326 free (npat);
328 return ret;
331 /* Turn an array of strings returned by rl_completion_matches into a STRINGLIST.
332 This understands how rl_completion_matches sets matches[0] (the lcd of the
333 strings in the list, unless it's the only match). */
334 STRINGLIST *
335 completions_to_stringlist (matches)
336 char **matches;
338 STRINGLIST *sl;
339 int mlen, i, n;
341 mlen = (matches == 0) ? 0 : strvec_len (matches);
342 sl = strlist_create (mlen + 1);
344 if (matches == 0 || matches[0] == 0)
345 return sl;
347 if (matches[1] == 0)
349 sl->list[0] = STRDUP (matches[0]);
350 sl->list[sl->list_len = 1] = (char *)NULL;
351 return sl;
354 for (i = 1, n = 0; i < mlen; i++, n++)
355 sl->list[n] = STRDUP (matches[i]);
356 sl->list_len = n;
357 sl->list[n] = (char *)NULL;
359 return sl;
362 /* Functions to manage the various ITEMLISTs that we populate internally.
363 The caller is responsible for setting ITP->flags correctly. */
365 static int
366 it_init_aliases (itp)
367 ITEMLIST *itp;
369 #ifdef ALIAS
370 alias_t **alias_list;
371 register int i, n;
372 STRINGLIST *sl;
374 alias_list = all_aliases ();
375 if (alias_list == 0)
377 itp->slist = (STRINGLIST *)NULL;
378 return 0;
380 for (n = 0; alias_list[n]; n++)
382 sl = strlist_create (n+1);
383 for (i = 0; i < n; i++)
384 sl->list[i] = STRDUP (alias_list[i]->name);
385 sl->list[n] = (char *)NULL;
386 sl->list_size = sl->list_len = n;
387 itp->slist = sl;
388 #else
389 itp->slist = (STRINGLIST *)NULL;
390 #endif
391 free (alias_list);
392 return 1;
395 static void
396 init_itemlist_from_varlist (itp, svfunc)
397 ITEMLIST *itp;
398 SVFUNC *svfunc;
400 SHELL_VAR **vlist;
401 STRINGLIST *sl;
402 register int i, n;
404 vlist = (*svfunc) ();
405 if (vlist == 0)
407 itp->slist = (STRINGLIST *)NULL;
408 return;
410 for (n = 0; vlist[n]; n++)
412 sl = strlist_create (n+1);
413 for (i = 0; i < n; i++)
414 sl->list[i] = savestring (vlist[i]->name);
415 sl->list[sl->list_len = n] = (char *)NULL;
416 itp->slist = sl;
419 static int
420 it_init_arrayvars (itp)
421 ITEMLIST *itp;
423 #if defined (ARRAY_VARS)
424 init_itemlist_from_varlist (itp, all_array_variables);
425 return 1;
426 #else
427 return 0;
428 #endif
431 static int
432 it_init_bindings (itp)
433 ITEMLIST *itp;
435 char **blist;
436 STRINGLIST *sl;
438 /* rl_funmap_names allocates blist, but not its members */
439 blist = (char **)rl_funmap_names (); /* XXX fix const later */
440 sl = strlist_create (0);
441 sl->list = blist;
442 sl->list_size = 0;
443 sl->list_len = strvec_len (sl->list);
444 itp->flags |= LIST_DONTFREEMEMBERS;
445 itp->slist = sl;
447 return 0;
450 static int
451 it_init_builtins (itp)
452 ITEMLIST *itp;
454 STRINGLIST *sl;
455 register int i, n;
457 sl = strlist_create (num_shell_builtins);
458 for (i = n = 0; i < num_shell_builtins; i++)
459 if (shell_builtins[i].function)
460 sl->list[n++] = shell_builtins[i].name;
461 sl->list[sl->list_len = n] = (char *)NULL;
462 itp->flags |= LIST_DONTFREEMEMBERS;
463 itp->slist = sl;
464 return 0;
467 static int
468 it_init_enabled (itp)
469 ITEMLIST *itp;
471 STRINGLIST *sl;
472 register int i, n;
474 sl = strlist_create (num_shell_builtins);
475 for (i = n = 0; i < num_shell_builtins; i++)
477 if (shell_builtins[i].function && (shell_builtins[i].flags & BUILTIN_ENABLED))
478 sl->list[n++] = shell_builtins[i].name;
480 sl->list[sl->list_len = n] = (char *)NULL;
481 itp->flags |= LIST_DONTFREEMEMBERS;
482 itp->slist = sl;
483 return 0;
486 static int
487 it_init_disabled (itp)
488 ITEMLIST *itp;
490 STRINGLIST *sl;
491 register int i, n;
493 sl = strlist_create (num_shell_builtins);
494 for (i = n = 0; i < num_shell_builtins; i++)
496 if (shell_builtins[i].function && ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
497 sl->list[n++] = shell_builtins[i].name;
499 sl->list[sl->list_len = n] = (char *)NULL;
500 itp->flags |= LIST_DONTFREEMEMBERS;
501 itp->slist = sl;
502 return 0;
505 static int
506 it_init_exported (itp)
507 ITEMLIST *itp;
509 init_itemlist_from_varlist (itp, all_exported_variables);
510 return 0;
513 static int
514 it_init_functions (itp)
515 ITEMLIST *itp;
517 init_itemlist_from_varlist (itp, all_visible_functions);
518 return 0;
521 /* Like it_init_builtins, but includes everything the help builtin looks at,
522 not just builtins with an active implementing function. */
523 static int
524 it_init_helptopics (itp)
525 ITEMLIST *itp;
527 STRINGLIST *sl;
528 register int i, n;
530 sl = strlist_create (num_shell_builtins);
531 for (i = n = 0; i < num_shell_builtins; i++)
532 sl->list[n++] = shell_builtins[i].name;
533 sl->list[sl->list_len = n] = (char *)NULL;
534 itp->flags |= LIST_DONTFREEMEMBERS;
535 itp->slist = sl;
536 return 0;
539 static int
540 it_init_hostnames (itp)
541 ITEMLIST *itp;
543 STRINGLIST *sl;
545 sl = strlist_create (0);
546 sl->list = get_hostname_list ();
547 sl->list_len = sl->list ? strvec_len (sl->list) : 0;
548 sl->list_size = sl->list_len;
549 itp->slist = sl;
550 itp->flags |= LIST_DONTFREEMEMBERS|LIST_DONTFREE;
551 return 0;
554 static int
555 it_init_joblist (itp, jstate)
556 ITEMLIST *itp;
557 int jstate;
559 #if defined (JOB_CONTROL)
560 STRINGLIST *sl;
561 register int i;
562 register PROCESS *p;
563 char *s, *t;
564 JOB *j;
565 JOB_STATE ws; /* wanted state */
567 ws = JNONE;
568 if (jstate == 0)
569 ws = JRUNNING;
570 else if (jstate == 1)
571 ws = JSTOPPED;
573 sl = strlist_create (js.j_jobslots);
574 for (i = js.j_jobslots - 1; i >= 0; i--)
576 j = get_job_by_jid (i);
577 if (j == 0)
578 continue;
579 p = j->pipe;
580 if (jstate == -1 || JOBSTATE(i) == ws)
582 s = savestring (p->command);
583 t = strpbrk (s, " \t\n");
584 if (t)
585 *t = '\0';
586 sl->list[sl->list_len++] = s;
589 itp->slist = sl;
590 #else
591 itp->slist = (STRINGLIST *)NULL;
592 #endif
593 return 0;
596 static int
597 it_init_jobs (itp)
598 ITEMLIST *itp;
600 return (it_init_joblist (itp, -1));
603 static int
604 it_init_running (itp)
605 ITEMLIST *itp;
607 return (it_init_joblist (itp, 0));
610 static int
611 it_init_stopped (itp)
612 ITEMLIST *itp;
614 return (it_init_joblist (itp, 1));
617 static int
618 it_init_keywords (itp)
619 ITEMLIST *itp;
621 STRINGLIST *sl;
622 register int i, n;
624 for (n = 0; word_token_alist[n].word; n++)
626 sl = strlist_create (n);
627 for (i = 0; i < n; i++)
628 sl->list[i] = word_token_alist[i].word;
629 sl->list[sl->list_len = i] = (char *)NULL;
630 itp->flags |= LIST_DONTFREEMEMBERS;
631 itp->slist = sl;
632 return 0;
635 static int
636 it_init_signals (itp)
637 ITEMLIST *itp;
639 STRINGLIST *sl;
641 sl = strlist_create (0);
642 sl->list = signal_names;
643 sl->list_len = strvec_len (sl->list);
644 itp->flags |= LIST_DONTFREE;
645 itp->slist = sl;
646 return 0;
649 static int
650 it_init_variables (itp)
651 ITEMLIST *itp;
653 init_itemlist_from_varlist (itp, all_visible_variables);
654 return 0;
657 static int
658 it_init_setopts (itp)
659 ITEMLIST *itp;
661 STRINGLIST *sl;
663 sl = strlist_create (0);
664 sl->list = get_minus_o_opts ();
665 sl->list_len = strvec_len (sl->list);
666 itp->slist = sl;
667 itp->flags |= LIST_DONTFREEMEMBERS;
668 return 0;
671 static int
672 it_init_shopts (itp)
673 ITEMLIST *itp;
675 STRINGLIST *sl;
677 sl = strlist_create (0);
678 sl->list = get_shopt_options ();
679 sl->list_len = strvec_len (sl->list);
680 itp->slist = sl;
681 itp->flags |= LIST_DONTFREEMEMBERS;
682 return 0;
685 /* Generate a list of all matches for TEXT using the STRINGLIST in itp->slist
686 as the list of possibilities. If the itemlist has been marked dirty or
687 it should be regenerated every time, destroy the old STRINGLIST and make a
688 new one before trying the match. TEXT is dequoted before attempting a
689 match. */
690 static STRINGLIST *
691 gen_matches_from_itemlist (itp, text)
692 ITEMLIST *itp;
693 const char *text;
695 STRINGLIST *ret, *sl;
696 int tlen, i, n;
697 char *ntxt;
699 if ((itp->flags & (LIST_DIRTY|LIST_DYNAMIC)) ||
700 (itp->flags & LIST_INITIALIZED) == 0)
702 if (itp->flags & (LIST_DIRTY|LIST_DYNAMIC))
703 clean_itemlist (itp);
704 if ((itp->flags & LIST_INITIALIZED) == 0)
705 initialize_itemlist (itp);
707 if (itp->slist == 0)
708 return ((STRINGLIST *)NULL);
709 ret = strlist_create (itp->slist->list_len+1);
710 sl = itp->slist;
712 ntxt = bush_dequote_text (text);
713 tlen = STRLEN (ntxt);
715 for (i = n = 0; i < sl->list_len; i++)
717 if (tlen == 0 || STREQN (sl->list[i], ntxt, tlen))
718 ret->list[n++] = STRDUP (sl->list[i]);
720 ret->list[ret->list_len = n] = (char *)NULL;
722 FREE (ntxt);
723 return ret;
726 /* A wrapper for rl_filename_completion_function that dequotes the filename
727 before attempting completions. */
728 static char *
729 pcomp_filename_completion_function (text, state)
730 const char *text;
731 int state;
733 static char *dfn; /* dequoted filename */
734 int iscompgen, iscompleting;
736 if (state == 0)
738 FREE (dfn);
739 /* remove backslashes quoting special characters in filenames. */
740 /* There are roughly three paths we can follow to get here:
741 1. complete -f
742 2. compgen -f "$word" from a completion function
743 3. compgen -f "$word" from the command line
744 They all need to be handled.
746 In the first two cases, readline will run the filename dequoting
747 function in rl_filename_completion_function if it found a filename
748 quoting character in the word to be completed
749 (rl_completion_found_quote). We run the dequoting function here
750 if we're running compgen, we're not completing, and the
751 rl_filename_completion_function won't dequote the filename
752 (rl_completion_found_quote == 0). */
753 iscompgen = this_shell_builtin == compgen_builtin;
754 iscompleting = RL_ISSTATE (RL_STATE_COMPLETING);
755 if (iscompgen && iscompleting == 0 && rl_completion_found_quote == 0
756 && rl_filename_dequoting_function)
758 /* Use rl_completion_quote_character because any single or
759 double quotes have been removed by the time TEXT makes it
760 here, and we don't want to remove backslashes inside
761 quoted strings. */
762 dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
764 /* Intended to solve a mismatched assumption by bush-completion. If
765 the text to be completed is empty, but bush-completion turns it into
766 a quoted string ('') assuming that this code will dequote it before
767 calling readline, do the dequoting. */
768 else if (iscompgen && iscompleting &&
769 pcomp_curtxt && *pcomp_curtxt == 0 &&
770 text && (*text == '\'' || *text == '"') && text[1] == text[0] && text[2] == 0 &&
771 rl_filename_dequoting_function)
772 dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
773 /* Another mismatched assumption by bush-completion. If compgen is being
774 run as part of bush-completion, and the argument to compgen is not
775 the same as the word originally passed to the programmable completion
776 code, dequote the argument if it has quote characters. It's an
777 attempt to detect when bush-completion is quoting its filename
778 argument before calling compgen. */
779 /* We could check whether gen_shell_function_matches is in the call
780 stack by checking whether the gen-shell-function-matches tag is in
781 the unwind-protect stack, but there's no function to do that yet.
782 We could simply check whether we're executing in a function by
783 checking variable_context, and may end up doing that. */
784 else if (iscompgen && iscompleting && rl_filename_dequoting_function &&
785 pcomp_curtxt && text &&
786 STREQ (pcomp_curtxt, text) == 0 &&
787 variable_context &&
788 sh_contains_quotes (text)) /* guess */
789 dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
790 else
791 dfn = savestring (text);
794 return (rl_filename_completion_function (dfn, state));
797 #define GEN_COMPS(bmap, flag, it, text, glist, tlist) \
798 do { \
799 if (bmap & flag) \
801 tlist = gen_matches_from_itemlist (it, text); \
802 if (tlist) \
804 glist = strlist_append (glist, tlist); \
805 strlist_dispose (tlist); \
808 } while (0)
810 #define GEN_XCOMPS(bmap, flag, text, func, cmatches, glist, tlist) \
811 do { \
812 if (bmap & flag) \
814 cmatches = rl_completion_matches (text, func); \
815 tlist = completions_to_stringlist (cmatches); \
816 glist = strlist_append (glist, tlist); \
817 strvec_dispose (cmatches); \
818 strlist_dispose (tlist); \
820 } while (0)
822 /* Functions to generate lists of matches from the actions member of CS. */
824 static STRINGLIST *
825 gen_action_completions (cs, text)
826 COMPSPEC *cs;
827 const char *text;
829 STRINGLIST *ret, *tmatches;
830 char **cmatches; /* from rl_completion_matches ... */
831 unsigned long flags;
832 int t;
834 ret = tmatches = (STRINGLIST *)NULL;
835 flags = cs->actions;
837 GEN_COMPS (flags, CA_ALIAS, &it_aliases, text, ret, tmatches);
838 GEN_COMPS (flags, CA_ARRAYVAR, &it_arrayvars, text, ret, tmatches);
839 GEN_COMPS (flags, CA_BINDING, &it_bindings, text, ret, tmatches);
840 GEN_COMPS (flags, CA_BUILTIN, &it_builtins, text, ret, tmatches);
841 GEN_COMPS (flags, CA_DISABLED, &it_disabled, text, ret, tmatches);
842 GEN_COMPS (flags, CA_ENABLED, &it_enabled, text, ret, tmatches);
843 GEN_COMPS (flags, CA_EXPORT, &it_exports, text, ret, tmatches);
844 GEN_COMPS (flags, CA_FUNCTION, &it_functions, text, ret, tmatches);
845 GEN_COMPS (flags, CA_HELPTOPIC, &it_helptopics, text, ret, tmatches);
846 GEN_COMPS (flags, CA_HOSTNAME, &it_hostnames, text, ret, tmatches);
847 GEN_COMPS (flags, CA_JOB, &it_jobs, text, ret, tmatches);
848 GEN_COMPS (flags, CA_KEYWORD, &it_keywords, text, ret, tmatches);
849 GEN_COMPS (flags, CA_RUNNING, &it_running, text, ret, tmatches);
850 GEN_COMPS (flags, CA_SETOPT, &it_setopts, text, ret, tmatches);
851 GEN_COMPS (flags, CA_SHOPT, &it_shopts, text, ret, tmatches);
852 GEN_COMPS (flags, CA_SIGNAL, &it_signals, text, ret, tmatches);
853 GEN_COMPS (flags, CA_STOPPED, &it_stopped, text, ret, tmatches);
854 GEN_COMPS (flags, CA_VARIABLE, &it_variables, text, ret, tmatches);
856 GEN_XCOMPS(flags, CA_COMMAND, text, command_word_completion_function, cmatches, ret, tmatches);
857 GEN_XCOMPS(flags, CA_FILE, text, pcomp_filename_completion_function, cmatches, ret, tmatches);
858 GEN_XCOMPS(flags, CA_USER, text, rl_username_completion_function, cmatches, ret, tmatches);
859 GEN_XCOMPS(flags, CA_GROUP, text, bush_groupname_completion_function, cmatches, ret, tmatches);
860 GEN_XCOMPS(flags, CA_SERVICE, text, bush_servicename_completion_function, cmatches, ret, tmatches);
862 /* And lastly, the special case for directories */
863 if (flags & CA_DIRECTORY)
865 t = rl_filename_completion_desired;
866 rl_completion_mark_symlink_dirs = 1; /* override user preference */
867 cmatches = bush_directory_completion_matches (text);
868 /* If we did not want filename completion before this, and there are
869 no matches, turn off rl_filename_completion_desired so whatever
870 matches we get are not treated as filenames (it gets turned on by
871 rl_filename_completion_function unconditionally). */
872 if (t == 0 && cmatches == 0 && rl_filename_completion_desired == 1)
873 rl_filename_completion_desired = 0;
874 tmatches = completions_to_stringlist (cmatches);
875 ret = strlist_append (ret, tmatches);
876 strvec_dispose (cmatches);
877 strlist_dispose (tmatches);
880 return ret;
883 /* Generate a list of matches for CS->globpat. Unresolved: should this use
884 TEXT as a match prefix, or just go without? Currently, the code does not
885 use TEXT, just globs CS->globpat and returns the results. If we do decide
886 to use TEXT, we should call quote_string_for_globbing before the call to
887 glob_filename. */
888 static STRINGLIST *
889 gen_globpat_matches (cs, text)
890 COMPSPEC *cs;
891 const char *text;
893 STRINGLIST *sl;
895 sl = strlist_create (0);
896 sl->list = glob_filename (cs->globpat, 0);
897 if (GLOB_FAILED (sl->list))
898 sl->list = (char **)NULL;
899 if (sl->list)
900 sl->list_len = sl->list_size = strvec_len (sl->list);
901 return sl;
904 /* Perform the shell word expansions on CS->words and return the results.
905 Again, this ignores TEXT. */
906 static STRINGLIST *
907 gen_wordlist_matches (cs, text)
908 COMPSPEC *cs;
909 const char *text;
911 WORD_LIST *l, *l2;
912 STRINGLIST *sl;
913 int nw, tlen;
914 char *ntxt; /* dequoted TEXT to use in comparisons */
916 if (cs->words == 0 || cs->words[0] == '\0')
917 return ((STRINGLIST *)NULL);
919 /* This used to be a simple expand_string(cs->words, 0), but that won't
920 do -- there's no way to split a simple list into individual words
921 that way, since the shell semantics say that word splitting is done
922 only on the results of expansion. split_at_delims also handles embedded
923 quoted strings and preserves the quotes for the expand_words_shellexp
924 function call that follows. */
925 /* XXX - this is where this function spends most of its time */
926 l = split_at_delims (cs->words, strlen (cs->words), (char *)NULL, -1, 0, (int *)NULL, (int *)NULL);
927 if (l == 0)
928 return ((STRINGLIST *)NULL);
929 /* This will jump back to the top level if the expansion fails... */
930 l2 = expand_words_shellexp (l);
931 dispose_words (l);
933 nw = list_length (l2);
934 sl = strlist_create (nw + 1);
936 ntxt = bush_dequote_text (text);
937 tlen = STRLEN (ntxt);
939 for (nw = 0, l = l2; l; l = l->next)
941 if (tlen == 0 || STREQN (l->word->word, ntxt, tlen))
942 sl->list[nw++] = STRDUP (l->word->word);
944 sl->list[sl->list_len = nw] = (char *)NULL;
946 dispose_words (l2);
947 FREE (ntxt);
948 return sl;
951 #ifdef ARRAY_VARS
953 static SHELL_VAR *
954 bind_comp_words (lwords)
955 WORD_LIST *lwords;
957 SHELL_VAR *v;
959 v = find_variable_noref ("COMP_WORDS");
960 if (v == 0)
961 v = make_new_array_variable ("COMP_WORDS");
962 if (nameref_p (v))
963 VUNSETATTR (v, att_nameref);
964 #if 0
965 if (readonly_p (v))
966 VUNSETATTR (v, att_readonly);
967 #endif
968 if (array_p (v) == 0)
969 v = convert_var_to_array (v);
970 v = assign_array_var_from_word_list (v, lwords, 0);
972 VUNSETATTR (v, att_invisible);
973 return v;
975 #endif /* ARRAY_VARS */
977 static void
978 bind_compfunc_variables (line, ind, lwords, cw, exported)
979 char *line;
980 int ind;
981 WORD_LIST *lwords;
982 int cw, exported;
984 char ibuf[INT_STRLEN_BOUND(int) + 1];
985 char *value;
986 SHELL_VAR *v;
987 size_t llen;
988 int c;
990 /* Set the variables that the function expects while it executes. Maybe
991 these should be in the function environment (temporary_env). */
992 v = bind_variable ("COMP_LINE", line, 0);
993 if (v && exported)
994 VSETATTR(v, att_exported);
996 /* Post bush-4.2: COMP_POINT is characters instead of bytes. */
997 c = line[ind];
998 line[ind] = '\0';
999 llen = MB_STRLEN (line);
1000 line[ind] = c;
1001 value = inttostr (llen, ibuf, sizeof(ibuf));
1002 v = bind_int_variable ("COMP_POINT", value, 0);
1003 if (v && exported)
1004 VSETATTR(v, att_exported);
1006 value = inttostr (rl_completion_type, ibuf, sizeof (ibuf));
1007 v = bind_int_variable ("COMP_TYPE", value, 0);
1008 if (v && exported)
1009 VSETATTR(v, att_exported);
1011 value = inttostr (rl_completion_invoking_key, ibuf, sizeof (ibuf));
1012 v = bind_int_variable ("COMP_KEY", value, 0);
1013 if (v && exported)
1014 VSETATTR(v, att_exported);
1016 /* Since array variables can't be exported, we don't bother making the
1017 array of words. */
1018 if (exported == 0)
1020 #ifdef ARRAY_VARS
1021 v = bind_comp_words (lwords);
1022 value = inttostr (cw, ibuf, sizeof(ibuf));
1023 bind_int_variable ("COMP_CWORD", value, 0);
1024 #endif
1026 else
1027 array_needs_making = 1;
1030 static void
1031 unbind_compfunc_variables (exported)
1032 int exported;
1034 unbind_variable_noref ("COMP_LINE");
1035 unbind_variable_noref ("COMP_POINT");
1036 unbind_variable_noref ("COMP_TYPE");
1037 unbind_variable_noref ("COMP_KEY");
1038 #ifdef ARRAY_VARS
1039 unbind_variable_noref ("COMP_WORDS");
1040 unbind_variable_noref ("COMP_CWORD");
1041 #endif
1042 if (exported)
1043 array_needs_making = 1;
1046 /* Build the list of words to pass to a function or external command
1047 as arguments. When the function or command is invoked,
1049 $0 == function or command being invoked
1050 $1 == command name
1051 $2 == word to be completed (possibly null)
1052 $3 == previous word
1054 Functions can access all of the words in the current command line
1055 with the COMP_WORDS array. External commands cannot; they have to
1056 make do with the COMP_LINE and COMP_POINT variables. */
1058 static WORD_LIST *
1059 build_arg_list (cmd, cname, text, lwords, ind)
1060 char *cmd;
1061 const char *cname;
1062 const char *text;
1063 WORD_LIST *lwords;
1064 int ind;
1066 WORD_LIST *ret, *cl, *l;
1067 WORD_DESC *w;
1068 int i;
1070 ret = (WORD_LIST *)NULL;
1071 w = make_word (cmd);
1072 ret = make_word_list (w, (WORD_LIST *)NULL); /* $0 */
1074 w = make_word (cname); /* $1 */
1075 cl = ret->next = make_word_list (w, (WORD_LIST *)NULL);
1077 w = make_word (text);
1078 cl->next = make_word_list (w, (WORD_LIST *)NULL); /* $2 */
1079 cl = cl->next;
1081 /* Search lwords for current word */
1082 for (l = lwords, i = 1; l && i < ind-1; l = l->next, i++)
1084 w = (l && l->word) ? copy_word (l->word) : make_word ("");
1085 cl->next = make_word_list (w, (WORD_LIST *)NULL);
1087 return ret;
1090 /* Build a command string with
1091 $0 == cs->funcname (function to execute for completion list)
1092 $1 == command name (command being completed)
1093 $2 = word to be completed (possibly null)
1094 $3 = previous word
1095 and run in the current shell. The function should put its completion
1096 list into the array variable COMPREPLY. We build a STRINGLIST
1097 from the results and return it.
1099 Since the shell function should return its list of matches in an array
1100 variable, this does nothing if arrays are not compiled into the shell. */
1102 static STRINGLIST *
1103 gen_shell_function_matches (cs, cmd, text, line, ind, lwords, nw, cw, foundp)
1104 COMPSPEC *cs;
1105 const char *cmd;
1106 const char *text;
1107 char *line;
1108 int ind;
1109 WORD_LIST *lwords;
1110 int nw, cw;
1111 int *foundp;
1113 char *funcname;
1114 STRINGLIST *sl;
1115 SHELL_VAR *f, *v;
1116 WORD_LIST *cmdlist;
1117 int fval, found;
1118 sh_parser_state_t ps;
1119 sh_parser_state_t * restrict pps;
1120 #if defined (ARRAY_VARS)
1121 ARRAY *a;
1122 #endif
1124 found = 0;
1125 if (foundp)
1126 *foundp = found;
1128 funcname = cs->funcname;
1129 f = find_function (funcname);
1130 if (f == 0)
1132 internal_error (_("completion: function `%s' not found"), funcname);
1133 rl_ding ();
1134 rl_on_new_line ();
1135 return ((STRINGLIST *)NULL);
1138 #if !defined (ARRAY_VARS)
1139 return ((STRINGLIST *)NULL);
1140 #else
1142 /* We pass cw - 1 because command_line_to_word_list returns indices that are
1143 1-based, while bush arrays are 0-based. */
1144 bind_compfunc_variables (line, ind, lwords, cw - 1, 0);
1146 cmdlist = build_arg_list (funcname, cmd, text, lwords, cw);
1148 pps = &ps;
1149 save_parser_state (pps);
1150 begin_unwind_frame ("gen-shell-function-matches");
1151 add_unwind_protect (restore_parser_state, (char *)pps);
1152 add_unwind_protect (dispose_words, (char *)cmdlist);
1153 add_unwind_protect (unbind_compfunc_variables, (char *)0);
1155 fval = execute_shell_function (f, cmdlist);
1157 discard_unwind_frame ("gen-shell-function-matches");
1158 restore_parser_state (pps);
1160 found = fval != EX_NOTFOUND;
1161 if (fval == EX_RETRYFAIL)
1162 found |= PCOMP_RETRYFAIL;
1163 if (foundp)
1164 *foundp = found;
1166 /* Now clean up and destroy everything. */
1167 dispose_words (cmdlist);
1168 unbind_compfunc_variables (0);
1170 /* The list of completions is returned in the array variable COMPREPLY. */
1171 v = find_variable ("COMPREPLY");
1172 if (v == 0)
1173 return ((STRINGLIST *)NULL);
1174 if (array_p (v) == 0 && assoc_p (v) == 0)
1175 v = convert_var_to_array (v);
1177 VUNSETATTR (v, att_invisible);
1179 a = array_cell (v);
1180 if (found == 0 || (found & PCOMP_RETRYFAIL) || a == 0 || array_p (v) == 0 || array_empty (a))
1181 sl = (STRINGLIST *)NULL;
1182 else
1184 /* XXX - should we filter the list of completions so only those matching
1185 TEXT are returned? Right now, we do not. */
1186 sl = strlist_create (0);
1187 sl->list = array_to_argv (a, 0);
1188 sl->list_len = sl->list_size = array_num_elements (a);
1191 /* XXX - should we unbind COMPREPLY here? */
1192 unbind_variable_noref ("COMPREPLY");
1194 return (sl);
1195 #endif
1198 /* Build a command string with
1199 $0 == cs->command (command to execute for completion list)
1200 $1 == command name (command being completed)
1201 $2 == word to be completed (possibly null)
1202 $3 == previous word
1203 and run it with command substitution. Parse the results, one word
1204 per line, with backslashes allowed to escape newlines. Build a
1205 STRINGLIST from the results and return it. */
1207 static STRINGLIST *
1208 gen_command_matches (cs, cmd, text, line, ind, lwords, nw, cw)
1209 COMPSPEC *cs;
1210 const char *cmd;
1211 const char *text;
1212 char *line;
1213 int ind;
1214 WORD_LIST *lwords;
1215 int nw, cw;
1217 char *csbuf, *cscmd, *t;
1218 int cmdlen, cmdsize, n, ws, we;
1219 WORD_LIST *cmdlist, *cl;
1220 WORD_DESC *tw;
1221 STRINGLIST *sl;
1223 bind_compfunc_variables (line, ind, lwords, cw, 1);
1224 cmdlist = build_arg_list (cs->command, cmd, text, lwords, cw);
1226 /* Estimate the size needed for the buffer. */
1227 n = strlen (cs->command);
1228 cmdsize = n + 1;
1229 for (cl = cmdlist->next; cl; cl = cl->next)
1230 cmdsize += STRLEN (cl->word->word) + 3;
1231 cmdsize += 2;
1233 /* allocate the string for the command and fill it in. */
1234 cscmd = (char *)xmalloc (cmdsize + 1);
1236 strcpy (cscmd, cs->command); /* $0 */
1237 cmdlen = n;
1238 cscmd[cmdlen++] = ' ';
1239 for (cl = cmdlist->next; cl; cl = cl->next) /* $1, $2, $3, ... */
1241 t = sh_single_quote (cl->word->word ? cl->word->word : "");
1242 n = strlen (t);
1243 RESIZE_MALLOCED_BUFFER (cscmd, cmdlen, n + 2, cmdsize, 64);
1244 strcpy (cscmd + cmdlen, t);
1245 cmdlen += n;
1246 if (cl->next)
1247 cscmd[cmdlen++] = ' ';
1248 free (t);
1250 cscmd[cmdlen] = '\0';
1252 tw = command_substitute (cscmd, 0, 0);
1253 csbuf = tw ? tw->word : (char *)NULL;
1254 if (tw)
1255 dispose_word_desc (tw);
1257 /* Now clean up and destroy everything. */
1258 dispose_words (cmdlist);
1259 free (cscmd);
1260 unbind_compfunc_variables (1);
1262 if (csbuf == 0 || *csbuf == '\0')
1264 FREE (csbuf);
1265 return ((STRINGLIST *)NULL);
1268 /* Now break CSBUF up at newlines, with backslash allowed to escape a
1269 newline, and put the individual words into a STRINGLIST. */
1270 sl = strlist_create (16);
1271 for (ws = 0; csbuf[ws]; )
1273 we = ws;
1274 while (csbuf[we] && csbuf[we] != '\n')
1276 if (csbuf[we] == '\\' && csbuf[we+1] == '\n')
1277 we++;
1278 we++;
1280 t = substring (csbuf, ws, we);
1281 if (sl->list_len >= sl->list_size - 1)
1282 strlist_resize (sl, sl->list_size + 16);
1283 sl->list[sl->list_len++] = t;
1284 while (csbuf[we] == '\n') we++;
1285 ws = we;
1287 sl->list[sl->list_len] = (char *)NULL;
1289 free (csbuf);
1290 return (sl);
1293 static WORD_LIST *
1294 command_line_to_word_list (line, llen, sentinel, nwp, cwp)
1295 char *line;
1296 int llen, sentinel, *nwp, *cwp;
1298 WORD_LIST *ret;
1299 char *delims;
1301 #if 0
1302 delims = "()<>;&| \t\n"; /* shell metacharacters break words */
1303 #else
1304 delims = rl_completer_word_break_characters;
1305 #endif
1306 ret = split_at_delims (line, llen, delims, sentinel, SD_NOQUOTEDELIM|SD_COMPLETE, nwp, cwp);
1307 return (ret);
1310 /* Evaluate COMPSPEC *cs and return all matches for WORD. */
1312 STRINGLIST *
1313 gen_compspec_completions (cs, cmd, word, start, end, foundp)
1314 COMPSPEC *cs;
1315 const char *cmd;
1316 const char *word;
1317 int start, end;
1318 int *foundp;
1320 STRINGLIST *ret, *tmatches;
1321 char *line;
1322 int llen, nw, cw, found, foundf;
1323 WORD_LIST *lwords;
1324 WORD_DESC *lw;
1325 COMPSPEC *tcs;
1327 found = 1;
1329 #ifdef DEBUG
1330 debug_printf ("gen_compspec_completions (%s, %s, %d, %d)", cmd, word, start, end);
1331 debug_printf ("gen_compspec_completions: %s -> %p", cmd, cs);
1332 #endif
1333 ret = gen_action_completions (cs, word);
1334 #ifdef DEBUG
1335 if (ret && progcomp_debug)
1337 debug_printf ("gen_action_completions (%p, %s) -->", cs, word);
1338 strlist_print (ret, "\t");
1339 rl_on_new_line ();
1341 #endif
1343 /* Now we start generating completions based on the other members of CS. */
1344 if (cs->globpat)
1346 tmatches = gen_globpat_matches (cs, word);
1347 if (tmatches)
1349 #ifdef DEBUG
1350 if (progcomp_debug)
1352 debug_printf ("gen_globpat_matches (%p, %s) -->", cs, word);
1353 strlist_print (tmatches, "\t");
1354 rl_on_new_line ();
1356 #endif
1357 ret = strlist_append (ret, tmatches);
1358 strlist_dispose (tmatches);
1359 rl_filename_completion_desired = 1;
1363 if (cs->words)
1365 tmatches = gen_wordlist_matches (cs, word);
1366 if (tmatches)
1368 #ifdef DEBUG
1369 if (progcomp_debug)
1371 debug_printf ("gen_wordlist_matches (%p, %s) -->", cs, word);
1372 strlist_print (tmatches, "\t");
1373 rl_on_new_line ();
1375 #endif
1376 ret = strlist_append (ret, tmatches);
1377 strlist_dispose (tmatches);
1381 lwords = (WORD_LIST *)NULL;
1382 line = (char *)NULL;
1383 if (cs->command || cs->funcname)
1385 /* If we have a command or function to execute, we need to first break
1386 the command line into individual words, find the number of words,
1387 and find the word in the list containing the word to be completed. */
1388 line = substring (pcomp_line, start, end);
1389 llen = end - start;
1391 #ifdef DEBUG
1392 debug_printf ("command_line_to_word_list (%s, %d, %d, %p, %p)",
1393 line, llen, pcomp_ind - start, &nw, &cw);
1394 #endif
1395 lwords = command_line_to_word_list (line, llen, pcomp_ind - start, &nw, &cw);
1396 /* If we skipped a NULL word at the beginning of the line, add it back */
1397 if (lwords && lwords->word && cmd[0] == 0 && lwords->word->word[0] != 0)
1399 lw = make_bare_word (cmd);
1400 lwords = make_word_list (lw, lwords);
1401 nw++;
1402 cw++;
1404 #ifdef DEBUG
1405 if (lwords == 0 && llen > 0)
1406 debug_printf ("ERROR: command_line_to_word_list returns NULL");
1407 else if (progcomp_debug)
1409 debug_printf ("command_line_to_word_list -->");
1410 printf ("\t");
1411 print_word_list (lwords, "!");
1412 printf ("\n");
1413 fflush(stdout);
1414 rl_on_new_line ();
1416 #endif
1419 if (cs->funcname)
1421 foundf = 0;
1422 tmatches = gen_shell_function_matches (cs, cmd, word, line, pcomp_ind - start, lwords, nw, cw, &foundf);
1423 if (foundf != 0)
1424 found = foundf;
1425 if (tmatches)
1427 #ifdef DEBUG
1428 if (progcomp_debug)
1430 debug_printf ("gen_shell_function_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
1431 strlist_print (tmatches, "\t");
1432 rl_on_new_line ();
1434 #endif
1435 ret = strlist_append (ret, tmatches);
1436 strlist_dispose (tmatches);
1440 if (cs->command)
1442 tmatches = gen_command_matches (cs, cmd, word, line, pcomp_ind - start, lwords, nw, cw);
1443 if (tmatches)
1445 #ifdef DEBUG
1446 if (progcomp_debug)
1448 debug_printf ("gen_command_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
1449 strlist_print (tmatches, "\t");
1450 rl_on_new_line ();
1452 #endif
1453 ret = strlist_append (ret, tmatches);
1454 strlist_dispose (tmatches);
1458 if (cs->command || cs->funcname)
1460 if (lwords)
1461 dispose_words (lwords);
1462 FREE (line);
1465 if (foundp)
1466 *foundp = found;
1468 if (found == 0 || (found & PCOMP_RETRYFAIL))
1470 strlist_dispose (ret);
1471 return NULL;
1474 if (cs->filterpat)
1476 tmatches = filter_stringlist (ret, cs->filterpat, word);
1477 #ifdef DEBUG
1478 if (progcomp_debug)
1480 debug_printf ("filter_stringlist (%p, %s, %s) -->", ret, cs->filterpat, word);
1481 strlist_print (tmatches, "\t");
1482 rl_on_new_line ();
1484 #endif
1485 if (ret && ret != tmatches)
1487 FREE (ret->list);
1488 free (ret);
1490 ret = tmatches;
1493 if (cs->prefix || cs->suffix)
1494 ret = strlist_prefix_suffix (ret, cs->prefix, cs->suffix);
1496 /* If no matches have been generated and the user has specified that
1497 directory completion should be done as a default, call
1498 gen_action_completions again to generate a list of matching directory
1499 names. */
1500 if ((ret == 0 || ret->list_len == 0) && (cs->options & COPT_DIRNAMES))
1502 tcs = compspec_create ();
1503 tcs->actions = CA_DIRECTORY;
1504 FREE (ret);
1505 ret = gen_action_completions (tcs, word);
1506 compspec_dispose (tcs);
1508 else if (cs->options & COPT_PLUSDIRS)
1510 tcs = compspec_create ();
1511 tcs->actions = CA_DIRECTORY;
1512 tmatches = gen_action_completions (tcs, word);
1513 ret = strlist_append (ret, tmatches);
1514 strlist_dispose (tmatches);
1515 compspec_dispose (tcs);
1518 return (ret);
1521 void
1522 pcomp_set_readline_variables (flags, nval)
1523 int flags, nval;
1525 /* If the user specified that the compspec returns filenames, make
1526 sure that readline knows it. */
1527 if (flags & COPT_FILENAMES)
1528 rl_filename_completion_desired = nval;
1529 /* If the user doesn't want a space appended, tell readline. */
1530 if (flags & COPT_NOSPACE)
1531 rl_completion_suppress_append = nval;
1532 /* The value here is inverted, since the default is on and the `noquote'
1533 option is supposed to turn it off */
1534 if (flags & COPT_NOQUOTE)
1535 rl_filename_quoting_desired = 1 - nval;
1536 if (flags & COPT_NOSORT)
1537 rl_sort_completion_matches = 1 - nval;
1540 /* Set or unset FLAGS in the options word of the current compspec.
1541 SET_OR_UNSET is 1 for setting, 0 for unsetting. */
1542 void
1543 pcomp_set_compspec_options (cs, flags, set_or_unset)
1544 COMPSPEC *cs;
1545 int flags, set_or_unset;
1547 if (cs == 0 && ((cs = pcomp_curcs) == 0))
1548 return;
1549 if (set_or_unset)
1550 cs->options |= flags;
1551 else
1552 cs->options &= ~flags;
1555 static STRINGLIST *
1556 gen_progcomp_completions (ocmd, cmd, word, start, end, foundp, retryp, lastcs)
1557 const char *ocmd;
1558 const char *cmd;
1559 const char *word;
1560 int start, end;
1561 int *foundp, *retryp;
1562 COMPSPEC **lastcs;
1564 COMPSPEC *cs, *oldcs;
1565 const char *oldcmd, *oldtxt;
1566 STRINGLIST *ret;
1568 cs = progcomp_search (ocmd);
1570 if (cs == 0 || cs == *lastcs)
1572 #if 0
1573 if (foundp)
1574 *foundp = 0;
1575 #endif
1576 return (NULL);
1579 if (*lastcs)
1580 compspec_dispose (*lastcs);
1581 cs->refcount++; /* XXX */
1582 *lastcs = cs;
1584 cs = compspec_copy (cs);
1586 oldcs = pcomp_curcs;
1587 oldcmd = pcomp_curcmd;
1588 oldtxt = pcomp_curtxt;
1590 pcomp_curcs = cs;
1591 pcomp_curcmd = cmd;
1592 pcomp_curtxt = word;
1594 ret = gen_compspec_completions (cs, cmd, word, start, end, foundp);
1596 pcomp_curcs = oldcs;
1597 pcomp_curcmd = oldcmd;
1598 pcomp_curtxt = oldtxt;
1600 /* We need to conditionally handle setting *retryp here */
1601 if (retryp)
1602 *retryp = foundp && (*foundp & PCOMP_RETRYFAIL);
1604 if (foundp)
1606 *foundp &= ~PCOMP_RETRYFAIL;
1607 *foundp |= cs->options;
1610 compspec_dispose (cs);
1611 return ret;
1614 /* The driver function for the programmable completion code. Returns a list
1615 of matches for WORD, which is an argument to command CMD. START and END
1616 bound the command currently being completed in pcomp_line (usually
1617 rl_line_buffer). */
1618 char **
1619 programmable_completions (cmd, word, start, end, foundp)
1620 const char *cmd;
1621 const char *word;
1622 int start, end, *foundp;
1624 COMPSPEC *lastcs;
1625 STRINGLIST *ret;
1626 char **rmatches, *t;
1627 int found, retry, count;
1628 char *ocmd;
1629 int oend;
1630 #if defined (ALIAS)
1631 alias_t *al;
1632 #endif
1634 lastcs = 0;
1635 found = count = 0;
1637 pcomp_line = rl_line_buffer;
1638 pcomp_ind = rl_point;
1640 ocmd = (char *)cmd;
1641 oend = end;
1645 retry = 0;
1647 /* We look at the basename of CMD if the full command does not have
1648 an associated COMPSPEC. */
1649 ret = gen_progcomp_completions (ocmd, ocmd, word, start, oend, &found, &retry, &lastcs);
1650 if (found == 0)
1652 t = strrchr (ocmd, '/');
1653 if (t && *(++t))
1654 ret = gen_progcomp_completions (t, ocmd, word, start, oend, &found, &retry, &lastcs);
1657 if (found == 0)
1658 ret = gen_progcomp_completions (DEFAULTCMD, ocmd, word, start, oend, &found, &retry, &lastcs);
1660 #if defined (ALIAS)
1661 /* Look up any alias for CMD, try to gen completions for it */
1662 /* Look up the alias, find the value, build a new line replacing CMD
1663 with that value, offsetting PCOMP_IND and END appropriately, reset
1664 PCOMP_LINE to the new line and OCMD with the new command name, then
1665 call gen_progcomp_completions again. We could use alias_expand for
1666 this, but it does more (and less) than we need right now. */
1667 if (found == 0 && retry == 0 && progcomp_alias && (al = find_alias (ocmd)))
1669 char *ncmd, *nline, *ntxt;
1670 int ind, lendiff;
1671 size_t nlen, olen, llen;
1673 /* We found an alias for OCMD. Take the value and build a new line */
1674 ntxt = al->value;
1675 nlen = strlen (ntxt);
1676 if (nlen == 0)
1677 break;
1678 olen = strlen (ocmd);
1679 lendiff = nlen - olen; /* can be negative */
1680 llen = strlen (pcomp_line);
1682 nline = (char *)xmalloc (llen + lendiff + 1);
1683 if (start > 0)
1684 strncpy (nline, pcomp_line, start);
1685 strncpy (nline + start, ntxt, nlen);
1686 strcpy (nline + start + nlen, pcomp_line + start + olen);
1688 /* Find the first word of the alias value and use that as OCMD. We
1689 don't check the alias value to see whether it begins with a valid
1690 command name, so this can be fooled. */
1691 ind = skip_to_delim (ntxt, 0, "()<>;&| \t\n", SD_NOJMP|SD_COMPLETE);
1692 if (ind > 0)
1693 ncmd = substring (ntxt, 0, ind);
1694 else
1696 free (nline);
1697 break; /* will free pcomp_line and ocmd later */
1700 /* Adjust PCOMP_IND and OEND appropriately */
1701 pcomp_ind += lendiff;
1702 oend += lendiff;
1704 /* Set up values with new line. WORD stays the same. */
1705 if (ocmd != cmd)
1706 free (ocmd);
1707 if (pcomp_line != rl_line_buffer)
1708 free (pcomp_line);
1710 ocmd = ncmd;
1711 pcomp_line = nline;
1713 /* And go back and start over. */
1714 retry = 1;
1716 #endif /* ALIAS */
1718 count++;
1720 if (count > 32)
1722 internal_warning (_("programmable_completion: %s: possible retry loop"), cmd);
1723 break;
1726 while (retry);
1728 if (pcomp_line != rl_line_buffer)
1729 free (pcomp_line);
1730 if (ocmd != cmd)
1731 free (ocmd);
1733 if (ret)
1735 rmatches = ret->list;
1736 free (ret);
1738 else
1739 rmatches = (char **)NULL;
1741 if (foundp)
1742 *foundp = found;
1744 if (lastcs) /* XXX - should be while? */
1745 compspec_dispose (lastcs);
1747 /* XXX restore pcomp_line and pcomp_ind? */
1748 pcomp_line = rl_line_buffer;
1749 pcomp_ind = rl_point;
1751 return (rmatches);
1754 #endif /* PROGRAMMABLE_COMPLETION */