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