]> git.ipfire.org Git - thirdparty/bash.git/blob - pcomplete.c
bash-20121026 additional cleanup
[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 roughtly 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 {
749 /* Use rl_completion_quote_character because any single or
750 double quotes have been removed by the time TEXT makes it
751 here, and we don't want to remove backslashes inside
752 quoted strings. */
753 dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
754 }
755 else
756 dfn = savestring (text);
757 }
758
759 return (rl_filename_completion_function (dfn, state));
760 }
761
762 #define GEN_COMPS(bmap, flag, it, text, glist, tlist) \
763 do { \
764 if (bmap & flag) \
765 { \
766 tlist = gen_matches_from_itemlist (it, text); \
767 if (tlist) \
768 { \
769 glist = strlist_append (glist, tlist); \
770 strlist_dispose (tlist); \
771 } \
772 } \
773 } while (0)
774
775 #define GEN_XCOMPS(bmap, flag, text, func, cmatches, glist, tlist) \
776 do { \
777 if (bmap & flag) \
778 { \
779 cmatches = rl_completion_matches (text, func); \
780 tlist = completions_to_stringlist (cmatches); \
781 glist = strlist_append (glist, tlist); \
782 strvec_dispose (cmatches); \
783 strlist_dispose (tlist); \
784 } \
785 } while (0)
786
787 /* Functions to generate lists of matches from the actions member of CS. */
788
789 static STRINGLIST *
790 gen_action_completions (cs, text)
791 COMPSPEC *cs;
792 const char *text;
793 {
794 STRINGLIST *ret, *tmatches;
795 char **cmatches; /* from rl_completion_matches ... */
796 unsigned long flags;
797 int t;
798
799 ret = tmatches = (STRINGLIST *)NULL;
800 flags = cs->actions;
801
802 GEN_COMPS (flags, CA_ALIAS, &it_aliases, text, ret, tmatches);
803 GEN_COMPS (flags, CA_ARRAYVAR, &it_arrayvars, text, ret, tmatches);
804 GEN_COMPS (flags, CA_BINDING, &it_bindings, text, ret, tmatches);
805 GEN_COMPS (flags, CA_BUILTIN, &it_builtins, text, ret, tmatches);
806 GEN_COMPS (flags, CA_DISABLED, &it_disabled, text, ret, tmatches);
807 GEN_COMPS (flags, CA_ENABLED, &it_enabled, text, ret, tmatches);
808 GEN_COMPS (flags, CA_EXPORT, &it_exports, text, ret, tmatches);
809 GEN_COMPS (flags, CA_FUNCTION, &it_functions, text, ret, tmatches);
810 GEN_COMPS (flags, CA_HELPTOPIC, &it_helptopics, text, ret, tmatches);
811 GEN_COMPS (flags, CA_HOSTNAME, &it_hostnames, text, ret, tmatches);
812 GEN_COMPS (flags, CA_JOB, &it_jobs, text, ret, tmatches);
813 GEN_COMPS (flags, CA_KEYWORD, &it_keywords, text, ret, tmatches);
814 GEN_COMPS (flags, CA_RUNNING, &it_running, text, ret, tmatches);
815 GEN_COMPS (flags, CA_SETOPT, &it_setopts, text, ret, tmatches);
816 GEN_COMPS (flags, CA_SHOPT, &it_shopts, text, ret, tmatches);
817 GEN_COMPS (flags, CA_SIGNAL, &it_signals, text, ret, tmatches);
818 GEN_COMPS (flags, CA_STOPPED, &it_stopped, text, ret, tmatches);
819 GEN_COMPS (flags, CA_VARIABLE, &it_variables, text, ret, tmatches);
820
821 GEN_XCOMPS(flags, CA_COMMAND, text, command_word_completion_function, cmatches, ret, tmatches);
822 GEN_XCOMPS(flags, CA_FILE, text, pcomp_filename_completion_function, cmatches, ret, tmatches);
823 GEN_XCOMPS(flags, CA_USER, text, rl_username_completion_function, cmatches, ret, tmatches);
824 GEN_XCOMPS(flags, CA_GROUP, text, bash_groupname_completion_function, cmatches, ret, tmatches);
825 GEN_XCOMPS(flags, CA_SERVICE, text, bash_servicename_completion_function, cmatches, ret, tmatches);
826
827 /* And lastly, the special case for directories */
828 if (flags & CA_DIRECTORY)
829 {
830 t = rl_filename_completion_desired;
831 rl_completion_mark_symlink_dirs = 1; /* override user preference */
832 cmatches = bash_directory_completion_matches (text);
833 /* If we did not want filename completion before this, and there are
834 no matches, turn off rl_filename_completion_desired so whatever
835 matches we get are not treated as filenames (it gets turned on by
836 rl_filename_completion_function unconditionally). */
837 if (t == 0 && cmatches == 0 && rl_filename_completion_desired == 1)
838 rl_filename_completion_desired = 0;
839 tmatches = completions_to_stringlist (cmatches);
840 ret = strlist_append (ret, tmatches);
841 strvec_dispose (cmatches);
842 strlist_dispose (tmatches);
843 }
844
845 return ret;
846 }
847
848 /* Generate a list of matches for CS->globpat. Unresolved: should this use
849 TEXT as a match prefix, or just go without? Currently, the code does not
850 use TEXT, just globs CS->globpat and returns the results. If we do decide
851 to use TEXT, we should call quote_string_for_globbing before the call to
852 glob_filename. */
853 static STRINGLIST *
854 gen_globpat_matches (cs, text)
855 COMPSPEC *cs;
856 const char *text;
857 {
858 STRINGLIST *sl;
859
860 sl = strlist_create (0);
861 sl->list = glob_filename (cs->globpat, 0);
862 if (GLOB_FAILED (sl->list))
863 sl->list = (char **)NULL;
864 if (sl->list)
865 sl->list_len = sl->list_size = strvec_len (sl->list);
866 return sl;
867 }
868
869 /* Perform the shell word expansions on CS->words and return the results.
870 Again, this ignores TEXT. */
871 static STRINGLIST *
872 gen_wordlist_matches (cs, text)
873 COMPSPEC *cs;
874 const char *text;
875 {
876 WORD_LIST *l, *l2;
877 STRINGLIST *sl;
878 int nw, tlen;
879 char *ntxt; /* dequoted TEXT to use in comparisons */
880
881 if (cs->words == 0 || cs->words[0] == '\0')
882 return ((STRINGLIST *)NULL);
883
884 /* This used to be a simple expand_string(cs->words, 0), but that won't
885 do -- there's no way to split a simple list into individual words
886 that way, since the shell semantics say that word splitting is done
887 only on the results of expansion. split_at_delims also handles embedded
888 quoted strings and preserves the quotes for the expand_words_shellexp
889 function call that follows. */
890 /* XXX - this is where this function spends most of its time */
891 l = split_at_delims (cs->words, strlen (cs->words), (char *)NULL, -1, 0, (int *)NULL, (int *)NULL);
892 if (l == 0)
893 return ((STRINGLIST *)NULL);
894 /* This will jump back to the top level if the expansion fails... */
895 l2 = expand_words_shellexp (l);
896 dispose_words (l);
897
898 nw = list_length (l2);
899 sl = strlist_create (nw + 1);
900
901 ntxt = bash_dequote_text (text);
902 tlen = STRLEN (ntxt);
903
904 for (nw = 0, l = l2; l; l = l->next)
905 {
906 if (tlen == 0 || STREQN (l->word->word, ntxt, tlen))
907 sl->list[nw++] = STRDUP (l->word->word);
908 }
909 sl->list[sl->list_len = nw] = (char *)NULL;
910
911 dispose_words (l2);
912 FREE (ntxt);
913 return sl;
914 }
915
916 #ifdef ARRAY_VARS
917
918 static SHELL_VAR *
919 bind_comp_words (lwords)
920 WORD_LIST *lwords;
921 {
922 SHELL_VAR *v;
923
924 v = find_variable ("COMP_WORDS");
925 if (v == 0)
926 v = make_new_array_variable ("COMP_WORDS");
927 if (readonly_p (v))
928 VUNSETATTR (v, att_readonly);
929 if (array_p (v) == 0)
930 v = convert_var_to_array (v);
931 v = assign_array_var_from_word_list (v, lwords, 0);
932
933 VUNSETATTR (v, att_invisible);
934 return v;
935 }
936 #endif /* ARRAY_VARS */
937
938 static void
939 bind_compfunc_variables (line, ind, lwords, cw, exported)
940 char *line;
941 int ind;
942 WORD_LIST *lwords;
943 int cw, exported;
944 {
945 char ibuf[INT_STRLEN_BOUND(int) + 1];
946 char *value;
947 SHELL_VAR *v;
948 size_t llen;
949 int c;
950
951 /* Set the variables that the function expects while it executes. Maybe
952 these should be in the function environment (temporary_env). */
953 v = bind_variable ("COMP_LINE", line, 0);
954 if (v && exported)
955 VSETATTR(v, att_exported);
956
957 /* Post bash-4.2: COMP_POINT is characters instead of bytes. */
958 c = line[ind];
959 line[ind] = '\0';
960 llen = MB_STRLEN (line);
961 line[ind] = c;
962 value = inttostr (llen, ibuf, sizeof(ibuf));
963 v = bind_int_variable ("COMP_POINT", value);
964 if (v && exported)
965 VSETATTR(v, att_exported);
966
967 value = inttostr (rl_completion_type, ibuf, sizeof (ibuf));
968 v = bind_int_variable ("COMP_TYPE", value);
969 if (v && exported)
970 VSETATTR(v, att_exported);
971
972 value = inttostr (rl_completion_invoking_key, ibuf, sizeof (ibuf));
973 v = bind_int_variable ("COMP_KEY", value);
974 if (v && exported)
975 VSETATTR(v, att_exported);
976
977 /* Since array variables can't be exported, we don't bother making the
978 array of words. */
979 if (exported == 0)
980 {
981 #ifdef ARRAY_VARS
982 v = bind_comp_words (lwords);
983 value = inttostr (cw, ibuf, sizeof(ibuf));
984 bind_int_variable ("COMP_CWORD", value);
985 #endif
986 }
987 else
988 array_needs_making = 1;
989 }
990
991 static void
992 unbind_compfunc_variables (exported)
993 int exported;
994 {
995 unbind_variable ("COMP_LINE");
996 unbind_variable ("COMP_POINT");
997 unbind_variable ("COMP_TYPE");
998 unbind_variable ("COMP_KEY");
999 #ifdef ARRAY_VARS
1000 unbind_variable ("COMP_WORDS");
1001 unbind_variable ("COMP_CWORD");
1002 #endif
1003 if (exported)
1004 array_needs_making = 1;
1005 }
1006
1007 /* Build the list of words to pass to a function or external command
1008 as arguments. When the function or command is invoked,
1009
1010 $0 == function or command being invoked
1011 $1 == command name
1012 $2 == word to be completed (possibly null)
1013 $3 == previous word
1014
1015 Functions can access all of the words in the current command line
1016 with the COMP_WORDS array. External commands cannot; they have to
1017 make do with the COMP_LINE and COMP_POINT variables. */
1018
1019 static WORD_LIST *
1020 build_arg_list (cmd, cname, text, lwords, ind)
1021 char *cmd;
1022 const char *cname;
1023 const char *text;
1024 WORD_LIST *lwords;
1025 int ind;
1026 {
1027 WORD_LIST *ret, *cl, *l;
1028 WORD_DESC *w;
1029 int i;
1030
1031 ret = (WORD_LIST *)NULL;
1032 w = make_word (cmd);
1033 ret = make_word_list (w, (WORD_LIST *)NULL); /* $0 */
1034
1035 w = make_word (cname); /* $1 */
1036 cl = ret->next = make_word_list (w, (WORD_LIST *)NULL);
1037
1038 w = make_word (text);
1039 cl->next = make_word_list (w, (WORD_LIST *)NULL); /* $2 */
1040 cl = cl->next;
1041
1042 /* Search lwords for current word */
1043 for (l = lwords, i = 1; l && i < ind-1; l = l->next, i++)
1044 ;
1045 w = (l && l->word) ? copy_word (l->word) : make_word ("");
1046 cl->next = make_word_list (w, (WORD_LIST *)NULL);
1047
1048 return ret;
1049 }
1050
1051 /* Build a command string with
1052 $0 == cs->funcname (function to execute for completion list)
1053 $1 == command name (command being completed)
1054 $2 = word to be completed (possibly null)
1055 $3 = previous word
1056 and run in the current shell. The function should put its completion
1057 list into the array variable COMPREPLY. We build a STRINGLIST
1058 from the results and return it.
1059
1060 Since the shell function should return its list of matches in an array
1061 variable, this does nothing if arrays are not compiled into the shell. */
1062
1063 static STRINGLIST *
1064 gen_shell_function_matches (cs, cmd, text, line, ind, lwords, nw, cw, foundp)
1065 COMPSPEC *cs;
1066 const char *cmd;
1067 const char *text;
1068 char *line;
1069 int ind;
1070 WORD_LIST *lwords;
1071 int nw, cw;
1072 int *foundp;
1073 {
1074 char *funcname;
1075 STRINGLIST *sl;
1076 SHELL_VAR *f, *v;
1077 WORD_LIST *cmdlist;
1078 int fval, found;
1079 sh_parser_state_t ps;
1080 sh_parser_state_t * restrict pps;
1081 #if defined (ARRAY_VARS)
1082 ARRAY *a;
1083 #endif
1084
1085 found = 0;
1086 if (foundp)
1087 *foundp = found;
1088
1089 funcname = cs->funcname;
1090 f = find_function (funcname);
1091 if (f == 0)
1092 {
1093 internal_error (_("completion: function `%s' not found"), funcname);
1094 rl_ding ();
1095 rl_on_new_line ();
1096 return ((STRINGLIST *)NULL);
1097 }
1098
1099 #if !defined (ARRAY_VARS)
1100 return ((STRINGLIST *)NULL);
1101 #else
1102
1103 /* We pass cw - 1 because command_line_to_word_list returns indices that are
1104 1-based, while bash arrays are 0-based. */
1105 bind_compfunc_variables (line, ind, lwords, cw - 1, 0);
1106
1107 cmdlist = build_arg_list (funcname, cmd, text, lwords, cw);
1108
1109 pps = &ps;
1110 save_parser_state (pps);
1111 begin_unwind_frame ("gen-shell-function-matches");
1112 add_unwind_protect (restore_parser_state, (char *)pps);
1113 add_unwind_protect (dispose_words, (char *)cmdlist);
1114 add_unwind_protect (unbind_compfunc_variables, (char *)0);
1115
1116 fval = execute_shell_function (f, cmdlist);
1117
1118 discard_unwind_frame ("gen-shell-function-matches");
1119 restore_parser_state (pps);
1120
1121 found = fval != EX_NOTFOUND;
1122 if (fval == EX_RETRYFAIL)
1123 found |= PCOMP_RETRYFAIL;
1124 if (foundp)
1125 *foundp = found;
1126
1127 /* Now clean up and destroy everything. */
1128 dispose_words (cmdlist);
1129 unbind_compfunc_variables (0);
1130
1131 /* The list of completions is returned in the array variable COMPREPLY. */
1132 v = find_variable ("COMPREPLY");
1133 if (v == 0)
1134 return ((STRINGLIST *)NULL);
1135 if (array_p (v) == 0)
1136 v = convert_var_to_array (v);
1137
1138 VUNSETATTR (v, att_invisible);
1139
1140 a = array_cell (v);
1141 if (found == 0 || (found & PCOMP_RETRYFAIL) || a == 0 || array_empty (a))
1142 sl = (STRINGLIST *)NULL;
1143 else
1144 {
1145 /* XXX - should we filter the list of completions so only those matching
1146 TEXT are returned? Right now, we do not. */
1147 sl = strlist_create (0);
1148 sl->list = array_to_argv (a);
1149 sl->list_len = sl->list_size = array_num_elements (a);
1150 }
1151
1152 /* XXX - should we unbind COMPREPLY here? */
1153 unbind_variable ("COMPREPLY");
1154
1155 return (sl);
1156 #endif
1157 }
1158
1159 /* Build a command string with
1160 $0 == cs->command (command to execute for completion list)
1161 $1 == command name (command being completed)
1162 $2 = word to be completed (possibly null)
1163 $3 = previous word
1164 and run in with command substitution. Parse the results, one word
1165 per line, with backslashes allowed to escape newlines. Build a
1166 STRINGLIST from the results and return it. */
1167
1168 static STRINGLIST *
1169 gen_command_matches (cs, cmd, text, line, ind, lwords, nw, cw)
1170 COMPSPEC *cs;
1171 const char *cmd;
1172 const char *text;
1173 char *line;
1174 int ind;
1175 WORD_LIST *lwords;
1176 int nw, cw;
1177 {
1178 char *csbuf, *cscmd, *t;
1179 int cmdlen, cmdsize, n, ws, we;
1180 WORD_LIST *cmdlist, *cl;
1181 WORD_DESC *tw;
1182 STRINGLIST *sl;
1183
1184 bind_compfunc_variables (line, ind, lwords, cw, 1);
1185 cmdlist = build_arg_list (cs->command, cmd, text, lwords, cw);
1186
1187 /* Estimate the size needed for the buffer. */
1188 n = strlen (cs->command);
1189 cmdsize = n + 1;
1190 for (cl = cmdlist->next; cl; cl = cl->next)
1191 cmdsize += STRLEN (cl->word->word) + 3;
1192 cmdsize += 2;
1193
1194 /* allocate the string for the command and fill it in. */
1195 cscmd = (char *)xmalloc (cmdsize + 1);
1196
1197 strcpy (cscmd, cs->command); /* $0 */
1198 cmdlen = n;
1199 cscmd[cmdlen++] = ' ';
1200 for (cl = cmdlist->next; cl; cl = cl->next) /* $1, $2, $3, ... */
1201 {
1202 t = sh_single_quote (cl->word->word ? cl->word->word : "");
1203 n = strlen (t);
1204 RESIZE_MALLOCED_BUFFER (cscmd, cmdlen, n + 2, cmdsize, 64);
1205 strcpy (cscmd + cmdlen, t);
1206 cmdlen += n;
1207 if (cl->next)
1208 cscmd[cmdlen++] = ' ';
1209 free (t);
1210 }
1211 cscmd[cmdlen] = '\0';
1212
1213 tw = command_substitute (cscmd, 0);
1214 csbuf = tw ? tw->word : (char *)NULL;
1215 if (tw)
1216 dispose_word_desc (tw);
1217
1218 /* Now clean up and destroy everything. */
1219 dispose_words (cmdlist);
1220 free (cscmd);
1221 unbind_compfunc_variables (1);
1222
1223 if (csbuf == 0 || *csbuf == '\0')
1224 {
1225 FREE (csbuf);
1226 return ((STRINGLIST *)NULL);
1227 }
1228
1229 /* Now break CSBUF up at newlines, with backslash allowed to escape a
1230 newline, and put the individual words into a STRINGLIST. */
1231 sl = strlist_create (16);
1232 for (ws = 0; csbuf[ws]; )
1233 {
1234 we = ws;
1235 while (csbuf[we] && csbuf[we] != '\n')
1236 {
1237 if (csbuf[we] == '\\' && csbuf[we+1] == '\n')
1238 we++;
1239 we++;
1240 }
1241 t = substring (csbuf, ws, we);
1242 if (sl->list_len >= sl->list_size - 1)
1243 strlist_resize (sl, sl->list_size + 16);
1244 sl->list[sl->list_len++] = t;
1245 while (csbuf[we] == '\n') we++;
1246 ws = we;
1247 }
1248 sl->list[sl->list_len] = (char *)NULL;
1249
1250 free (csbuf);
1251 return (sl);
1252 }
1253
1254 static WORD_LIST *
1255 command_line_to_word_list (line, llen, sentinel, nwp, cwp)
1256 char *line;
1257 int llen, sentinel, *nwp, *cwp;
1258 {
1259 WORD_LIST *ret;
1260 char *delims;
1261
1262 #if 0
1263 delims = "()<>;&| \t\n"; /* shell metacharacters break words */
1264 #else
1265 delims = rl_completer_word_break_characters;
1266 #endif
1267 ret = split_at_delims (line, llen, delims, sentinel, SD_NOQUOTEDELIM, nwp, cwp);
1268 return (ret);
1269 }
1270
1271 /* Evaluate COMPSPEC *cs and return all matches for WORD. */
1272
1273 STRINGLIST *
1274 gen_compspec_completions (cs, cmd, word, start, end, foundp)
1275 COMPSPEC *cs;
1276 const char *cmd;
1277 const char *word;
1278 int start, end;
1279 int *foundp;
1280 {
1281 STRINGLIST *ret, *tmatches;
1282 char *line;
1283 int llen, nw, cw, found, foundf;
1284 WORD_LIST *lwords;
1285 WORD_DESC *lw;
1286 COMPSPEC *tcs;
1287
1288 found = 1;
1289
1290 #ifdef DEBUG
1291 debug_printf ("gen_compspec_completions (%s, %s, %d, %d)", cmd, word, start, end);
1292 debug_printf ("gen_compspec_completions: %s -> %p", cmd, cs);
1293 #endif
1294 ret = gen_action_completions (cs, word);
1295 #ifdef DEBUG
1296 if (ret && progcomp_debug)
1297 {
1298 debug_printf ("gen_action_completions (%p, %s) -->", cs, word);
1299 strlist_print (ret, "\t");
1300 rl_on_new_line ();
1301 }
1302 #endif
1303
1304 /* Now we start generating completions based on the other members of CS. */
1305 if (cs->globpat)
1306 {
1307 tmatches = gen_globpat_matches (cs, word);
1308 if (tmatches)
1309 {
1310 #ifdef DEBUG
1311 if (progcomp_debug)
1312 {
1313 debug_printf ("gen_globpat_matches (%p, %s) -->", cs, word);
1314 strlist_print (tmatches, "\t");
1315 rl_on_new_line ();
1316 }
1317 #endif
1318 ret = strlist_append (ret, tmatches);
1319 strlist_dispose (tmatches);
1320 rl_filename_completion_desired = 1;
1321 }
1322 }
1323
1324 if (cs->words)
1325 {
1326 tmatches = gen_wordlist_matches (cs, word);
1327 if (tmatches)
1328 {
1329 #ifdef DEBUG
1330 if (progcomp_debug)
1331 {
1332 debug_printf ("gen_wordlist_matches (%p, %s) -->", cs, word);
1333 strlist_print (tmatches, "\t");
1334 rl_on_new_line ();
1335 }
1336 #endif
1337 ret = strlist_append (ret, tmatches);
1338 strlist_dispose (tmatches);
1339 }
1340 }
1341
1342 lwords = (WORD_LIST *)NULL;
1343 line = (char *)NULL;
1344 if (cs->command || cs->funcname)
1345 {
1346 /* If we have a command or function to execute, we need to first break
1347 the command line into individual words, find the number of words,
1348 and find the word in the list containing the word to be completed. */
1349 line = substring (rl_line_buffer, start, end);
1350 llen = end - start;
1351
1352 #ifdef DEBUG
1353 debug_printf ("command_line_to_word_list (%s, %d, %d, %p, %p)",
1354 line, llen, rl_point - start, &nw, &cw);
1355 #endif
1356 lwords = command_line_to_word_list (line, llen, rl_point - start, &nw, &cw);
1357 /* If we skipped a NULL word at the beginning of the line, add it back */
1358 if (lwords && lwords->word && cmd[0] == 0 && lwords->word->word[0] != 0)
1359 {
1360 lw = make_bare_word (cmd);
1361 lwords = make_word_list (lw, lwords);
1362 nw++;
1363 cw++;
1364 }
1365 #ifdef DEBUG
1366 if (lwords == 0 && llen > 0)
1367 debug_printf ("ERROR: command_line_to_word_list returns NULL");
1368 else if (progcomp_debug)
1369 {
1370 debug_printf ("command_line_to_word_list -->");
1371 printf ("\t");
1372 print_word_list (lwords, "!");
1373 printf ("\n");
1374 fflush(stdout);
1375 rl_on_new_line ();
1376 }
1377 #endif
1378 }
1379
1380 if (cs->funcname)
1381 {
1382 foundf = 0;
1383 tmatches = gen_shell_function_matches (cs, cmd, word, line, rl_point - start, lwords, nw, cw, &foundf);
1384 if (foundf != 0)
1385 found = foundf;
1386 if (tmatches)
1387 {
1388 #ifdef DEBUG
1389 if (progcomp_debug)
1390 {
1391 debug_printf ("gen_shell_function_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
1392 strlist_print (tmatches, "\t");
1393 rl_on_new_line ();
1394 }
1395 #endif
1396 ret = strlist_append (ret, tmatches);
1397 strlist_dispose (tmatches);
1398 }
1399 }
1400
1401 if (cs->command)
1402 {
1403 tmatches = gen_command_matches (cs, cmd, word, line, rl_point - start, lwords, nw, cw);
1404 if (tmatches)
1405 {
1406 #ifdef DEBUG
1407 if (progcomp_debug)
1408 {
1409 debug_printf ("gen_command_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
1410 strlist_print (tmatches, "\t");
1411 rl_on_new_line ();
1412 }
1413 #endif
1414 ret = strlist_append (ret, tmatches);
1415 strlist_dispose (tmatches);
1416 }
1417 }
1418
1419 if (cs->command || cs->funcname)
1420 {
1421 if (lwords)
1422 dispose_words (lwords);
1423 FREE (line);
1424 }
1425
1426 if (foundp)
1427 *foundp = found;
1428
1429 if (found == 0 || (found & PCOMP_RETRYFAIL))
1430 {
1431 strlist_dispose (ret);
1432 return NULL;
1433 }
1434
1435 if (cs->filterpat)
1436 {
1437 tmatches = filter_stringlist (ret, cs->filterpat, word);
1438 #ifdef DEBUG
1439 if (progcomp_debug)
1440 {
1441 debug_printf ("filter_stringlist (%p, %s, %s) -->", ret, cs->filterpat, word);
1442 strlist_print (tmatches, "\t");
1443 rl_on_new_line ();
1444 }
1445 #endif
1446 if (ret && ret != tmatches)
1447 {
1448 FREE (ret->list);
1449 free (ret);
1450 }
1451 ret = tmatches;
1452 }
1453
1454 if (cs->prefix || cs->suffix)
1455 ret = strlist_prefix_suffix (ret, cs->prefix, cs->suffix);
1456
1457 /* If no matches have been generated and the user has specified that
1458 directory completion should be done as a default, call
1459 gen_action_completions again to generate a list of matching directory
1460 names. */
1461 if ((ret == 0 || ret->list_len == 0) && (cs->options & COPT_DIRNAMES))
1462 {
1463 tcs = compspec_create ();
1464 tcs->actions = CA_DIRECTORY;
1465 FREE (ret);
1466 ret = gen_action_completions (tcs, word);
1467 compspec_dispose (tcs);
1468 }
1469 else if (cs->options & COPT_PLUSDIRS)
1470 {
1471 tcs = compspec_create ();
1472 tcs->actions = CA_DIRECTORY;
1473 tmatches = gen_action_completions (tcs, word);
1474 ret = strlist_append (ret, tmatches);
1475 strlist_dispose (tmatches);
1476 compspec_dispose (tcs);
1477 }
1478
1479 return (ret);
1480 }
1481
1482 void
1483 pcomp_set_readline_variables (flags, nval)
1484 int flags, nval;
1485 {
1486 /* If the user specified that the compspec returns filenames, make
1487 sure that readline knows it. */
1488 if (flags & COPT_FILENAMES)
1489 rl_filename_completion_desired = nval;
1490 /* If the user doesn't want a space appended, tell readline. */
1491 if (flags & COPT_NOSPACE)
1492 rl_completion_suppress_append = nval;
1493 /* The value here is inverted, since the default is on and the `noquote'
1494 option is supposed to turn it off */
1495 if (flags & COPT_NOQUOTE)
1496 rl_filename_quoting_desired = 1 - nval;
1497 }
1498
1499 /* Set or unset FLAGS in the options word of the current compspec.
1500 SET_OR_UNSET is 1 for setting, 0 for unsetting. */
1501 void
1502 pcomp_set_compspec_options (cs, flags, set_or_unset)
1503 COMPSPEC *cs;
1504 int flags, set_or_unset;
1505 {
1506 if (cs == 0 && ((cs = pcomp_curcs) == 0))
1507 return;
1508 if (set_or_unset)
1509 cs->options |= flags;
1510 else
1511 cs->options &= ~flags;
1512 }
1513
1514 static STRINGLIST *
1515 gen_progcomp_completions (ocmd, cmd, word, start, end, foundp, retryp, lastcs)
1516 const char *ocmd;
1517 const char *cmd;
1518 const char *word;
1519 int start, end;
1520 int *foundp, *retryp;
1521 COMPSPEC **lastcs;
1522 {
1523 COMPSPEC *cs, *oldcs;
1524 const char *oldcmd;
1525 STRINGLIST *ret;
1526
1527 cs = progcomp_search (ocmd);
1528
1529 if (cs == 0 || cs == *lastcs)
1530 {
1531 #if 0
1532 if (foundp)
1533 *foundp = 0;
1534 #endif
1535 return (NULL);
1536 }
1537
1538 if (*lastcs)
1539 compspec_dispose (*lastcs);
1540 cs->refcount++; /* XXX */
1541 *lastcs = cs;
1542
1543 cs = compspec_copy (cs);
1544
1545 oldcs = pcomp_curcs;
1546 oldcmd = pcomp_curcmd;
1547
1548 pcomp_curcs = cs;
1549 pcomp_curcmd = cmd;
1550
1551 ret = gen_compspec_completions (cs, cmd, word, start, end, foundp);
1552
1553 pcomp_curcs = oldcs;
1554 pcomp_curcmd = oldcmd;
1555
1556 /* We need to conditionally handle setting *retryp here */
1557 if (retryp)
1558 *retryp = foundp && (*foundp & PCOMP_RETRYFAIL);
1559
1560 if (foundp)
1561 {
1562 *foundp &= ~PCOMP_RETRYFAIL;
1563 *foundp |= cs->options;
1564 }
1565
1566 compspec_dispose (cs);
1567 return ret;
1568 }
1569
1570 /* The driver function for the programmable completion code. Returns a list
1571 of matches for WORD, which is an argument to command CMD. START and END
1572 bound the command currently being completed in rl_line_buffer. */
1573 char **
1574 programmable_completions (cmd, word, start, end, foundp)
1575 const char *cmd;
1576 const char *word;
1577 int start, end, *foundp;
1578 {
1579 COMPSPEC *cs, *lastcs;
1580 STRINGLIST *ret;
1581 char **rmatches, *t;
1582 int found, retry, count;
1583
1584 lastcs = 0;
1585 found = count = 0;
1586
1587 do
1588 {
1589 retry = 0;
1590
1591 /* We look at the basename of CMD if the full command does not have
1592 an associated COMPSPEC. */
1593 ret = gen_progcomp_completions (cmd, cmd, word, start, end, &found, &retry, &lastcs);
1594 if (found == 0)
1595 {
1596 t = strrchr (cmd, '/');
1597 if (t && *(++t))
1598 ret = gen_progcomp_completions (t, cmd, word, start, end, &found, &retry, &lastcs);
1599 }
1600
1601 if (found == 0)
1602 ret = gen_progcomp_completions (DEFAULTCMD, cmd, word, start, end, &found, &retry, &lastcs);
1603
1604 count++;
1605
1606 if (count > 32)
1607 {
1608 internal_warning ("programmable_completion: %s: possible retry loop", cmd);
1609 break;
1610 }
1611 }
1612 while (retry);
1613
1614 if (ret)
1615 {
1616 rmatches = ret->list;
1617 free (ret);
1618 }
1619 else
1620 rmatches = (char **)NULL;
1621
1622 if (foundp)
1623 *foundp = found;
1624
1625 if (lastcs) /* XXX - should be while? */
1626 compspec_dispose (lastcs);
1627
1628 return (rmatches);
1629 }
1630
1631 #endif /* PROGRAMMABLE_COMPLETION */