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