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