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