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