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