blob: 17d37d51ba07213843d7358994664415e45ee67f [file] [log] [blame]
Jari Aaltobb706242000-03-17 21:46:59 +00001/* pcomplete.c - functions to generate lists of matches for programmable
2 completion. */
3
4/* Copyright (C) 1999 Free Software Foundation, Inc.
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
38# if defined (PREFER_VARARGS)
39# include <varargs.h>
40# endif
41#endif
42
43#include <stdio.h>
44#include "bashansi.h"
45
46#include "shell.h"
47#include "pcomplete.h"
48#include "alias.h"
49#include "bashline.h"
Jari Aaltof73dda02001-11-13 17:56:06 +000050#include "execute_cmd.h"
Jari Aaltobb706242000-03-17 21:46:59 +000051#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 "builtins.h"
62#include "builtins/common.h"
63
64#include <glob/glob.h>
Jari Aaltof73dda02001-11-13 17:56:06 +000065#include <glob/strmatch.h>
Jari Aaltobb706242000-03-17 21:46:59 +000066
67#include <readline/rlconf.h>
68#include <readline/readline.h>
69#include <readline/history.h>
70
71#ifdef STRDUP
72# undef STRDUP
73#endif
74#define STRDUP(x) ((x) ? savestring (x) : (char *)NULL)
75
76typedef SHELL_VAR **SVFUNC ();
77
78#ifndef HAVE_STRPBRK
79extern char *strpbrk __P((char *, char *));
80#endif
81
Jari Aaltobb706242000-03-17 21:46:59 +000082extern int array_needs_making;
83extern STRING_INT_ALIST word_token_alist[];
84extern char *signal_names[];
85
Jari Aaltof73dda02001-11-13 17:56:06 +000086#if defined(PREFER_STDARG)
87static void debug_printf (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
88#endif
89
90static int it_init_joblist __P((ITEMLIST *, int));
91
92static int it_init_aliases __P((ITEMLIST *));
93static int it_init_arrayvars __P((ITEMLIST *));
94static int it_init_bindings __P((ITEMLIST *));
95static int it_init_builtins __P((ITEMLIST *));
96static int it_init_disabled __P((ITEMLIST *));
97static int it_init_enabled __P((ITEMLIST *));
98static int it_init_exported __P((ITEMLIST *));
99static int it_init_functions __P((ITEMLIST *));
100static int it_init_hostnames __P((ITEMLIST *));
101static int it_init_jobs __P((ITEMLIST *));
102static int it_init_running __P((ITEMLIST *));
103static int it_init_stopped __P((ITEMLIST *));
104static int it_init_keywords __P((ITEMLIST *));
105static int it_init_signals __P((ITEMLIST *));
106static int it_init_variables __P((ITEMLIST *));
107static int it_init_setopts __P((ITEMLIST *));
108static int it_init_shopts __P((ITEMLIST *));
109
110static int shouldexp_filterpat __P((char *));
111static char *preproc_filterpat __P((char *, char *));
112
113static void init_itemlist_from_varlist __P((ITEMLIST *, SVFUNC *));
114
115static STRINGLIST *gen_matches_from_itemlist __P((ITEMLIST *, const char *));
116static STRINGLIST *gen_action_completions __P((COMPSPEC *, const char *));
117static STRINGLIST *gen_globpat_matches __P((COMPSPEC *, const char *));
118static STRINGLIST *gen_wordlist_matches __P((COMPSPEC *, const char *));
119static STRINGLIST *gen_shell_function_matches __P((COMPSPEC *, const char *,
120 char *, int, WORD_LIST *,
121 int, int));
122static STRINGLIST *gen_command_matches __P((COMPSPEC *, const char *, char *,
123 int, WORD_LIST *, int, int));
124
125static char *pcomp_filename_completion_function __P((const char *, int));
126
127#if defined (ARRAY_VARS)
128static SHELL_VAR *bind_comp_words __P((WORD_LIST *));
129#endif
130static void bind_compfunc_variables __P((char *, int, WORD_LIST *, int, int));
131static void unbind_compfunc_variables __P((int));
132static WORD_LIST *build_arg_list __P((char *, const char *, WORD_LIST *, int));
133static WORD_LIST *command_line_to_word_list __P((char *, int, int, int *, int *));
Jari Aaltobb706242000-03-17 21:46:59 +0000134
135static int progcomp_debug = 0;
136
137int prog_completion_enabled = 1;
138
139/* These are used to manage the arrays of strings for possible completions. */
140ITEMLIST it_aliases = { 0, it_init_aliases, (STRINGLIST *)0 };
141ITEMLIST it_arrayvars = { LIST_DYNAMIC, it_init_arrayvars, (STRINGLIST *)0 };
142ITEMLIST it_bindings = { 0, it_init_bindings, (STRINGLIST *)0 };
143ITEMLIST it_builtins = { 0, it_init_builtins, (STRINGLIST *)0 };
144ITEMLIST it_commands = { LIST_DYNAMIC }; /* unused */
145ITEMLIST it_directories = { LIST_DYNAMIC }; /* unused */
146ITEMLIST it_disabled = { 0, it_init_disabled, (STRINGLIST *)0 };
147ITEMLIST it_enabled = { 0, it_init_enabled, (STRINGLIST *)0 };
148ITEMLIST it_exports = { LIST_DYNAMIC, it_init_exported, (STRINGLIST *)0 };
149ITEMLIST it_files = { LIST_DYNAMIC }; /* unused */
150ITEMLIST it_functions = { 0, it_init_functions, (STRINGLIST *)0 };
151ITEMLIST it_hostnames = { LIST_DYNAMIC, it_init_hostnames, (STRINGLIST *)0 };
Jari Aaltof73dda02001-11-13 17:56:06 +0000152ITEMLIST it_groups = { LIST_DYNAMIC }; /* unused */
153ITEMLIST it_jobs = { LIST_DYNAMIC, it_init_jobs, (STRINGLIST *)0 };
Jari Aaltobb706242000-03-17 21:46:59 +0000154ITEMLIST it_keywords = { 0, it_init_keywords, (STRINGLIST *)0 };
155ITEMLIST it_running = { LIST_DYNAMIC, it_init_running, (STRINGLIST *)0 };
156ITEMLIST it_setopts = { 0, it_init_setopts, (STRINGLIST *)0 };
157ITEMLIST it_shopts = { 0, it_init_shopts, (STRINGLIST *)0 };
158ITEMLIST it_signals = { 0, it_init_signals, (STRINGLIST *)0 };
159ITEMLIST it_stopped = { LIST_DYNAMIC, it_init_stopped, (STRINGLIST *)0 };
160ITEMLIST it_users = { LIST_DYNAMIC }; /* unused */
161ITEMLIST it_variables = { LIST_DYNAMIC, it_init_variables, (STRINGLIST *)0 };
162
163/* Debugging code */
164#if !defined (USE_VARARGS)
165static void
166debug_printf (format, arg1, arg2, arg3, arg4, arg5)
167 char *format;
168{
169 if (progcomp_debug == 0)
170 return;
171
172 fprintf (stdout, format, arg1, arg2, arg3, arg4, arg5);
173 fprintf (stdout, "\n");
174 rl_on_new_line ();
175}
176#else
177static void
178#if defined (PREFER_STDARG)
179debug_printf (const char *format, ...)
180#else
181debug_printf (format, va_alist)
182 const char *format;
183 va_dcl
184#endif
185{
186 va_list args;
187
188 if (progcomp_debug == 0)
189 return;
190
191#if defined (PREFER_STDARG)
192 va_start (args, format);
193#else
194 va_start (args);
195#endif
196
197 fprintf (stdout, "DEBUG: ");
198 vfprintf (stdout, format, args);
199 fprintf (stdout, "\n");
200
201 rl_on_new_line ();
202
203 va_end (args);
204}
205#endif /* USE_VARARGS */
206
207/* Functions to manage the item lists */
208
209void
210set_itemlist_dirty (it)
211 ITEMLIST *it;
212{
213 it->flags |= LIST_DIRTY;
214}
215
216void
217initialize_itemlist (itp)
218 ITEMLIST *itp;
219{
220 (*itp->list_getter) (itp);
221 itp->flags |= LIST_INITIALIZED;
222 itp->flags &= ~LIST_DIRTY;
223}
224
225void
226clean_itemlist (itp)
227 ITEMLIST *itp;
228{
229 STRINGLIST *sl;
230
231 sl = itp->slist;
232 if (sl)
233 {
234 if ((itp->flags & (LIST_DONTFREEMEMBERS|LIST_DONTFREE)) == 0)
235 free_array_members (sl->list);
236 if ((itp->flags & LIST_DONTFREE) == 0)
237 free (sl->list);
238 free (sl);
239 }
240 itp->slist = (STRINGLIST *)NULL;
241 itp->flags &= ~(LIST_DONTFREE|LIST_DONTFREEMEMBERS|LIST_INITIALIZED|LIST_DIRTY);
242}
243
Jari Aaltobb706242000-03-17 21:46:59 +0000244
245static int
246shouldexp_filterpat (s)
247 char *s;
248{
249 register char *p;
250
251 for (p = s; p && *p; p++)
252 {
253 if (*p == '\\')
254 p++;
255 else if (*p == '&')
256 return 1;
257 }
258 return 0;
259}
260
261/* Replace any instance of `&' in PAT with TEXT. Backslash may be used to
262 quote a `&' and inhibit substitution. Returns a new string. This just
263 calls stringlib.c:strcreplace(). */
264static char *
265preproc_filterpat (pat, text)
266 char *pat;
267 char *text;
268{
269 char *ret;
270
271 ret = strcreplace (pat, '&', text, 1);
272 return ret;
273}
274
275/* Remove any match of FILTERPAT from SL. A `&' in FILTERPAT is replaced by
276 TEXT. A leading `!' in FILTERPAT negates the pattern; in this case
277 any member of SL->list that does *not* match will be removed. This returns
278 a new STRINGLIST with the matching members of SL *copied*. Any
279 non-matching members of SL->list are *freed*. */
280STRINGLIST *
281filter_stringlist (sl, filterpat, text)
282 STRINGLIST *sl;
283 char *filterpat, *text;
284{
285 int i, m, not;
286 STRINGLIST *ret;
287 char *npat, *t;
288
289 if (sl == 0 || sl->list == 0 || sl->list_len == 0)
290 return sl;
291
292 npat = shouldexp_filterpat (filterpat) ? preproc_filterpat (filterpat, text) : filterpat;
293
294 not = (npat[0] == '!');
295 t = not ? npat + 1 : npat;
296
297 ret = alloc_stringlist (sl->list_size);
298 for (i = 0; i < sl->list_len; i++)
299 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000300 m = strmatch (t, sl->list[i], FNMATCH_EXTFLAG);
Jari Aaltobb706242000-03-17 21:46:59 +0000301 if ((not && m == FNM_NOMATCH) || (not == 0 && m != FNM_NOMATCH))
302 free (sl->list[i]);
303 else
304 ret->list[ret->list_len++] = sl->list[i];
305 }
306
307 ret->list[ret->list_len] = (char *)NULL;
308 if (npat != filterpat)
309 free (npat);
310
311 return ret;
312}
313
Jari Aalto28ef6c32001-04-06 19:14:31 +0000314/* Turn an array of strings returned by rl_completion_matches into a STRINGLIST.
315 This understands how rl_completion_matches sets matches[0] (the lcd of the
Jari Aaltobb706242000-03-17 21:46:59 +0000316 strings in the list, unless it's the only match). */
317STRINGLIST *
318completions_to_stringlist (matches)
319 char **matches;
320{
321 STRINGLIST *sl;
322 int mlen, i, n;
323
324 mlen = (matches == 0) ? 0 : array_len (matches);
325 sl = alloc_stringlist (mlen + 1);
326
327 if (matches == 0 || matches[0] == 0)
328 return sl;
329
330 if (matches[1] == 0)
331 {
332 sl->list[0] = STRDUP (matches[0]);
333 sl->list[sl->list_len = 1] = (char *)NULL;
334 return sl;
335 }
336
337 for (i = 1, n = 0; i < mlen; i++, n++)
338 sl->list[n] = STRDUP (matches[i]);
339 sl->list_len = n;
340 sl->list[n] = (char *)NULL;
341
342 return sl;
343}
344
345/* Functions to manage the various ITEMLISTs that we populate internally.
346 The caller is responsible for setting ITP->flags correctly. */
347
348static int
349it_init_aliases (itp)
350 ITEMLIST *itp;
351{
352#ifdef ALIAS
Jari Aaltof73dda02001-11-13 17:56:06 +0000353 alias_t **alias_list;
Jari Aaltobb706242000-03-17 21:46:59 +0000354 register int i, n;
355 STRINGLIST *sl;
356
Jari Aaltof73dda02001-11-13 17:56:06 +0000357 alias_list = all_aliases ();
358 if (alias_list == 0)
Jari Aaltobb706242000-03-17 21:46:59 +0000359 {
360 itp->slist = (STRINGLIST *)NULL;
361 return 0;
362 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000363 for (n = 0; alias_list[n]; n++)
Jari Aaltobb706242000-03-17 21:46:59 +0000364 ;
365 sl = alloc_stringlist (n+1);
366 for (i = 0; i < n; i++)
Jari Aaltof73dda02001-11-13 17:56:06 +0000367 sl->list[i] = STRDUP (alias_list[i]->name);
Jari Aaltobb706242000-03-17 21:46:59 +0000368 sl->list[n] = (char *)NULL;
369 sl->list_size = sl->list_len = n;
370 itp->slist = sl;
371#else
372 itp->slist = (STRINGLIST *)NULL;
373#endif
374 return 1;
375}
376
377static void
378init_itemlist_from_varlist (itp, svfunc)
379 ITEMLIST *itp;
380 SVFUNC *svfunc;
381{
382 SHELL_VAR **vlist;
383 STRINGLIST *sl;
384 register int i, n;
385
386 vlist = (*svfunc) ();
387 for (n = 0; vlist[n]; n++)
388 ;
389 sl = alloc_stringlist (n+1);
390 for (i = 0; i < n; i++)
391 sl->list[i] = savestring (vlist[i]->name);
392 sl->list[sl->list_len = n] = (char *)NULL;
393 itp->slist = sl;
394}
395
396static int
397it_init_arrayvars (itp)
398 ITEMLIST *itp;
399{
400#if defined (ARRAY_VARS)
401 init_itemlist_from_varlist (itp, all_array_variables);
402 return 1;
403#else
404 return 0;
405#endif
406}
407
408static int
409it_init_bindings (itp)
410 ITEMLIST *itp;
411{
412 char **blist;
413 STRINGLIST *sl;
414
415 /* rl_funmap_names allocates blist, but not its members */
Jari Aaltof73dda02001-11-13 17:56:06 +0000416 blist = (char **)rl_funmap_names (); /* XXX fix const later */
Jari Aaltobb706242000-03-17 21:46:59 +0000417 sl = alloc_stringlist (0);
418 sl->list = blist;
419 sl->list_size = 0;
420 sl->list_len = array_len (sl->list);
421 itp->flags |= LIST_DONTFREEMEMBERS;
422 itp->slist = sl;
423
424 return 0;
425}
426
427static int
428it_init_builtins (itp)
429 ITEMLIST *itp;
430{
431 STRINGLIST *sl;
Jari Aaltobb706242000-03-17 21:46:59 +0000432 register int i, n;
433
434 sl = alloc_stringlist (num_shell_builtins);
435 for (i = n = 0; i < num_shell_builtins; i++)
436 if (shell_builtins[i].function)
437 sl->list[n++] = shell_builtins[i].name;
438 sl->list[sl->list_len = n] = (char *)NULL;
439 itp->flags |= LIST_DONTFREEMEMBERS;
440 itp->slist = sl;
441 return 0;
442}
443
444static int
445it_init_enabled (itp)
446 ITEMLIST *itp;
447{
448 STRINGLIST *sl;
Jari Aaltobb706242000-03-17 21:46:59 +0000449 register int i, n;
450
451 sl = alloc_stringlist (num_shell_builtins);
452 for (i = n = 0; i < num_shell_builtins; i++)
453 {
454 if (shell_builtins[i].function && (shell_builtins[i].flags & BUILTIN_ENABLED))
455 sl->list[n++] = shell_builtins[i].name;
456 }
457 sl->list[sl->list_len = n] = (char *)NULL;
458 itp->flags |= LIST_DONTFREEMEMBERS;
459 itp->slist = sl;
460 return 0;
461}
462
463static int
464it_init_disabled (itp)
465 ITEMLIST *itp;
466{
467 STRINGLIST *sl;
Jari Aaltobb706242000-03-17 21:46:59 +0000468 register int i, n;
469
470 sl = alloc_stringlist (num_shell_builtins);
471 for (i = n = 0; i < num_shell_builtins; i++)
472 {
473 if (shell_builtins[i].function && ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
474 sl->list[n++] = shell_builtins[i].name;
475 }
476 sl->list[sl->list_len = n] = (char *)NULL;
477 itp->flags |= LIST_DONTFREEMEMBERS;
478 itp->slist = sl;
479 return 0;
480}
481
482static int
483it_init_exported (itp)
484 ITEMLIST *itp;
485{
486 init_itemlist_from_varlist (itp, all_exported_variables);
487 return 0;
488}
489
490static int
491it_init_functions (itp)
492 ITEMLIST *itp;
493{
494 init_itemlist_from_varlist (itp, all_visible_functions);
495 return 0;
496}
497
498static int
499it_init_hostnames (itp)
500 ITEMLIST *itp;
501{
502 STRINGLIST *sl;
503
504 sl = alloc_stringlist (0);
505 sl->list = get_hostname_list ();
506 sl->list_len = sl->list ? array_len (sl->list) : 0;
507 sl->list_size = sl->list_len;
508 itp->slist = sl;
509 itp->flags |= LIST_DONTFREEMEMBERS|LIST_DONTFREE;
510 return 0;
511}
512
513static int
514it_init_joblist (itp, jstate)
515 ITEMLIST *itp;
516 int jstate;
517{
518#if defined (JOB_CONTROL)
519 STRINGLIST *sl;
Jari Aaltof73dda02001-11-13 17:56:06 +0000520 register int i;
Jari Aaltobb706242000-03-17 21:46:59 +0000521 register PROCESS *p;
522 char *s, *t;
523 JOB_STATE js;
524
525 if (jstate == 0)
526 js = JRUNNING;
527 else if (jstate == 1)
528 js = JSTOPPED;
529
530 sl = alloc_stringlist (job_slots);
531 for (i = job_slots - 1; i >= 0; i--)
532 {
533 if (jobs[i] == 0)
534 continue;
535 p = jobs[i]->pipe;
536 if (jstate == -1 || JOBSTATE(i) == js)
537 {
538 s = savestring (p->command);
539 t = strpbrk (s, " \t\n");
540 if (t)
541 *t = '\0';
Jari Aalto28ef6c32001-04-06 19:14:31 +0000542 sl->list[sl->list_len++] = s;
Jari Aaltobb706242000-03-17 21:46:59 +0000543 }
544 }
545 itp->slist = sl;
546#else
547 itp->slist = (STRINGLIST *)NULL;
548#endif
549 return 0;
550}
551
552static int
553it_init_jobs (itp)
554 ITEMLIST *itp;
555{
556 return (it_init_joblist (itp, -1));
557}
558
559static int
560it_init_running (itp)
561 ITEMLIST *itp;
562{
563 return (it_init_joblist (itp, 0));
564}
565
566static int
567it_init_stopped (itp)
568 ITEMLIST *itp;
569{
570 return (it_init_joblist (itp, 1));
571}
572
573static int
574it_init_keywords (itp)
575 ITEMLIST *itp;
576{
577 STRINGLIST *sl;
578 register int i, n;
579
580 for (n = 0; word_token_alist[n].word; n++)
581 ;
582 sl = alloc_stringlist (n);
583 for (i = 0; i < n; i++)
584 sl->list[i] = word_token_alist[i].word;
585 sl->list[sl->list_len = i] = (char *)NULL;
586 itp->flags |= LIST_DONTFREEMEMBERS;
587 itp->slist = sl;
588 return 0;
589}
590
591static int
592it_init_signals (itp)
593 ITEMLIST *itp;
594{
595 STRINGLIST *sl;
596
597 sl = alloc_stringlist (0);
598 sl->list = signal_names;
599 sl->list_len = array_len (sl->list);
600 itp->flags |= LIST_DONTFREE;
601 itp->slist = sl;
602 return 0;
603}
604
605static int
606it_init_variables (itp)
607 ITEMLIST *itp;
608{
609 init_itemlist_from_varlist (itp, all_visible_variables);
610 return 0;
611}
612
613static int
614it_init_setopts (itp)
615 ITEMLIST *itp;
616{
617 STRINGLIST *sl;
618
619 sl = alloc_stringlist (0);
620 sl->list = get_minus_o_opts ();
621 sl->list_len = array_len (sl->list);
622 itp->slist = sl;
623 itp->flags |= LIST_DONTFREEMEMBERS;
624 return 0;
625}
626
627static int
628it_init_shopts (itp)
629 ITEMLIST *itp;
630{
631 STRINGLIST *sl;
632
633 sl = alloc_stringlist (0);
634 sl->list = get_shopt_options ();
635 sl->list_len = array_len (sl->list);
636 itp->slist = sl;
637 itp->flags |= LIST_DONTFREEMEMBERS;
638 return 0;
639}
640
641/* Generate a list of all matches for TEXT using the STRINGLIST in itp->slist
642 as the list of possibilities. If the itemlist has been marked dirty or
643 it should be regenerated every time, destroy the old STRINGLIST and make a
644 new one before trying the match. */
645static STRINGLIST *
646gen_matches_from_itemlist (itp, text)
647 ITEMLIST *itp;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000648 const char *text;
Jari Aaltobb706242000-03-17 21:46:59 +0000649{
650 STRINGLIST *ret, *sl;
651 int tlen, i, n;
652
653 if ((itp->flags & (LIST_DIRTY|LIST_DYNAMIC)) ||
654 (itp->flags & LIST_INITIALIZED) == 0)
655 {
656 if (itp->flags & (LIST_DIRTY | LIST_DYNAMIC))
657 clean_itemlist (itp);
658 if ((itp->flags & LIST_INITIALIZED) == 0)
659 initialize_itemlist (itp);
660 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000661 if (itp->slist == 0)
662 return ((STRINGLIST *)NULL);
Jari Aaltobb706242000-03-17 21:46:59 +0000663 ret = alloc_stringlist (itp->slist->list_len+1);
664 sl = itp->slist;
665 tlen = STRLEN (text);
666 for (i = n = 0; i < sl->list_len; i++)
667 {
668 if (tlen == 0 || STREQN (sl->list[i], text, tlen))
669 ret->list[n++] = STRDUP (sl->list[i]);
670 }
671 ret->list[ret->list_len = n] = (char *)NULL;
672 return ret;
673}
674
Jari Aalto28ef6c32001-04-06 19:14:31 +0000675/* A wrapper for rl_filename_completion_function that dequotes the filename
Jari Aaltobb706242000-03-17 21:46:59 +0000676 before attempting completions. */
677static char *
678pcomp_filename_completion_function (text, state)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000679 const char *text;
Jari Aaltobb706242000-03-17 21:46:59 +0000680 int state;
681{
682 static char *dfn; /* dequoted filename */
683 int qc;
684
685 if (state == 0)
686 {
687 FREE (dfn);
688 /* remove backslashes quoting special characters in filenames. */
689 if (rl_filename_dequoting_function)
690 {
691 qc = (text[0] == '"' || text[0] == '\'') ? text[0] : 0;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000692 dfn = (*rl_filename_dequoting_function) ((char *)text, qc);
Jari Aaltobb706242000-03-17 21:46:59 +0000693 }
694 else
695 dfn = savestring (text);
696 }
697
Jari Aalto28ef6c32001-04-06 19:14:31 +0000698 return (rl_filename_completion_function (dfn, state));
Jari Aaltobb706242000-03-17 21:46:59 +0000699}
700
701#define GEN_COMPS(bmap, flag, it, text, glist, tlist) \
702 do { \
703 if (bmap & flag) \
704 { \
705 tlist = gen_matches_from_itemlist (it, text); \
Jari Aaltof73dda02001-11-13 17:56:06 +0000706 if (tlist) \
707 { \
708 glist = append_stringlist (glist, tlist); \
709 free_stringlist (tlist); \
710 } \
Jari Aaltobb706242000-03-17 21:46:59 +0000711 } \
712 } while (0)
713
714#define GEN_XCOMPS(bmap, flag, text, func, cmatches, glist, tlist) \
715 do { \
716 if (bmap & flag) \
717 { \
Jari Aalto28ef6c32001-04-06 19:14:31 +0000718 cmatches = rl_completion_matches (text, func); \
Jari Aaltobb706242000-03-17 21:46:59 +0000719 tlist = completions_to_stringlist (cmatches); \
720 glist = append_stringlist (glist, tlist); \
721 free_array (cmatches); \
722 free_stringlist (tlist); \
723 } \
724 } while (0)
725
726/* Functions to generate lists of matches from the actions member of CS. */
727
728static STRINGLIST *
729gen_action_completions (cs, text)
730 COMPSPEC *cs;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000731 const char *text;
Jari Aaltobb706242000-03-17 21:46:59 +0000732{
733 STRINGLIST *ret, *tmatches;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000734 char **cmatches; /* from rl_completion_matches ... */
Jari Aaltobb706242000-03-17 21:46:59 +0000735 unsigned long flags;
736
737 ret = tmatches = (STRINGLIST *)NULL;
738 flags = cs->actions;
739
740 GEN_COMPS (flags, CA_ALIAS, &it_aliases, text, ret, tmatches);
741 GEN_COMPS (flags, CA_ARRAYVAR, &it_arrayvars, text, ret, tmatches);
742 GEN_COMPS (flags, CA_BINDING, &it_bindings, text, ret, tmatches);
743 GEN_COMPS (flags, CA_BUILTIN, &it_builtins, text, ret, tmatches);
744 GEN_COMPS (flags, CA_DISABLED, &it_disabled, text, ret, tmatches);
745 GEN_COMPS (flags, CA_ENABLED, &it_enabled, text, ret, tmatches);
746 GEN_COMPS (flags, CA_EXPORT, &it_exports, text, ret, tmatches);
747 GEN_COMPS (flags, CA_FUNCTION, &it_functions, text, ret, tmatches);
748 GEN_COMPS (flags, CA_HOSTNAME, &it_hostnames, text, ret, tmatches);
749 GEN_COMPS (flags, CA_JOB, &it_jobs, text, ret, tmatches);
750 GEN_COMPS (flags, CA_KEYWORD, &it_keywords, text, ret, tmatches);
751 GEN_COMPS (flags, CA_RUNNING, &it_running, text, ret, tmatches);
752 GEN_COMPS (flags, CA_SETOPT, &it_setopts, text, ret, tmatches);
753 GEN_COMPS (flags, CA_SHOPT, &it_shopts, text, ret, tmatches);
754 GEN_COMPS (flags, CA_SIGNAL, &it_signals, text, ret, tmatches);
755 GEN_COMPS (flags, CA_STOPPED, &it_stopped, text, ret, tmatches);
756 GEN_COMPS (flags, CA_VARIABLE, &it_variables, text, ret, tmatches);
757
758 GEN_XCOMPS(flags, CA_COMMAND, text, command_word_completion_function, cmatches, ret, tmatches);
759 GEN_XCOMPS(flags, CA_FILE, text, pcomp_filename_completion_function, cmatches, ret, tmatches);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000760 GEN_XCOMPS(flags, CA_USER, text, rl_username_completion_function, cmatches, ret, tmatches);
Jari Aaltof73dda02001-11-13 17:56:06 +0000761 GEN_XCOMPS(flags, CA_GROUP, text, bash_groupname_completion_function, cmatches, ret, tmatches);
Jari Aaltobb706242000-03-17 21:46:59 +0000762
763 /* And lastly, the special case for directories */
764 if (flags & CA_DIRECTORY)
765 {
766 cmatches = bash_directory_completion_matches (text);
767 tmatches = completions_to_stringlist (cmatches);
768 ret = append_stringlist (ret, tmatches);
769 free_array (cmatches);
770 free_stringlist (tmatches);
771 }
772
773 return ret;
774}
775
776/* Generate a list of matches for CS->globpat. Unresolved: should this use
777 TEXT as a match prefix, or just go without? Currently, the code does not
778 use TEXT, just globs CS->globpat and returns the results. If we do decide
779 to use TEXT, we should call quote_string_for_globbing before the call to
780 glob_filename. */
781static STRINGLIST *
782gen_globpat_matches (cs, text)
783 COMPSPEC *cs;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000784 const char *text;
Jari Aaltobb706242000-03-17 21:46:59 +0000785{
786 STRINGLIST *sl;
Jari Aaltobb706242000-03-17 21:46:59 +0000787
788 sl = alloc_stringlist (0);
789 sl->list = glob_filename (cs->globpat);
790 if (GLOB_FAILED (sl->list))
791 sl->list = (char **)NULL;
792 if (sl->list)
793 sl->list_len = sl->list_size = array_len (sl->list);
794 return sl;
795}
796
797/* Perform the shell word expansions on CS->words and return the results.
798 Again, this ignores TEXT. */
799static STRINGLIST *
800gen_wordlist_matches (cs, text)
801 COMPSPEC *cs;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000802 const char *text;
Jari Aaltobb706242000-03-17 21:46:59 +0000803{
804 WORD_LIST *l, *l2;
805 STRINGLIST *sl;
806 int nw, tlen;
807
808 if (cs->words == 0 || cs->words[0] == '\0')
809 return ((STRINGLIST *)NULL);
810
811 /* This used to be a simple expand_string(cs->words, 0), but that won't
812 do -- there's no way to split a simple list into individual words
813 that way, since the shell semantics say that word splitting is done
814 only on the results of expansion. */
815 l = split_at_delims (cs->words, strlen (cs->words), (char *)NULL, -1, (int *)NULL, (int *)NULL);
816 if (l == 0)
817 return ((STRINGLIST *)NULL);
818 /* This will jump back to the top level if the expansion fails... */
819 l2 = expand_words_shellexp (l);
820 dispose_words (l);
821
822 nw = list_length (l2);
823 sl = alloc_stringlist (nw + 1);
824 tlen = STRLEN (text);
825
826 for (nw = 0, l = l2; l; l = l->next)
827 {
828 if (tlen == 0 || STREQN (l->word->word, text, tlen))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000829 sl->list[nw++] = STRDUP (l->word->word);
Jari Aaltobb706242000-03-17 21:46:59 +0000830 }
831 sl->list[sl->list_len = nw] = (char *)NULL;
832
833 return sl;
834}
835
836#ifdef ARRAY_VARS
837
838static SHELL_VAR *
839bind_comp_words (lwords)
840 WORD_LIST *lwords;
841{
842 SHELL_VAR *v;
843
844 v = find_variable ("COMP_WORDS");
845 if (v == 0)
846 v = make_new_array_variable ("COMP_WORDS");
847 if (readonly_p (v))
848 VUNSETATTR (v, att_readonly);
849 if (array_p (v) == 0)
850 v = convert_var_to_array (v);
851 v = assign_array_var_from_word_list (v, lwords);
852 return v;
853}
854#endif /* ARRAY_VARS */
855
856static void
857bind_compfunc_variables (line, ind, lwords, cw, exported)
858 char *line;
859 int ind;
860 WORD_LIST *lwords;
861 int cw, exported;
862{
Jari Aaltof73dda02001-11-13 17:56:06 +0000863 char ibuf[INT_STRLEN_BOUND(int) + 1];
Jari Aaltobb706242000-03-17 21:46:59 +0000864 char *value;
865 SHELL_VAR *v;
866
867 /* Set the variables that the function expects while it executes. Maybe
868 these should be in the function environment (temporary_env). */
869 v = bind_variable ("COMP_LINE", line);
870 if (v && exported)
871 VSETATTR(v, att_exported);
872
Jari Aaltof73dda02001-11-13 17:56:06 +0000873 value = inttostr (ind, ibuf, sizeof(ibuf));
Jari Aaltobb706242000-03-17 21:46:59 +0000874 v = bind_int_variable ("COMP_POINT", value);
875 if (v && exported)
876 VSETATTR(v, att_exported);
877
878 /* Since array variables can't be exported, we don't bother making the
879 array of words. */
880 if (exported == 0)
881 {
882#ifdef ARRAY_VARS
883 v = bind_comp_words (lwords);
Jari Aaltof73dda02001-11-13 17:56:06 +0000884 value = inttostr (cw, ibuf, sizeof(ibuf));
Jari Aaltobb706242000-03-17 21:46:59 +0000885 bind_int_variable ("COMP_CWORD", value);
886#endif
887 }
888 else
889 array_needs_making = 1;
890}
891
892static void
893unbind_compfunc_variables (exported)
894 int exported;
895{
896 makunbound ("COMP_LINE", shell_variables);
897 makunbound ("COMP_POINT", shell_variables);
898#ifdef ARRAY_VARS
899 makunbound ("COMP_WORDS", shell_variables);
900 makunbound ("COMP_CWORD", shell_variables);
901#endif
902 if (exported)
903 array_needs_making = 1;
904}
905
906/* Build the list of words to pass to a function or external command
907 as arguments. When the function or command is invoked,
908
909 $0 == function or command being invoked
910 $1 == command name
911 $2 = word to be completed (possibly null)
912 $3 = previous word
913
914 Functions can access all of the words in the current command line
915 with the COMP_WORDS array. External commands cannot. */
916
917static WORD_LIST *
918build_arg_list (cmd, text, lwords, ind)
919 char *cmd;
Jari Aaltof73dda02001-11-13 17:56:06 +0000920 const char *text;
Jari Aaltobb706242000-03-17 21:46:59 +0000921 WORD_LIST *lwords;
922 int ind;
923{
924 WORD_LIST *ret, *cl, *l;
925 WORD_DESC *w;
926 int i;
927
928 ret = (WORD_LIST *)NULL;
929 w = make_word (cmd);
930 ret = make_word_list (w, (WORD_LIST *)NULL);
931
932 w = (lwords && lwords->word) ? copy_word (lwords->word) : make_word ("");
933 cl = ret->next = make_word_list (w, (WORD_LIST *)NULL);
934
935 w = make_word (text);
936 cl->next = make_word_list (w, (WORD_LIST *)NULL);
937 cl = cl->next;
938
939 /* Search lwords for current word */
940 for (l = lwords, i = 1; l && i < ind-1; l = l->next, i++)
941 ;
942 w = (l && l->word) ? copy_word (l->word) : make_word ("");
943 cl->next = make_word_list (w, (WORD_LIST *)NULL);
944
945 return ret;
946}
947
948/* Build a command string with
949 $0 == cs->funcname (function to execute for completion list)
950 $1 == command name (command being completed)
951 $2 = word to be completed (possibly null)
952 $3 = previous word
953 and run in the current shell. The function should put its completion
954 list into the array variable COMPREPLY. We build a STRINGLIST
955 from the results and return it.
956
957 Since the shell function should return its list of matches in an array
958 variable, this does nothing if arrays are not compiled into the shell. */
959
960static STRINGLIST *
961gen_shell_function_matches (cs, text, line, ind, lwords, nw, cw)
962 COMPSPEC *cs;
Jari Aaltof73dda02001-11-13 17:56:06 +0000963 const char *text;
964 char *line;
Jari Aaltobb706242000-03-17 21:46:59 +0000965 int ind;
966 WORD_LIST *lwords;
967 int nw, cw;
968{
969 char *funcname;
970 STRINGLIST *sl;
971 SHELL_VAR *f, *v;
972 WORD_LIST *cmdlist;
973 int fval;
974#if defined (ARRAY_VARS)
975 ARRAY *a;
976#endif
977
978 funcname = cs->funcname;
979 f = find_function (funcname);
980 if (f == 0)
981 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000982 internal_error ("completion: function `%s' not found", funcname);
983 rl_ding ();
Jari Aaltobb706242000-03-17 21:46:59 +0000984 rl_on_new_line ();
985 return ((STRINGLIST *)NULL);
986 }
987
988#if !defined (ARRAY_VARS)
989 return ((STRINGLIST *)NULL);
990#else
991
992 /* We pass cw - 1 because command_line_to_word_list returns indices that are
993 1-based, while bash arrays are 0-based. */
994 bind_compfunc_variables (line, ind, lwords, cw - 1, 0);
995
996 cmdlist = build_arg_list (funcname, text, lwords, cw);
997
998 fval = execute_shell_function (f, cmdlist);
999
1000 /* Now clean up and destroy everything. */
1001 dispose_words (cmdlist);
1002 unbind_compfunc_variables (0);
1003
1004 /* The list of completions is returned in the array variable COMPREPLY. */
1005 v = find_variable ("COMPREPLY");
1006 if (v == 0)
1007 return ((STRINGLIST *)NULL);
1008 if (array_p (v) == 0)
1009 v = convert_var_to_array (v);
1010
1011 a = array_cell (v);
1012 if (a == 0 || array_empty (a))
1013 sl = (STRINGLIST *)NULL;
1014 else
1015 {
1016 /* XXX - should we filter the list of completions so only those matching
1017 TEXT are returned? Right now, we do not. */
1018 sl = alloc_stringlist (0);
1019 sl->list = array_to_argv (a);
1020 sl->list_len = sl->list_size = array_num_elements (a);
1021 }
1022
1023 /* XXX - should we unbind COMPREPLY here? */
1024 makunbound ("COMPREPLY", shell_variables);
1025
1026 return (sl);
1027#endif
1028}
1029
1030/* Build a command string with
1031 $0 == cs->command (command to execute for completion list)
1032 $1 == command name (command being completed)
1033 $2 = word to be completed (possibly null)
1034 $3 = previous word
1035 and run in with command substitution. Parse the results, one word
1036 per line, with backslashes allowed to escape newlines. Build a
1037 STRINGLIST from the results and return it. */
1038
1039static STRINGLIST *
1040gen_command_matches (cs, text, line, ind, lwords, nw, cw)
1041 COMPSPEC *cs;
Jari Aaltof73dda02001-11-13 17:56:06 +00001042 const char *text;
1043 char *line;
Jari Aaltobb706242000-03-17 21:46:59 +00001044 int ind;
1045 WORD_LIST *lwords;
1046 int nw, cw;
1047{
1048 char *csbuf, *cscmd, *t;
1049 int cmdlen, cmdsize, n, ws, we;
1050 WORD_LIST *cmdlist, *cl;
1051 STRINGLIST *sl;
1052
1053 bind_compfunc_variables (line, ind, lwords, cw, 1);
1054 cmdlist = build_arg_list (cs->command, text, lwords, cw);
1055
1056 /* Estimate the size needed for the buffer. */
1057 n = strlen (cs->command);
1058 cmdsize = n + 1;
1059 for (cl = cmdlist->next; cl; cl = cl->next)
1060 cmdsize += STRLEN (cl->word->word) + 3;
1061 cmdsize += 2;
1062
1063 /* allocate the string for the command and fill it in. */
Jari Aaltof73dda02001-11-13 17:56:06 +00001064 cscmd = (char *)xmalloc (cmdsize + 1);
Jari Aaltobb706242000-03-17 21:46:59 +00001065
1066 strcpy (cscmd, cs->command); /* $0 */
1067 cmdlen = n;
1068 cscmd[cmdlen++] = ' ';
1069 for (cl = cmdlist->next; cl; cl = cl->next) /* $1, $2, $3, ... */
1070 {
Jari Aalto28ef6c32001-04-06 19:14:31 +00001071 t = sh_single_quote (cl->word->word ? cl->word->word : "");
Jari Aaltobb706242000-03-17 21:46:59 +00001072 n = strlen (t);
1073 RESIZE_MALLOCED_BUFFER (cscmd, cmdlen, n + 2, cmdsize, 64);
1074 strcpy (cscmd + cmdlen, t);
1075 cmdlen += n;
1076 if (cl->next)
1077 cscmd[cmdlen++] = ' ';
1078 free (t);
1079 }
1080 cscmd[cmdlen] = '\0';
1081
1082 csbuf = command_substitute (cscmd, 0);
1083
1084 /* Now clean up and destroy everything. */
1085 dispose_words (cmdlist);
1086 free (cscmd);
1087 unbind_compfunc_variables (1);
1088
1089 if (csbuf == 0 || *csbuf == '\0')
1090 {
1091 FREE (csbuf);
1092 return ((STRINGLIST *)NULL);
1093 }
1094
1095 /* Now break CSBUF up at newlines, with backslash allowed to escape a
1096 newline, and put the individual words into a STRINGLIST. */
1097 sl = alloc_stringlist (16);
1098 for (ws = 0; csbuf[ws]; )
1099 {
1100 we = ws;
1101 while (csbuf[we] && csbuf[we] != '\n')
1102 {
1103 if (csbuf[we] == '\\' && csbuf[we+1] == '\n')
1104 we++;
1105 we++;
1106 }
1107 t = substring (csbuf, ws, we);
1108 if (sl->list_len >= sl->list_size - 1)
1109 realloc_stringlist (sl, sl->list_size + 16);
1110 sl->list[sl->list_len++] = t;
1111 while (csbuf[we] == '\n') we++;
1112 ws = we;
1113 }
1114 sl->list[sl->list_len] = (char *)NULL;
1115
1116 free (csbuf);
1117 return (sl);
1118}
1119
1120static WORD_LIST *
1121command_line_to_word_list (line, llen, sentinel, nwp, cwp)
1122 char *line;
1123 int llen, sentinel, *nwp, *cwp;
1124{
1125 WORD_LIST *ret;
1126 char *delims;
1127
1128 delims = "()<>;&| \t\n"; /* shell metacharacters break words */
1129 ret = split_at_delims (line, llen, delims, sentinel, nwp, cwp);
1130 return (ret);
1131}
1132
1133/* Evaluate COMPSPEC *cs and return all matches for WORD. */
1134
1135STRINGLIST *
1136gen_compspec_completions (cs, cmd, word, start, end)
1137 COMPSPEC *cs;
Jari Aalto28ef6c32001-04-06 19:14:31 +00001138 const char *cmd;
1139 const char *word;
Jari Aaltobb706242000-03-17 21:46:59 +00001140 int start, end;
1141{
1142 STRINGLIST *ret, *tmatches;
Jari Aaltof73dda02001-11-13 17:56:06 +00001143 char *line;
Jari Aaltobb706242000-03-17 21:46:59 +00001144 int llen, nw, cw;
1145 WORD_LIST *lwords;
1146
1147 debug_printf ("programmable_completions (%s, %s, %d, %d)", cmd, word, start, end);
Jari Aaltof73dda02001-11-13 17:56:06 +00001148 debug_printf ("programmable_completions: %s -> %p", cmd, cs);
Jari Aaltobb706242000-03-17 21:46:59 +00001149 ret = gen_action_completions (cs, word);
1150 if (ret && progcomp_debug)
1151 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001152 debug_printf ("gen_action_completions (%p, %s) -->", cs, word);
Jari Aaltobb706242000-03-17 21:46:59 +00001153 print_stringlist (ret, "\t");
1154 rl_on_new_line ();
1155 }
1156
1157 /* Now we start generating completions based on the other members of CS. */
1158 if (cs->globpat)
1159 {
1160 tmatches = gen_globpat_matches (cs, word);
1161 if (tmatches)
1162 {
1163 if (progcomp_debug)
1164 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001165 debug_printf ("gen_globpat_matches (%p, %s) -->", cs, word);
Jari Aaltobb706242000-03-17 21:46:59 +00001166 print_stringlist (tmatches, "\t");
1167 rl_on_new_line ();
1168 }
1169 ret = append_stringlist (ret, tmatches);
1170 free_stringlist (tmatches);
1171 rl_filename_completion_desired = 1;
1172 }
1173 }
1174
1175 if (cs->words)
1176 {
1177 tmatches = gen_wordlist_matches (cs, word);
1178 if (tmatches)
1179 {
1180 if (progcomp_debug)
1181 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001182 debug_printf ("gen_wordlist_matches (%p, %s) -->", cs, word);
Jari Aaltobb706242000-03-17 21:46:59 +00001183 print_stringlist (tmatches, "\t");
1184 rl_on_new_line ();
1185 }
1186 ret = append_stringlist (ret, tmatches);
1187 free_stringlist (tmatches);
1188 }
1189 }
1190
1191 lwords = (WORD_LIST *)NULL;
1192 line = (char *)NULL;
1193 if (cs->command || cs->funcname)
1194 {
1195 /* If we have a command or function to execute, we need to first break
1196 the command line into individual words, find the number of words,
1197 and find the word in the list containing the word to be completed. */
1198 line = substring (rl_line_buffer, start, end);
1199 llen = end - start;
1200
Jari Aaltof73dda02001-11-13 17:56:06 +00001201 debug_printf ("command_line_to_word_list (%s, %d, %d, %p, %p)",
Jari Aaltobb706242000-03-17 21:46:59 +00001202 line, llen, rl_point - start, &nw, &cw);
1203 lwords = command_line_to_word_list (line, llen, rl_point - start, &nw, &cw);
1204 if (lwords == 0 && llen > 0)
1205 debug_printf ("ERROR: command_line_to_word_list returns NULL");
1206 else if (progcomp_debug)
1207 {
1208 debug_printf ("command_line_to_word_list -->");
1209 printf ("\t");
1210 print_word_list (lwords, "!");
1211 printf ("\n");
1212 fflush(stdout);
1213 rl_on_new_line ();
1214 }
1215 }
1216
1217 if (cs->funcname)
1218 {
1219 tmatches = gen_shell_function_matches (cs, word, line, rl_point - start, lwords, nw, cw);
1220 if (tmatches)
1221 {
1222 if (progcomp_debug)
1223 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001224 debug_printf ("gen_shell_function_matches (%p, %s, %p, %d, %d) -->", cs, word, lwords, nw, cw);
Jari Aaltobb706242000-03-17 21:46:59 +00001225 print_stringlist (tmatches, "\t");
1226 rl_on_new_line ();
1227 }
1228 ret = append_stringlist (ret, tmatches);
1229 free_stringlist (tmatches);
1230 }
1231 }
1232
1233 if (cs->command)
1234 {
1235 tmatches = gen_command_matches (cs, word, line, rl_point - start, lwords, nw, cw);
1236 if (tmatches)
1237 {
1238 if (progcomp_debug)
1239 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001240 debug_printf ("gen_command_matches (%p, %s, %p, %d, %d) -->", cs, word, lwords, nw, cw);
Jari Aaltobb706242000-03-17 21:46:59 +00001241 print_stringlist (tmatches, "\t");
1242 rl_on_new_line ();
1243 }
1244 ret = append_stringlist (ret, tmatches);
1245 free_stringlist (tmatches);
1246 }
1247 }
1248
1249 if (cs->command || cs->funcname)
1250 {
1251 if (lwords)
1252 dispose_words (lwords);
1253 FREE (line);
1254 }
1255
1256 if (cs->filterpat)
1257 {
1258 tmatches = filter_stringlist (ret, cs->filterpat, word);
1259 if (progcomp_debug)
1260 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001261 debug_printf ("filter_stringlist (%p, %s, %s) -->", ret, cs->filterpat, word);
Jari Aaltobb706242000-03-17 21:46:59 +00001262 print_stringlist (tmatches, "\t");
1263 rl_on_new_line ();
1264 }
1265 if (ret && ret != tmatches)
1266 {
1267 FREE (ret->list);
1268 free (ret);
1269 }
1270 ret = tmatches;
1271 }
1272
1273 if (cs->prefix || cs->suffix)
1274 ret = prefix_suffix_stringlist (ret, cs->prefix, cs->suffix);
1275
Jari Aalto28ef6c32001-04-06 19:14:31 +00001276 /* If no matches have been generated and the user has specified that
1277 directory completion should be done as a default, call
1278 gen_action_completions again to generate a list of matching directory
1279 names. */
1280 if ((ret == 0 || ret->list_len == 0) && (cs->options & COPT_DIRNAMES))
1281 {
1282 COMPSPEC *dummy;
1283
1284 dummy = alloc_compspec ();
1285 dummy->actions = CA_DIRECTORY;
1286 ret = gen_action_completions (dummy, word);
1287 free_compspec (dummy);
1288 }
1289
Jari Aaltobb706242000-03-17 21:46:59 +00001290 return (ret);
1291}
1292
1293/* The driver function for the programmable completion code. Returns a list
1294 of matches for WORD, which is an argument to command CMD. START and END
1295 bound the command currently being completed in rl_line_buffer. */
1296char **
1297programmable_completions (cmd, word, start, end, foundp)
Jari Aalto28ef6c32001-04-06 19:14:31 +00001298 const char *cmd;
1299 const char *word;
Jari Aaltobb706242000-03-17 21:46:59 +00001300 int start, end, *foundp;
1301{
1302 COMPSPEC *cs;
1303 STRINGLIST *ret;
1304 char **rmatches, *t;
1305
1306 /* We look at the basename of CMD if the full command does not have
1307 an associated COMPSPEC. */
1308 cs = find_compspec (cmd);
1309 if (cs == 0)
1310 {
1311 t = strrchr (cmd, '/');
1312 if (t)
1313 cs = find_compspec (++t);
1314 }
1315 if (cs == 0)
1316 {
1317 if (foundp)
1318 *foundp = 0;
1319 return ((char **)NULL);
1320 }
1321
Jari Aalto28ef6c32001-04-06 19:14:31 +00001322 /* Signal the caller that we found a COMPSPEC for this command, and pass
1323 back any meta-options associated with the compspec. */
Jari Aaltobb706242000-03-17 21:46:59 +00001324 if (foundp)
Jari Aalto28ef6c32001-04-06 19:14:31 +00001325 *foundp = 1|cs->options;
Jari Aaltobb706242000-03-17 21:46:59 +00001326
1327 ret = gen_compspec_completions (cs, cmd, word, start, end);
1328
1329 if (ret)
1330 {
1331 rmatches = ret->list;
1332 free (ret);
1333 }
1334 else
1335 rmatches = (char **)NULL;
1336
1337 return (rmatches);
1338}
1339
1340#endif /* PROGRAMMABLE_COMPLETION */