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