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