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