]> git.ipfire.org Git - thirdparty/bash.git/blob - pcomplete.c
Bash-4.3 patch 4
[thirdparty/bash.git] / pcomplete.c
1 /* pcomplete.c - functions to generate lists of matches for programmable completion. */
2
3 /* Copyright (C) 1999-2012 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
7 Bash 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.
11
12 Bash 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.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <config.h>
22
23 #if defined (PROGRAMMABLE_COMPLETION)
24
25 #include "bashtypes.h"
26 #include "posixstat.h"
27
28 #if defined (HAVE_UNISTD_H)
29 # include <unistd.h>
30 #endif
31
32 #include <signal.h>
33
34 #if defined (PREFER_STDARG)
35 # include <stdarg.h>
36 #else
37 # include <varargs.h>
38 #endif
39
40 #include <sys/time.h>
41
42 #include <stdio.h>
43 #include "bashansi.h"
44 #include "bashintl.h"
45
46 #include "shell.h"
47 #include "pcomplete.h"
48 #include "alias.h"
49 #include "bashline.h"
50 #include "execute_cmd.h"
51 #include "pathexp.h"
52
53 #if defined (JOB_CONTROL)
54 # include "jobs.h"
55 #endif
56
57 #if !defined (NSIG)
58 # include "trap.h"
59 #endif
60
61 #include "shmbutil.h"
62
63 #include "builtins.h"
64 #include "builtins/common.h"
65 #include "builtins/builtext.h"
66
67 #include <glob/glob.h>
68 #include <glob/strmatch.h>
69
70 #include <readline/rlconf.h>
71 #include <readline/readline.h>
72 #include <readline/history.h>
73
74 #define PCOMP_RETRYFAIL 256
75
76 #ifdef STRDUP
77 # undef STRDUP
78 #endif
79 #define STRDUP(x) ((x) ? savestring (x) : (char *)NULL)
80
81 typedef SHELL_VAR **SVFUNC ();
82
83 #ifndef HAVE_STRPBRK
84 extern char *strpbrk __P((char *, char *));
85 #endif
86
87 extern int array_needs_making;
88 extern STRING_INT_ALIST word_token_alist[];
89 extern char *signal_names[];
90 extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
91
92 #if defined (DEBUG)
93 #if defined (PREFER_STDARG)
94 static void debug_printf (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
95 #endif
96 #endif /* DEBUG */
97
98 static int it_init_joblist __P((ITEMLIST *, int));
99
100 static int it_init_aliases __P((ITEMLIST *));
101 static int it_init_arrayvars __P((ITEMLIST *));
102 static int it_init_bindings __P((ITEMLIST *));
103 static int it_init_builtins __P((ITEMLIST *));
104 static int it_init_disabled __P((ITEMLIST *));
105 static int it_init_enabled __P((ITEMLIST *));
106 static int it_init_exported __P((ITEMLIST *));
107 static int it_init_functions __P((ITEMLIST *));
108 static int it_init_helptopics __P((ITEMLIST *));
109 static int it_init_hostnames __P((ITEMLIST *));
110 static int it_init_jobs __P((ITEMLIST *));
111 static int it_init_running __P((ITEMLIST *));
112 static int it_init_stopped __P((ITEMLIST *));
113 static int it_init_keywords __P((ITEMLIST *));
114 static int it_init_signals __P((ITEMLIST *));
115 static int it_init_variables __P((ITEMLIST *));
116 static int it_init_setopts __P((ITEMLIST *));
117 static int it_init_shopts __P((ITEMLIST *));
118
119 static int shouldexp_filterpat __P((char *));
120 static char *preproc_filterpat __P((char *, char *));
121
122 static void init_itemlist_from_varlist __P((ITEMLIST *, SVFUNC *));
123
124 static STRINGLIST *gen_matches_from_itemlist __P((ITEMLIST *, const char *));
125 static STRINGLIST *gen_action_completions __P((COMPSPEC *, const char *));
126 static STRINGLIST *gen_globpat_matches __P((COMPSPEC *, const char *));
127 static STRINGLIST *gen_wordlist_matches __P((COMPSPEC *, const char *));
128 static STRINGLIST *gen_shell_function_matches __P((COMPSPEC *, const char *,
129 const char *,
130 char *, int, WORD_LIST *,
131 int, int, int *));
132 static STRINGLIST *gen_command_matches __P((COMPSPEC *, const char *,
133 const char *,
134 char *, int, WORD_LIST *,
135 int, int));
136
137 static STRINGLIST *gen_progcomp_completions __P((const char *, const char *,
138 const char *,
139 int, int, int *, int *,
140 COMPSPEC **));
141
142 static char *pcomp_filename_completion_function __P((const char *, int));
143
144 #if defined (ARRAY_VARS)
145 static SHELL_VAR *bind_comp_words __P((WORD_LIST *));
146 #endif
147 static void bind_compfunc_variables __P((char *, int, WORD_LIST *, int, int));
148 static void unbind_compfunc_variables __P((int));
149 static WORD_LIST *build_arg_list __P((char *, const char *, const char *, WORD_LIST *, int));
150 static WORD_LIST *command_line_to_word_list __P((char *, int, int, int *, int *));
151
152 #ifdef DEBUG
153 static int progcomp_debug = 0;
154 #endif
155
156 int prog_completion_enabled = 1;
157
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 };
183
184 COMPSPEC *pcomp_curcs;
185 const char *pcomp_curcmd;
186
187 #ifdef DEBUG
188 /* Debugging code */
189 static void
190 #if defined (PREFER_STDARG)
191 debug_printf (const char *format, ...)
192 #else
193 debug_printf (format, va_alist)
194 const char *format;
195 va_dcl
196 #endif
197 {
198 va_list args;
199
200 if (progcomp_debug == 0)
201 return;
202
203 SH_VA_START (args, format);
204
205 fprintf (stdout, "DEBUG: ");
206 vfprintf (stdout, format, args);
207 fprintf (stdout, "\n");
208
209 rl_on_new_line ();
210
211 va_end (args);
212 }
213 #endif
214
215 /* Functions to manage the item lists */
216
217 void
218 set_itemlist_dirty (it)
219 ITEMLIST *it;
220 {
221 it->flags |= LIST_DIRTY;
222 }
223
224 void
225 initialize_itemlist (itp)
226 ITEMLIST *itp;
227 {
228 (*itp->list_getter) (itp);
229 itp->flags |= LIST_INITIALIZED;
230 itp->flags &= ~LIST_DIRTY;
231 }
232
233 void
234 clean_itemlist (itp)
235 ITEMLIST *itp;
236 {
237 STRINGLIST *sl;
238
239 sl = itp->slist;
240 if (sl)
241 {
242 if ((itp->flags & (LIST_DONTFREEMEMBERS|LIST_DONTFREE)) == 0)
243 strvec_flush (sl->list);
244 if ((itp->flags & LIST_DONTFREE) == 0)
245 free (sl->list);
246 free (sl);
247 }
248 itp->slist = (STRINGLIST *)NULL;
249 itp->flags &= ~(LIST_DONTFREE|LIST_DONTFREEMEMBERS|LIST_INITIALIZED|LIST_DIRTY);
250 }
251
252
253 static int
254 shouldexp_filterpat (s)
255 char *s;
256 {
257 register char *p;
258
259 for (p = s; p && *p; p++)
260 {
261 if (*p == '\\')
262 p++;
263 else if (*p == '&')
264 return 1;
265 }
266 return 0;
267 }
268
269 /* Replace any instance of `&' in PAT with TEXT. Backslash may be used to
270 quote a `&' and inhibit substitution. Returns a new string. This just
271 calls stringlib.c:strcreplace(). */
272 static char *
273 preproc_filterpat (pat, text)
274 char *pat;
275 char *text;
276 {
277 char *ret;
278
279 ret = strcreplace (pat, '&', text, 1);
280 return ret;
281 }
282
283 /* Remove any match of FILTERPAT from SL. A `&' in FILTERPAT is replaced by
284 TEXT. A leading `!' in FILTERPAT negates the pattern; in this case
285 any member of SL->list that does *not* match will be removed. This returns
286 a new STRINGLIST with the matching members of SL *copied*. Any
287 non-matching members of SL->list are *freed*. */
288 STRINGLIST *
289 filter_stringlist (sl, filterpat, text)
290 STRINGLIST *sl;
291 char *filterpat, *text;
292 {
293 int i, m, not;
294 STRINGLIST *ret;
295 char *npat, *t;
296
297 if (sl == 0 || sl->list == 0 || sl->list_len == 0)
298 return sl;
299
300 npat = shouldexp_filterpat (filterpat) ? preproc_filterpat (filterpat, text) : filterpat;
301
302 not = (npat[0] == '!');
303 t = not ? npat + 1 : npat;
304
305 ret = strlist_create (sl->list_size);
306 for (i = 0; i < sl->list_len; i++)
307 {
308 m = strmatch (t, sl->list[i], FNMATCH_EXTFLAG);
309 if ((not && m == FNM_NOMATCH) || (not == 0 && m != FNM_NOMATCH))
310 free (sl->list[i]);
311 else
312 ret->list[ret->list_len++] = sl->list[i];
313 }
314
315 ret->list[ret->list_len] = (char *)NULL;
316 if (npat != filterpat)
317 free (npat);
318
319 return ret;
320 }
321
322 /* Turn an array of strings returned by rl_completion_matches into a STRINGLIST.
323 This understands how rl_completion_matches sets matches[0] (the lcd of the
324 strings in the list, unless it's the only match). */
325 STRINGLIST *
326 completions_to_stringlist (matches)
327 char **matches;
328 {
329 STRINGLIST *sl;
330 int mlen, i, n;
331
332 mlen = (matches == 0) ? 0 : strvec_len (matches);
333 sl = strlist_create (mlen + 1);
334
335 if (matches == 0 || matches[0] == 0)
336 return sl;
337
338 if (matches[1] == 0)
339 {
340 sl->list[0] = STRDUP (matches[0]);
341 sl->list[sl->list_len = 1] = (char *)NULL;
342 return sl;
343 }
344
345 for (i = 1, n = 0; i < mlen; i++, n++)
346 sl->list[n] = STRDUP (matches[i]);
347 sl->list_len = n;
348 sl->list[n] = (char *)NULL;
349
350 return sl;
351 }
352
353 /* Functions to manage the various ITEMLISTs that we populate internally.
354 The caller is responsible for setting ITP->flags correctly. */
355
356 static int
357 it_init_aliases (itp)
358 ITEMLIST *itp;
359 {
360 #ifdef ALIAS
361 alias_t **alias_list;
362 register int i, n;
363 STRINGLIST *sl;
364
365 alias_list = all_aliases ();
366 if (alias_list == 0)
367 {
368 itp->slist = (STRINGLIST *)NULL;
369 return 0;
370 }
371 for (n = 0; alias_list[n]; n++)
372 ;
373 sl = strlist_create (n+1);
374 for (i = 0; i < n; i++)
375 sl->list[i] = STRDUP (alias_list[i]->name);
376 sl->list[n] = (char *)NULL;
377 sl->list_size = sl->list_len = n;
378 itp->slist = sl;
379 #else
380 itp->slist = (STRINGLIST *)NULL;
381 #endif
382 free (alias_list);
383 return 1;
384 }
385
386 static void
387 init_itemlist_from_varlist (itp, svfunc)
388 ITEMLIST *itp;
389 SVFUNC *svfunc;
390 {
391 SHELL_VAR **vlist;
392 STRINGLIST *sl;
393 register int i, n;
394
395 vlist = (*svfunc) ();
396 if (vlist == 0)
397 {
398 itp->slist = (STRINGLIST *)NULL;
399 return;
400 }
401 for (n = 0; vlist[n]; n++)
402 ;
403 sl = strlist_create (n+1);
404 for (i = 0; i < n; i++)
405 sl->list[i] = savestring (vlist[i]->name);
406 sl->list[sl->list_len = n] = (char *)NULL;
407 itp->slist = sl;
408 }
409
410 static int
411 it_init_arrayvars (itp)
412 ITEMLIST *itp;
413 {
414 #if defined (ARRAY_VARS)
415 init_itemlist_from_varlist (itp, all_array_variables);
416 return 1;
417 #else
418 return 0;
419 #endif
420 }
421
422 static int
423 it_init_bindings (itp)
424 ITEMLIST *itp;
425 {
426 char **blist;
427 STRINGLIST *sl;
428
429 /* rl_funmap_names allocates blist, but not its members */
430 blist = (char **)rl_funmap_names (); /* XXX fix const later */
431 sl = strlist_create (0);
432 sl->list = blist;
433 sl->list_size = 0;
434 sl->list_len = strvec_len (sl->list);
435 itp->flags |= LIST_DONTFREEMEMBERS;
436 itp->slist = sl;
437
438 return 0;
439 }
440
441 static int
442 it_init_builtins (itp)
443 ITEMLIST *itp;
444 {
445 STRINGLIST *sl;
446 register int i, n;
447
448 sl = strlist_create (num_shell_builtins);
449 for (i = n = 0; i < num_shell_builtins; i++)
450 if (shell_builtins[i].function)
451 sl->list[n++] = shell_builtins[i].name;
452 sl->list[sl->list_len = n] = (char *)NULL;
453 itp->flags |= LIST_DONTFREEMEMBERS;
454 itp->slist = sl;
455 return 0;
456 }
457
458 static int
459 it_init_enabled (itp)
460 ITEMLIST *itp;
461 {
462 STRINGLIST *sl;
463 register int i, n;
464
465 sl = strlist_create (num_shell_builtins);
466 for (i = n = 0; i < num_shell_builtins; i++)
467 {
468 if (shell_builtins[i].function && (shell_builtins[i].flags & BUILTIN_ENABLED))
469 sl->list[n++] = shell_builtins[i].name;
470 }
471 sl->list[sl->list_len = n] = (char *)NULL;
472 itp->flags |= LIST_DONTFREEMEMBERS;
473 itp->slist = sl;
474 return 0;
475 }
476
477 static int
478 it_init_disabled (itp)
479 ITEMLIST *itp;
480 {
481 STRINGLIST *sl;
482 register int i, n;
483
484 sl = strlist_create (num_shell_builtins);
485 for (i = n = 0; i < num_shell_builtins; i++)
486 {
487 if (shell_builtins[i].function && ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
488 sl->list[n++] = shell_builtins[i].name;
489 }
490 sl->list[sl->list_len = n] = (char *)NULL;
491 itp->flags |= LIST_DONTFREEMEMBERS;
492 itp->slist = sl;
493 return 0;
494 }
495
496 static int
497 it_init_exported (itp)
498 ITEMLIST *itp;
499 {
500 init_itemlist_from_varlist (itp, all_exported_variables);
501 return 0;
502 }
503
504 static int
505 it_init_functions (itp)
506 ITEMLIST *itp;
507 {
508 init_itemlist_from_varlist (itp, all_visible_functions);
509 return 0;
510 }
511
512 /* Like it_init_builtins, but includes everything the help builtin looks at,
513 not just builtins with an active implementing function. */
514 static int
515 it_init_helptopics (itp)
516 ITEMLIST *itp;
517 {
518 STRINGLIST *sl;
519 register int i, n;
520
521 sl = strlist_create (num_shell_builtins);
522 for (i = n = 0; i < num_shell_builtins; i++)
523 sl->list[n++] = shell_builtins[i].name;
524 sl->list[sl->list_len = n] = (char *)NULL;
525 itp->flags |= LIST_DONTFREEMEMBERS;
526 itp->slist = sl;
527 return 0;
528 }
529
530 static int
531 it_init_hostnames (itp)
532 ITEMLIST *itp;
533 {
534 STRINGLIST *sl;
535
536 sl = strlist_create (0);
537 sl->list = get_hostname_list ();
538 sl->list_len = sl->list ? strvec_len (sl->list) : 0;
539 sl->list_size = sl->list_len;
540 itp->slist = sl;
541 itp->flags |= LIST_DONTFREEMEMBERS|LIST_DONTFREE;
542 return 0;
543 }
544
545 static int
546 it_init_joblist (itp, jstate)
547 ITEMLIST *itp;
548 int jstate;
549 {
550 #if defined (JOB_CONTROL)
551 STRINGLIST *sl;
552 register int i;
553 register PROCESS *p;
554 char *s, *t;
555 JOB *j;
556 JOB_STATE ws; /* wanted state */
557
558 ws = JNONE;
559 if (jstate == 0)
560 ws = JRUNNING;
561 else if (jstate == 1)
562 ws = JSTOPPED;
563
564 sl = strlist_create (js.j_jobslots);
565 for (i = js.j_jobslots - 1; i >= 0; i--)
566 {
567 j = get_job_by_jid (i);
568 if (j == 0)
569 continue;
570 p = j->pipe;
571 if (jstate == -1 || JOBSTATE(i) == ws)
572 {
573 s = savestring (p->command);
574 t = strpbrk (s, " \t\n");
575 if (t)
576 *t = '\0';
577 sl->list[sl->list_len++] = s;
578 }
579 }
580 itp->slist = sl;
581 #else
582 itp->slist = (STRINGLIST *)NULL;
583 #endif
584 return 0;
585 }
586
587 static int
588 it_init_jobs (itp)
589 ITEMLIST *itp;
590 {
591 return (it_init_joblist (itp, -1));
592 }
593
594 static int
595 it_init_running (itp)
596 ITEMLIST *itp;
597 {
598 return (it_init_joblist (itp, 0));
599 }
600
601 static int
602 it_init_stopped (itp)
603 ITEMLIST *itp;
604 {
605 return (it_init_joblist (itp, 1));
606 }
607
608 static int
609 it_init_keywords (itp)
610 ITEMLIST *itp;
611 {
612 STRINGLIST *sl;
613 register int i, n;
614
615 for (n = 0; word_token_alist[n].word; n++)
616 ;
617 sl = strlist_create (n);
618 for (i = 0; i < n; i++)
619 sl->list[i] = word_token_alist[i].word;
620 sl->list[sl->list_len = i] = (char *)NULL;
621 itp->flags |= LIST_DONTFREEMEMBERS;
622 itp->slist = sl;
623 return 0;
624 }
625
626 static int
627 it_init_signals (itp)
628 ITEMLIST *itp;
629 {
630 STRINGLIST *sl;
631
632 sl = strlist_create (0);
633 sl->list = signal_names;
634 sl->list_len = strvec_len (sl->list);
635 itp->flags |= LIST_DONTFREE;
636 itp->slist = sl;
637 return 0;
638 }
639
640 static int
641 it_init_variables (itp)
642 ITEMLIST *itp;
643 {
644 init_itemlist_from_varlist (itp, all_visible_variables);
645 return 0;
646 }
647
648 static int
649 it_init_setopts (itp)
650 ITEMLIST *itp;
651 {
652 STRINGLIST *sl;
653
654 sl = strlist_create (0);
655 sl->list = get_minus_o_opts ();
656 sl->list_len = strvec_len (sl->list);
657 itp->slist = sl;
658 itp->flags |= LIST_DONTFREEMEMBERS;
659 return 0;
660 }
661
662 static int
663 it_init_shopts (itp)
664 ITEMLIST *itp;
665 {
666 STRINGLIST *sl;
667
668 sl = strlist_create (0);
669 sl->list = get_shopt_options ();
670 sl->list_len = strvec_len (sl->list);
671 itp->slist = sl;
672 itp->flags |= LIST_DONTFREEMEMBERS;
673 return 0;
674 }
675
676 /* Generate a list of all matches for TEXT using the STRINGLIST in itp->slist
677 as the list of possibilities. If the itemlist has been marked dirty or
678 it should be regenerated every time, destroy the old STRINGLIST and make a
679 new one before trying the match. TEXT is dequoted before attempting a
680 match. */
681 static STRINGLIST *
682 gen_matches_from_itemlist (itp, text)
683 ITEMLIST *itp;
684 const char *text;
685 {
686 STRINGLIST *ret, *sl;
687 int tlen, i, n;
688 char *ntxt;
689
690 if ((itp->flags & (LIST_DIRTY|LIST_DYNAMIC)) ||
691 (itp->flags & LIST_INITIALIZED) == 0)
692 {
693 if (itp->flags & (LIST_DIRTY|LIST_DYNAMIC))
694 clean_itemlist (itp);
695 if ((itp->flags & LIST_INITIALIZED) == 0)
696 initialize_itemlist (itp);
697 }
698 if (itp->slist == 0)
699 return ((STRINGLIST *)NULL);
700 ret = strlist_create (itp->slist->list_len+1);
701 sl = itp->slist;
702
703 ntxt = bash_dequote_text (text);
704 tlen = STRLEN (ntxt);
705
706 for (i = n = 0; i < sl->list_len; i++)
707 {
708 if (tlen == 0 || STREQN (sl->list[i], ntxt, tlen))
709 ret->list[n++] = STRDUP (sl->list[i]);
710 }
711 ret->list[ret->list_len = n] = (char *)NULL;
712
713 FREE (ntxt);
714 return ret;
715 }
716
717 /* A wrapper for rl_filename_completion_function that dequotes the filename
718 before attempting completions. */
719 static char *
720 pcomp_filename_completion_function (text, state)
721 const char *text;
722 int state;
723 {
724 static char *dfn; /* dequoted filename */
725 int qc;
726 int iscompgen, iscompleting;
727
728 if (state == 0)
729 {
730 FREE (dfn);
731 /* remove backslashes quoting special characters in filenames. */
732 /* There are roughly three paths we can follow to get here:
733 1. complete -f
734 2. compgen -f "$word" from a completion function
735 3. compgen -f "$word" from the command line
736 They all need to be handled.
737
738 In the first two cases, readline will run the filename dequoting
739 function in rl_filename_completion_function if it found a filename
740 quoting character in the word to be completed
741 (rl_completion_found_quote). We run the dequoting function here
742 if we're running compgen, we're not completing, and the
743 rl_filename_completion_function won't dequote the filename
744 (rl_completion_found_quote == 0). */
745 iscompgen = this_shell_builtin == compgen_builtin;
746 iscompleting = RL_ISSTATE (RL_STATE_COMPLETING);
747 if (iscompgen && iscompleting == 0 && rl_completion_found_quote == 0
748 && rl_filename_dequoting_function)
749 {
750 /* Use rl_completion_quote_character because any single or
751 double quotes have been removed by the time TEXT makes it
752 here, and we don't want to remove backslashes inside
753 quoted strings. */
754 dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
755 }
756 else
757 dfn = savestring (text);
758 }
759
760 return (rl_filename_completion_function (dfn, state));
761 }
762
763 #define GEN_COMPS(bmap, flag, it, text, glist, tlist) \
764 do { \
765 if (bmap & flag) \
766 { \
767 tlist = gen_matches_from_itemlist (it, text); \
768 if (tlist) \
769 { \
770 glist = strlist_append (glist, tlist); \
771 strlist_dispose (tlist); \
772 } \
773 } \
774 } while (0)
775
776 #define GEN_XCOMPS(bmap, flag, text, func, cmatches, glist, tlist) \
777 do { \
778 if (bmap & flag) \
779 { \
780 cmatches = rl_completion_matches (text, func); \
781 tlist = completions_to_stringlist (cmatches); \
782 glist = strlist_append (glist, tlist); \
783 strvec_dispose (cmatches); \
784 strlist_dispose (tlist); \
785 } \
786 } while (0)
787
788 /* Functions to generate lists of matches from the actions member of CS. */
789
790 static STRINGLIST *
791 gen_action_completions (cs, text)
792 COMPSPEC *cs;
793 const char *text;
794 {
795 STRINGLIST *ret, *tmatches;
796 char **cmatches; /* from rl_completion_matches ... */
797 unsigned long flags;
798 int t;
799
800 ret = tmatches = (STRINGLIST *)NULL;
801 flags = cs->actions;
802
803 GEN_COMPS (flags, CA_ALIAS, &it_aliases, text, ret, tmatches);
804 GEN_COMPS (flags, CA_ARRAYVAR, &it_arrayvars, text, ret, tmatches);
805 GEN_COMPS (flags, CA_BINDING, &it_bindings, text, ret, tmatches);
806 GEN_COMPS (flags, CA_BUILTIN, &it_builtins, text, ret, tmatches);
807 GEN_COMPS (flags, CA_DISABLED, &it_disabled, text, ret, tmatches);
808 GEN_COMPS (flags, CA_ENABLED, &it_enabled, text, ret, tmatches);
809 GEN_COMPS (flags, CA_EXPORT, &it_exports, text, ret, tmatches);
810 GEN_COMPS (flags, CA_FUNCTION, &it_functions, text, ret, tmatches);
811 GEN_COMPS (flags, CA_HELPTOPIC, &it_helptopics, text, ret, tmatches);
812 GEN_COMPS (flags, CA_HOSTNAME, &it_hostnames, text, ret, tmatches);
813 GEN_COMPS (flags, CA_JOB, &it_jobs, text, ret, tmatches);
814 GEN_COMPS (flags, CA_KEYWORD, &it_keywords, text, ret, tmatches);
815 GEN_COMPS (flags, CA_RUNNING, &it_running, text, ret, tmatches);
816 GEN_COMPS (flags, CA_SETOPT, &it_setopts, text, ret, tmatches);
817 GEN_COMPS (flags, CA_SHOPT, &it_shopts, text, ret, tmatches);
818 GEN_COMPS (flags, CA_SIGNAL, &it_signals, text, ret, tmatches);
819 GEN_COMPS (flags, CA_STOPPED, &it_stopped, text, ret, tmatches);
820 GEN_COMPS (flags, CA_VARIABLE, &it_variables, text, ret, tmatches);
821
822 GEN_XCOMPS(flags, CA_COMMAND, text, command_word_completion_function, cmatches, ret, tmatches);
823 GEN_XCOMPS(flags, CA_FILE, text, pcomp_filename_completion_function, cmatches, ret, tmatches);
824 GEN_XCOMPS(flags, CA_USER, text, rl_username_completion_function, cmatches, ret, tmatches);
825 GEN_XCOMPS(flags, CA_GROUP, text, bash_groupname_completion_function, cmatches, ret, tmatches);
826 GEN_XCOMPS(flags, CA_SERVICE, text, bash_servicename_completion_function, cmatches, ret, tmatches);
827
828 /* And lastly, the special case for directories */
829 if (flags & CA_DIRECTORY)
830 {
831 t = rl_filename_completion_desired;
832 rl_completion_mark_symlink_dirs = 1; /* override user preference */
833 cmatches = bash_directory_completion_matches (text);
834 /* If we did not want filename completion before this, and there are
835 no matches, turn off rl_filename_completion_desired so whatever
836 matches we get are not treated as filenames (it gets turned on by
837 rl_filename_completion_function unconditionally). */
838 if (t == 0 && cmatches == 0 && rl_filename_completion_desired == 1)
839 rl_filename_completion_desired = 0;
840 tmatches = completions_to_stringlist (cmatches);
841 ret = strlist_append (ret, tmatches);
842 strvec_dispose (cmatches);
843 strlist_dispose (tmatches);
844 }
845
846 return ret;
847 }
848
849 /* Generate a list of matches for CS->globpat. Unresolved: should this use
850 TEXT as a match prefix, or just go without? Currently, the code does not
851 use TEXT, just globs CS->globpat and returns the results. If we do decide
852 to use TEXT, we should call quote_string_for_globbing before the call to
853 glob_filename. */
854 static STRINGLIST *
855 gen_globpat_matches (cs, text)
856 COMPSPEC *cs;
857 const char *text;
858 {
859 STRINGLIST *sl;
860
861 sl = strlist_create (0);
862 sl->list = glob_filename (cs->globpat, 0);
863 if (GLOB_FAILED (sl->list))
864 sl->list = (char **)NULL;
865 if (sl->list)
866 sl->list_len = sl->list_size = strvec_len (sl->list);
867 return sl;
868 }
869
870 /* Perform the shell word expansions on CS->words and return the results.
871 Again, this ignores TEXT. */
872 static STRINGLIST *
873 gen_wordlist_matches (cs, text)
874 COMPSPEC *cs;
875 const char *text;
876 {
877 WORD_LIST *l, *l2;
878 STRINGLIST *sl;
879 int nw, tlen;
880 char *ntxt; /* dequoted TEXT to use in comparisons */
881
882 if (cs->words == 0 || cs->words[0] == '\0')
883 return ((STRINGLIST *)NULL);
884
885 /* This used to be a simple expand_string(cs->words, 0), but that won't
886 do -- there's no way to split a simple list into individual words
887 that way, since the shell semantics say that word splitting is done
888 only on the results of expansion. split_at_delims also handles embedded
889 quoted strings and preserves the quotes for the expand_words_shellexp
890 function call that follows. */
891 /* XXX - this is where this function spends most of its time */
892 l = split_at_delims (cs->words, strlen (cs->words), (char *)NULL, -1, 0, (int *)NULL, (int *)NULL);
893 if (l == 0)
894 return ((STRINGLIST *)NULL);
895 /* This will jump back to the top level if the expansion fails... */
896 l2 = expand_words_shellexp (l);
897 dispose_words (l);
898
899 nw = list_length (l2);
900 sl = strlist_create (nw + 1);
901
902 ntxt = bash_dequote_text (text);
903 tlen = STRLEN (ntxt);
904
905 for (nw = 0, l = l2; l; l = l->next)
906 {
907 if (tlen == 0 || STREQN (l->word->word, ntxt, tlen))
908 sl->list[nw++] = STRDUP (l->word->word);
909 }
910 sl->list[sl->list_len = nw] = (char *)NULL;
911
912 dispose_words (l2);
913 FREE (ntxt);
914 return sl;
915 }
916
917 #ifdef ARRAY_VARS
918
919 static SHELL_VAR *
920 bind_comp_words (lwords)
921 WORD_LIST *lwords;
922 {
923 SHELL_VAR *v;
924
925 v = find_variable ("COMP_WORDS");
926 if (v == 0)
927 v = make_new_array_variable ("COMP_WORDS");
928 if (readonly_p (v))
929 VUNSETATTR (v, att_readonly);
930 if (array_p (v) == 0)
931 v = convert_var_to_array (v);
932 v = assign_array_var_from_word_list (v, lwords, 0);
933
934 VUNSETATTR (v, att_invisible);
935 return v;
936 }
937 #endif /* ARRAY_VARS */
938
939 static void
940 bind_compfunc_variables (line, ind, lwords, cw, exported)
941 char *line;
942 int ind;
943 WORD_LIST *lwords;
944 int cw, exported;
945 {
946 char ibuf[INT_STRLEN_BOUND(int) + 1];
947 char *value;
948 SHELL_VAR *v;
949 size_t llen;
950 int c;
951
952 /* Set the variables that the function expects while it executes. Maybe
953 these should be in the function environment (temporary_env). */
954 v = bind_variable ("COMP_LINE", line, 0);
955 if (v && exported)
956 VSETATTR(v, att_exported);
957
958 /* Post bash-4.2: COMP_POINT is characters instead of bytes. */
959 c = line[ind];
960 line[ind] = '\0';
961 llen = MB_STRLEN (line);
962 line[ind] = c;
963 value = inttostr (llen, ibuf, sizeof(ibuf));
964 v = bind_int_variable ("COMP_POINT", value);
965 if (v && exported)
966 VSETATTR(v, att_exported);
967
968 value = inttostr (rl_completion_type, ibuf, sizeof (ibuf));
969 v = bind_int_variable ("COMP_TYPE", value);
970 if (v && exported)
971 VSETATTR(v, att_exported);
972
973 value = inttostr (rl_completion_invoking_key, ibuf, sizeof (ibuf));
974 v = bind_int_variable ("COMP_KEY", value);
975 if (v && exported)
976 VSETATTR(v, att_exported);
977
978 /* Since array variables can't be exported, we don't bother making the
979 array of words. */
980 if (exported == 0)
981 {
982 #ifdef ARRAY_VARS
983 v = bind_comp_words (lwords);
984 value = inttostr (cw, ibuf, sizeof(ibuf));
985 bind_int_variable ("COMP_CWORD", value);
986 #endif
987 }
988 else
989 array_needs_making = 1;
990 }
991
992 static void
993 unbind_compfunc_variables (exported)
994 int exported;
995 {
996 unbind_variable ("COMP_LINE");
997 unbind_variable ("COMP_POINT");
998 unbind_variable ("COMP_TYPE");
999 unbind_variable ("COMP_KEY");
1000 #ifdef ARRAY_VARS
1001 unbind_variable ("COMP_WORDS");
1002 unbind_variable ("COMP_CWORD");
1003 #endif
1004 if (exported)
1005 array_needs_making = 1;
1006 }
1007
1008 /* Build the list of words to pass to a function or external command
1009 as arguments. When the function or command is invoked,
1010
1011 $0 == function or command being invoked
1012 $1 == command name
1013 $2 == word to be completed (possibly null)
1014 $3 == previous word
1015
1016 Functions can access all of the words in the current command line
1017 with the COMP_WORDS array. External commands cannot; they have to
1018 make do with the COMP_LINE and COMP_POINT variables. */
1019
1020 static WORD_LIST *
1021 build_arg_list (cmd, cname, text, lwords, ind)
1022 char *cmd;
1023 const char *cname;
1024 const char *text;
1025 WORD_LIST *lwords;
1026 int ind;
1027 {
1028 WORD_LIST *ret, *cl, *l;
1029 WORD_DESC *w;
1030 int i;
1031
1032 ret = (WORD_LIST *)NULL;
1033 w = make_word (cmd);
1034 ret = make_word_list (w, (WORD_LIST *)NULL); /* $0 */
1035
1036 w = make_word (cname); /* $1 */
1037 cl = ret->next = make_word_list (w, (WORD_LIST *)NULL);
1038
1039 w = make_word (text);
1040 cl->next = make_word_list (w, (WORD_LIST *)NULL); /* $2 */
1041 cl = cl->next;
1042
1043 /* Search lwords for current word */
1044 for (l = lwords, i = 1; l && i < ind-1; l = l->next, i++)
1045 ;
1046 w = (l && l->word) ? copy_word (l->word) : make_word ("");
1047 cl->next = make_word_list (w, (WORD_LIST *)NULL);
1048
1049 return ret;
1050 }
1051
1052 /* Build a command string with
1053 $0 == cs->funcname (function to execute for completion list)
1054 $1 == command name (command being completed)
1055 $2 = word to be completed (possibly null)
1056 $3 = previous word
1057 and run in the current shell. The function should put its completion
1058 list into the array variable COMPREPLY. We build a STRINGLIST
1059 from the results and return it.
1060
1061 Since the shell function should return its list of matches in an array
1062 variable, this does nothing if arrays are not compiled into the shell. */
1063
1064 static STRINGLIST *
1065 gen_shell_function_matches (cs, cmd, text, line, ind, lwords, nw, cw, foundp)
1066 COMPSPEC *cs;
1067 const char *cmd;
1068 const char *text;
1069 char *line;
1070 int ind;
1071 WORD_LIST *lwords;
1072 int nw, cw;
1073 int *foundp;
1074 {
1075 char *funcname;
1076 STRINGLIST *sl;
1077 SHELL_VAR *f, *v;
1078 WORD_LIST *cmdlist;
1079 int fval, found;
1080 sh_parser_state_t ps;
1081 sh_parser_state_t * restrict pps;
1082 #if defined (ARRAY_VARS)
1083 ARRAY *a;
1084 #endif
1085
1086 found = 0;
1087 if (foundp)
1088 *foundp = found;
1089
1090 funcname = cs->funcname;
1091 f = find_function (funcname);
1092 if (f == 0)
1093 {
1094 internal_error (_("completion: function `%s' not found"), funcname);
1095 rl_ding ();
1096 rl_on_new_line ();
1097 return ((STRINGLIST *)NULL);
1098 }
1099
1100 #if !defined (ARRAY_VARS)
1101 return ((STRINGLIST *)NULL);
1102 #else
1103
1104 /* We pass cw - 1 because command_line_to_word_list returns indices that are
1105 1-based, while bash arrays are 0-based. */
1106 bind_compfunc_variables (line, ind, lwords, cw - 1, 0);
1107
1108 cmdlist = build_arg_list (funcname, cmd, text, lwords, cw);
1109
1110 pps = &ps;
1111 save_parser_state (pps);
1112 begin_unwind_frame ("gen-shell-function-matches");
1113 add_unwind_protect (restore_parser_state, (char *)pps);
1114 add_unwind_protect (dispose_words, (char *)cmdlist);
1115 add_unwind_protect (unbind_compfunc_variables, (char *)0);
1116
1117 fval = execute_shell_function (f, cmdlist);
1118
1119 discard_unwind_frame ("gen-shell-function-matches");
1120 restore_parser_state (pps);
1121
1122 found = fval != EX_NOTFOUND;
1123 if (fval == EX_RETRYFAIL)
1124 found |= PCOMP_RETRYFAIL;
1125 if (foundp)
1126 *foundp = found;
1127
1128 /* Now clean up and destroy everything. */
1129 dispose_words (cmdlist);
1130 unbind_compfunc_variables (0);
1131
1132 /* The list of completions is returned in the array variable COMPREPLY. */
1133 v = find_variable ("COMPREPLY");
1134 if (v == 0)
1135 return ((STRINGLIST *)NULL);
1136 if (array_p (v) == 0)
1137 v = convert_var_to_array (v);
1138
1139 VUNSETATTR (v, att_invisible);
1140
1141 a = array_cell (v);
1142 if (found == 0 || (found & PCOMP_RETRYFAIL) || a == 0 || array_empty (a))
1143 sl = (STRINGLIST *)NULL;
1144 else
1145 {
1146 /* XXX - should we filter the list of completions so only those matching
1147 TEXT are returned? Right now, we do not. */
1148 sl = strlist_create (0);
1149 sl->list = array_to_argv (a);
1150 sl->list_len = sl->list_size = array_num_elements (a);
1151 }
1152
1153 /* XXX - should we unbind COMPREPLY here? */
1154 unbind_variable ("COMPREPLY");
1155
1156 return (sl);
1157 #endif
1158 }
1159
1160 /* Build a command string with
1161 $0 == cs->command (command to execute for completion list)
1162 $1 == command name (command being completed)
1163 $2 = word to be completed (possibly null)
1164 $3 = previous word
1165 and run in with command substitution. Parse the results, one word
1166 per line, with backslashes allowed to escape newlines. Build a
1167 STRINGLIST from the results and return it. */
1168
1169 static STRINGLIST *
1170 gen_command_matches (cs, cmd, text, line, ind, lwords, nw, cw)
1171 COMPSPEC *cs;
1172 const char *cmd;
1173 const char *text;
1174 char *line;
1175 int ind;
1176 WORD_LIST *lwords;
1177 int nw, cw;
1178 {
1179 char *csbuf, *cscmd, *t;
1180 int cmdlen, cmdsize, n, ws, we;
1181 WORD_LIST *cmdlist, *cl;
1182 WORD_DESC *tw;
1183 STRINGLIST *sl;
1184
1185 bind_compfunc_variables (line, ind, lwords, cw, 1);
1186 cmdlist = build_arg_list (cs->command, cmd, text, lwords, cw);
1187
1188 /* Estimate the size needed for the buffer. */
1189 n = strlen (cs->command);
1190 cmdsize = n + 1;
1191 for (cl = cmdlist->next; cl; cl = cl->next)
1192 cmdsize += STRLEN (cl->word->word) + 3;
1193 cmdsize += 2;
1194
1195 /* allocate the string for the command and fill it in. */
1196 cscmd = (char *)xmalloc (cmdsize + 1);
1197
1198 strcpy (cscmd, cs->command); /* $0 */
1199 cmdlen = n;
1200 cscmd[cmdlen++] = ' ';
1201 for (cl = cmdlist->next; cl; cl = cl->next) /* $1, $2, $3, ... */
1202 {
1203 t = sh_single_quote (cl->word->word ? cl->word->word : "");
1204 n = strlen (t);
1205 RESIZE_MALLOCED_BUFFER (cscmd, cmdlen, n + 2, cmdsize, 64);
1206 strcpy (cscmd + cmdlen, t);
1207 cmdlen += n;
1208 if (cl->next)
1209 cscmd[cmdlen++] = ' ';
1210 free (t);
1211 }
1212 cscmd[cmdlen] = '\0';
1213
1214 tw = command_substitute (cscmd, 0);
1215 csbuf = tw ? tw->word : (char *)NULL;
1216 if (tw)
1217 dispose_word_desc (tw);
1218
1219 /* Now clean up and destroy everything. */
1220 dispose_words (cmdlist);
1221 free (cscmd);
1222 unbind_compfunc_variables (1);
1223
1224 if (csbuf == 0 || *csbuf == '\0')
1225 {
1226 FREE (csbuf);
1227 return ((STRINGLIST *)NULL);
1228 }
1229
1230 /* Now break CSBUF up at newlines, with backslash allowed to escape a
1231 newline, and put the individual words into a STRINGLIST. */
1232 sl = strlist_create (16);
1233 for (ws = 0; csbuf[ws]; )
1234 {
1235 we = ws;
1236 while (csbuf[we] && csbuf[we] != '\n')
1237 {
1238 if (csbuf[we] == '\\' && csbuf[we+1] == '\n')
1239 we++;
1240 we++;
1241 }
1242 t = substring (csbuf, ws, we);
1243 if (sl->list_len >= sl->list_size - 1)
1244 strlist_resize (sl, sl->list_size + 16);
1245 sl->list[sl->list_len++] = t;
1246 while (csbuf[we] == '\n') we++;
1247 ws = we;
1248 }
1249 sl->list[sl->list_len] = (char *)NULL;
1250
1251 free (csbuf);
1252 return (sl);
1253 }
1254
1255 static WORD_LIST *
1256 command_line_to_word_list (line, llen, sentinel, nwp, cwp)
1257 char *line;
1258 int llen, sentinel, *nwp, *cwp;
1259 {
1260 WORD_LIST *ret;
1261 char *delims;
1262
1263 #if 0
1264 delims = "()<>;&| \t\n"; /* shell metacharacters break words */
1265 #else
1266 delims = rl_completer_word_break_characters;
1267 #endif
1268 ret = split_at_delims (line, llen, delims, sentinel, SD_NOQUOTEDELIM, nwp, cwp);
1269 return (ret);
1270 }
1271
1272 /* Evaluate COMPSPEC *cs and return all matches for WORD. */
1273
1274 STRINGLIST *
1275 gen_compspec_completions (cs, cmd, word, start, end, foundp)
1276 COMPSPEC *cs;
1277 const char *cmd;
1278 const char *word;
1279 int start, end;
1280 int *foundp;
1281 {
1282 STRINGLIST *ret, *tmatches;
1283 char *line;
1284 int llen, nw, cw, found, foundf;
1285 WORD_LIST *lwords;
1286 WORD_DESC *lw;
1287 COMPSPEC *tcs;
1288
1289 found = 1;
1290
1291 #ifdef DEBUG
1292 debug_printf ("gen_compspec_completions (%s, %s, %d, %d)", cmd, word, start, end);
1293 debug_printf ("gen_compspec_completions: %s -> %p", cmd, cs);
1294 #endif
1295 ret = gen_action_completions (cs, word);
1296 #ifdef DEBUG
1297 if (ret && progcomp_debug)
1298 {
1299 debug_printf ("gen_action_completions (%p, %s) -->", cs, word);
1300 strlist_print (ret, "\t");
1301 rl_on_new_line ();
1302 }
1303 #endif
1304
1305 /* Now we start generating completions based on the other members of CS. */
1306 if (cs->globpat)
1307 {
1308 tmatches = gen_globpat_matches (cs, word);
1309 if (tmatches)
1310 {
1311 #ifdef DEBUG
1312 if (progcomp_debug)
1313 {
1314 debug_printf ("gen_globpat_matches (%p, %s) -->", cs, word);
1315 strlist_print (tmatches, "\t");
1316 rl_on_new_line ();
1317 }
1318 #endif
1319 ret = strlist_append (ret, tmatches);
1320 strlist_dispose (tmatches);
1321 rl_filename_completion_desired = 1;
1322 }
1323 }
1324
1325 if (cs->words)
1326 {
1327 tmatches = gen_wordlist_matches (cs, word);
1328 if (tmatches)
1329 {
1330 #ifdef DEBUG
1331 if (progcomp_debug)
1332 {
1333 debug_printf ("gen_wordlist_matches (%p, %s) -->", cs, word);
1334 strlist_print (tmatches, "\t");
1335 rl_on_new_line ();
1336 }
1337 #endif
1338 ret = strlist_append (ret, tmatches);
1339 strlist_dispose (tmatches);
1340 }
1341 }
1342
1343 lwords = (WORD_LIST *)NULL;
1344 line = (char *)NULL;
1345 if (cs->command || cs->funcname)
1346 {
1347 /* If we have a command or function to execute, we need to first break
1348 the command line into individual words, find the number of words,
1349 and find the word in the list containing the word to be completed. */
1350 line = substring (rl_line_buffer, start, end);
1351 llen = end - start;
1352
1353 #ifdef DEBUG
1354 debug_printf ("command_line_to_word_list (%s, %d, %d, %p, %p)",
1355 line, llen, rl_point - start, &nw, &cw);
1356 #endif
1357 lwords = command_line_to_word_list (line, llen, rl_point - start, &nw, &cw);
1358 /* If we skipped a NULL word at the beginning of the line, add it back */
1359 if (lwords && lwords->word && cmd[0] == 0 && lwords->word->word[0] != 0)
1360 {
1361 lw = make_bare_word (cmd);
1362 lwords = make_word_list (lw, lwords);
1363 nw++;
1364 cw++;
1365 }
1366 #ifdef DEBUG
1367 if (lwords == 0 && llen > 0)
1368 debug_printf ("ERROR: command_line_to_word_list returns NULL");
1369 else if (progcomp_debug)
1370 {
1371 debug_printf ("command_line_to_word_list -->");
1372 printf ("\t");
1373 print_word_list (lwords, "!");
1374 printf ("\n");
1375 fflush(stdout);
1376 rl_on_new_line ();
1377 }
1378 #endif
1379 }
1380
1381 if (cs->funcname)
1382 {
1383 foundf = 0;
1384 tmatches = gen_shell_function_matches (cs, cmd, word, line, rl_point - start, lwords, nw, cw, &foundf);
1385 if (foundf != 0)
1386 found = foundf;
1387 if (tmatches)
1388 {
1389 #ifdef DEBUG
1390 if (progcomp_debug)
1391 {
1392 debug_printf ("gen_shell_function_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
1393 strlist_print (tmatches, "\t");
1394 rl_on_new_line ();
1395 }
1396 #endif
1397 ret = strlist_append (ret, tmatches);
1398 strlist_dispose (tmatches);
1399 }
1400 }
1401
1402 if (cs->command)
1403 {
1404 tmatches = gen_command_matches (cs, cmd, word, line, rl_point - start, lwords, nw, cw);
1405 if (tmatches)
1406 {
1407 #ifdef DEBUG
1408 if (progcomp_debug)
1409 {
1410 debug_printf ("gen_command_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
1411 strlist_print (tmatches, "\t");
1412 rl_on_new_line ();
1413 }
1414 #endif
1415 ret = strlist_append (ret, tmatches);
1416 strlist_dispose (tmatches);
1417 }
1418 }
1419
1420 if (cs->command || cs->funcname)
1421 {
1422 if (lwords)
1423 dispose_words (lwords);
1424 FREE (line);
1425 }
1426
1427 if (foundp)
1428 *foundp = found;
1429
1430 if (found == 0 || (found & PCOMP_RETRYFAIL))
1431 {
1432 strlist_dispose (ret);
1433 return NULL;
1434 }
1435
1436 if (cs->filterpat)
1437 {
1438 tmatches = filter_stringlist (ret, cs->filterpat, word);
1439 #ifdef DEBUG
1440 if (progcomp_debug)
1441 {
1442 debug_printf ("filter_stringlist (%p, %s, %s) -->", ret, cs->filterpat, word);
1443 strlist_print (tmatches, "\t");
1444 rl_on_new_line ();
1445 }
1446 #endif
1447 if (ret && ret != tmatches)
1448 {
1449 FREE (ret->list);
1450 free (ret);
1451 }
1452 ret = tmatches;
1453 }
1454
1455 if (cs->prefix || cs->suffix)
1456 ret = strlist_prefix_suffix (ret, cs->prefix, cs->suffix);
1457
1458 /* If no matches have been generated and the user has specified that
1459 directory completion should be done as a default, call
1460 gen_action_completions again to generate a list of matching directory
1461 names. */
1462 if ((ret == 0 || ret->list_len == 0) && (cs->options & COPT_DIRNAMES))
1463 {
1464 tcs = compspec_create ();
1465 tcs->actions = CA_DIRECTORY;
1466 FREE (ret);
1467 ret = gen_action_completions (tcs, word);
1468 compspec_dispose (tcs);
1469 }
1470 else if (cs->options & COPT_PLUSDIRS)
1471 {
1472 tcs = compspec_create ();
1473 tcs->actions = CA_DIRECTORY;
1474 tmatches = gen_action_completions (tcs, word);
1475 ret = strlist_append (ret, tmatches);
1476 strlist_dispose (tmatches);
1477 compspec_dispose (tcs);
1478 }
1479
1480 return (ret);
1481 }
1482
1483 void
1484 pcomp_set_readline_variables (flags, nval)
1485 int flags, nval;
1486 {
1487 /* If the user specified that the compspec returns filenames, make
1488 sure that readline knows it. */
1489 if (flags & COPT_FILENAMES)
1490 rl_filename_completion_desired = nval;
1491 /* If the user doesn't want a space appended, tell readline. */
1492 if (flags & COPT_NOSPACE)
1493 rl_completion_suppress_append = nval;
1494 /* The value here is inverted, since the default is on and the `noquote'
1495 option is supposed to turn it off */
1496 if (flags & COPT_NOQUOTE)
1497 rl_filename_quoting_desired = 1 - nval;
1498 }
1499
1500 /* Set or unset FLAGS in the options word of the current compspec.
1501 SET_OR_UNSET is 1 for setting, 0 for unsetting. */
1502 void
1503 pcomp_set_compspec_options (cs, flags, set_or_unset)
1504 COMPSPEC *cs;
1505 int flags, set_or_unset;
1506 {
1507 if (cs == 0 && ((cs = pcomp_curcs) == 0))
1508 return;
1509 if (set_or_unset)
1510 cs->options |= flags;
1511 else
1512 cs->options &= ~flags;
1513 }
1514
1515 static STRINGLIST *
1516 gen_progcomp_completions (ocmd, cmd, word, start, end, foundp, retryp, lastcs)
1517 const char *ocmd;
1518 const char *cmd;
1519 const char *word;
1520 int start, end;
1521 int *foundp, *retryp;
1522 COMPSPEC **lastcs;
1523 {
1524 COMPSPEC *cs, *oldcs;
1525 const char *oldcmd;
1526 STRINGLIST *ret;
1527
1528 cs = progcomp_search (ocmd);
1529
1530 if (cs == 0 || cs == *lastcs)
1531 {
1532 #if 0
1533 if (foundp)
1534 *foundp = 0;
1535 #endif
1536 return (NULL);
1537 }
1538
1539 if (*lastcs)
1540 compspec_dispose (*lastcs);
1541 cs->refcount++; /* XXX */
1542 *lastcs = cs;
1543
1544 cs = compspec_copy (cs);
1545
1546 oldcs = pcomp_curcs;
1547 oldcmd = pcomp_curcmd;
1548
1549 pcomp_curcs = cs;
1550 pcomp_curcmd = cmd;
1551
1552 ret = gen_compspec_completions (cs, cmd, word, start, end, foundp);
1553
1554 pcomp_curcs = oldcs;
1555 pcomp_curcmd = oldcmd;
1556
1557 /* We need to conditionally handle setting *retryp here */
1558 if (retryp)
1559 *retryp = foundp && (*foundp & PCOMP_RETRYFAIL);
1560
1561 if (foundp)
1562 {
1563 *foundp &= ~PCOMP_RETRYFAIL;
1564 *foundp |= cs->options;
1565 }
1566
1567 compspec_dispose (cs);
1568 return ret;
1569 }
1570
1571 /* The driver function for the programmable completion code. Returns a list
1572 of matches for WORD, which is an argument to command CMD. START and END
1573 bound the command currently being completed in rl_line_buffer. */
1574 char **
1575 programmable_completions (cmd, word, start, end, foundp)
1576 const char *cmd;
1577 const char *word;
1578 int start, end, *foundp;
1579 {
1580 COMPSPEC *cs, *lastcs;
1581 STRINGLIST *ret;
1582 char **rmatches, *t;
1583 int found, retry, count;
1584
1585 lastcs = 0;
1586 found = count = 0;
1587
1588 do
1589 {
1590 retry = 0;
1591
1592 /* We look at the basename of CMD if the full command does not have
1593 an associated COMPSPEC. */
1594 ret = gen_progcomp_completions (cmd, cmd, word, start, end, &found, &retry, &lastcs);
1595 if (found == 0)
1596 {
1597 t = strrchr (cmd, '/');
1598 if (t && *(++t))
1599 ret = gen_progcomp_completions (t, cmd, word, start, end, &found, &retry, &lastcs);
1600 }
1601
1602 if (found == 0)
1603 ret = gen_progcomp_completions (DEFAULTCMD, cmd, word, start, end, &found, &retry, &lastcs);
1604
1605 count++;
1606
1607 if (count > 32)
1608 {
1609 internal_warning ("programmable_completion: %s: possible retry loop", cmd);
1610 break;
1611 }
1612 }
1613 while (retry);
1614
1615 if (ret)
1616 {
1617 rmatches = ret->list;
1618 free (ret);
1619 }
1620 else
1621 rmatches = (char **)NULL;
1622
1623 if (foundp)
1624 *foundp = found;
1625
1626 if (lastcs) /* XXX - should be while? */
1627 compspec_dispose (lastcs);
1628
1629 return (rmatches);
1630 }
1631
1632 #endif /* PROGRAMMABLE_COMPLETION */