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