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