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