1 /* pcomplete.c - functions to generate lists of matches for programmable completion. */
3 /* Copyright (C) 1999-2020 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne Again SHell.
7 Bush 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.
12 Bush 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.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
23 #if defined (PROGRAMMABLE_COMPLETION)
25 #include "bushtypes.h"
26 #include "posixstat.h"
28 #if defined (HAVE_UNISTD_H)
34 #if defined (PREFER_STDARG)
40 #include "posixtime.h"
47 #include "pcomplete.h"
48 #include "impl/alias.h"
49 #include "input/bushline.h"
50 #include "runner/execute_cmd.h"
51 #include "impl/pathexp.h"
53 #if defined (JOB_CONTROL)
64 #include "builtins/common.h"
65 #include "builtins/builtext.h"
67 #include <glob/glob.h>
68 #include <glob/strmatch.h>
70 #include <readline/rlconf.h>
71 #include <readline/readline.h>
72 #include <readline/history.h>
77 #define STRDUP(x) ((x) ? savestring (x) : (char *)NULL)
79 typedef SHELL_VAR
**SVFUNC ();
82 extern char *strpbrk
PARAMS((char *, char *));
85 extern STRING_INT_ALIST word_token_alist
[];
86 extern char *signal_names
[];
89 #if defined (PREFER_STDARG)
90 static void debug_printf (const char *, ...) __attribute__((__format__ (printf
, 1, 2)));
94 static int it_init_joblist
PARAMS((ITEMLIST
*, int));
96 static int it_init_aliases
PARAMS((ITEMLIST
*));
97 static int it_init_arrayvars
PARAMS((ITEMLIST
*));
98 static int it_init_bindings
PARAMS((ITEMLIST
*));
99 static int it_init_builtins
PARAMS((ITEMLIST
*));
100 static int it_init_disabled
PARAMS((ITEMLIST
*));
101 static int it_init_enabled
PARAMS((ITEMLIST
*));
102 static int it_init_exported
PARAMS((ITEMLIST
*));
103 static int it_init_functions
PARAMS((ITEMLIST
*));
104 static int it_init_helptopics
PARAMS((ITEMLIST
*));
105 static int it_init_hostnames
PARAMS((ITEMLIST
*));
106 static int it_init_jobs
PARAMS((ITEMLIST
*));
107 static int it_init_running
PARAMS((ITEMLIST
*));
108 static int it_init_stopped
PARAMS((ITEMLIST
*));
109 static int it_init_keywords
PARAMS((ITEMLIST
*));
110 static int it_init_signals
PARAMS((ITEMLIST
*));
111 static int it_init_variables
PARAMS((ITEMLIST
*));
112 static int it_init_setopts
PARAMS((ITEMLIST
*));
113 static int it_init_shopts
PARAMS((ITEMLIST
*));
115 static int shouldexp_filterpat
PARAMS((char *));
116 static char *preproc_filterpat
PARAMS((char *, const char *));
118 static void init_itemlist_from_varlist
PARAMS((ITEMLIST
*, SVFUNC
*));
120 static STRINGLIST
*gen_matches_from_itemlist
PARAMS((ITEMLIST
*, const char *));
121 static STRINGLIST
*gen_action_completions
PARAMS((COMPSPEC
*, const char *));
122 static STRINGLIST
*gen_globpat_matches
PARAMS((COMPSPEC
*, const char *));
123 static STRINGLIST
*gen_wordlist_matches
PARAMS((COMPSPEC
*, const char *));
124 static STRINGLIST
*gen_shell_function_matches
PARAMS((COMPSPEC
*, const char *,
126 char *, int, WORD_LIST
*,
128 static STRINGLIST
*gen_command_matches
PARAMS((COMPSPEC
*, const char *,
130 char *, int, WORD_LIST
*,
133 static STRINGLIST
*gen_progcomp_completions
PARAMS((const char *, const char *,
135 int, int, int *, int *,
138 static char *pcomp_filename_completion_function
PARAMS((const char *, int));
140 #if defined (ARRAY_VARS)
141 static SHELL_VAR
*bind_comp_words
PARAMS((WORD_LIST
*));
143 static void bind_compfunc_variables
PARAMS((char *, int, WORD_LIST
*, int, int));
144 static void unbind_compfunc_variables
PARAMS((int));
145 static WORD_LIST
*build_arg_list
PARAMS((char *, const char *, const char *, WORD_LIST
*, int));
146 static WORD_LIST
*command_line_to_word_list
PARAMS((char *, int, int, int *, int *));
149 static int progcomp_debug
= 0;
152 int prog_completion_enabled
= 1;
155 int progcomp_alias
= 0; /* unavailable to user code for now */
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 };
184 COMPSPEC
*pcomp_curcs
;
185 const char *pcomp_curcmd
;
186 const char *pcomp_curtxt
;
194 #if defined (PREFER_STDARG)
195 debug_printf (const char *format
, ...)
197 debug_printf (format
, va_alist
)
204 if (progcomp_debug
== 0)
207 SH_VA_START (args
, format
);
209 fprintf (stdout
, "DEBUG: ");
210 vfprintf (stdout
, format
, args
);
211 fprintf (stdout
, "\n");
219 /* Functions to manage the item lists */
222 set_itemlist_dirty (it
)
225 it
->flags
|= LIST_DIRTY
;
229 initialize_itemlist (itp
)
232 (*itp
->list_getter
) (itp
);
233 itp
->flags
|= LIST_INITIALIZED
;
234 itp
->flags
&= ~LIST_DIRTY
;
246 if ((itp
->flags
& (LIST_DONTFREEMEMBERS
|LIST_DONTFREE
)) == 0)
247 strvec_flush (sl
->list
);
248 if ((itp
->flags
& LIST_DONTFREE
) == 0)
252 itp
->slist
= (STRINGLIST
*)NULL
;
253 itp
->flags
&= ~(LIST_DONTFREE
|LIST_DONTFREEMEMBERS
|LIST_INITIALIZED
|LIST_DIRTY
);
258 shouldexp_filterpat (s
)
263 for (p
= s
; p
&& *p
; p
++)
273 /* Replace any instance of `&' in PAT with TEXT. Backslash may be used to
274 quote a `&' and inhibit substitution. Returns a new string. This just
275 calls stringlib.c:strcreplace(). */
277 preproc_filterpat (pat
, text
)
283 ret
= strcreplace (pat
, '&', text
, 1);
287 /* Remove any match of FILTERPAT from SL. A `&' in FILTERPAT is replaced by
288 TEXT. A leading `!' in FILTERPAT negates the pattern; in this case
289 any member of SL->list that does *not* match will be removed. This returns
290 a new STRINGLIST with the matching members of SL *copied*. Any
291 non-matching members of SL->list are *freed*. */
293 filter_stringlist (sl
, filterpat
, text
)
302 if (sl
== 0 || sl
->list
== 0 || sl
->list_len
== 0)
305 npat
= shouldexp_filterpat (filterpat
) ? preproc_filterpat (filterpat
, text
) : filterpat
;
307 #if defined (EXTENDED_GLOB)
308 not = (npat
[0] == '!' && (extended_glob
== 0 || npat
[1] != '(')); /*)*/
310 not = (npat
[0] == '!');
312 t
= not ? npat
+ 1 : npat
;
314 ret
= strlist_create (sl
->list_size
);
315 for (i
= 0; i
< sl
->list_len
; i
++)
317 m
= strmatch (t
, sl
->list
[i
], FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
);
318 if ((not && m
== FNM_NOMATCH
) || (not == 0 && m
!= FNM_NOMATCH
))
321 ret
->list
[ret
->list_len
++] = sl
->list
[i
];
324 ret
->list
[ret
->list_len
] = (char *)NULL
;
325 if (npat
!= filterpat
)
331 /* Turn an array of strings returned by rl_completion_matches into a STRINGLIST.
332 This understands how rl_completion_matches sets matches[0] (the lcd of the
333 strings in the list, unless it's the only match). */
335 completions_to_stringlist (matches
)
341 mlen
= (matches
== 0) ? 0 : strvec_len (matches
);
342 sl
= strlist_create (mlen
+ 1);
344 if (matches
== 0 || matches
[0] == 0)
349 sl
->list
[0] = STRDUP (matches
[0]);
350 sl
->list
[sl
->list_len
= 1] = (char *)NULL
;
354 for (i
= 1, n
= 0; i
< mlen
; i
++, n
++)
355 sl
->list
[n
] = STRDUP (matches
[i
]);
357 sl
->list
[n
] = (char *)NULL
;
362 /* Functions to manage the various ITEMLISTs that we populate internally.
363 The caller is responsible for setting ITP->flags correctly. */
366 it_init_aliases (itp
)
370 alias_t
**alias_list
;
374 alias_list
= all_aliases ();
377 itp
->slist
= (STRINGLIST
*)NULL
;
380 for (n
= 0; alias_list
[n
]; n
++)
382 sl
= strlist_create (n
+1);
383 for (i
= 0; i
< n
; i
++)
384 sl
->list
[i
] = STRDUP (alias_list
[i
]->name
);
385 sl
->list
[n
] = (char *)NULL
;
386 sl
->list_size
= sl
->list_len
= n
;
389 itp
->slist
= (STRINGLIST
*)NULL
;
396 init_itemlist_from_varlist (itp
, svfunc
)
404 vlist
= (*svfunc
) ();
407 itp
->slist
= (STRINGLIST
*)NULL
;
410 for (n
= 0; vlist
[n
]; n
++)
412 sl
= strlist_create (n
+1);
413 for (i
= 0; i
< n
; i
++)
414 sl
->list
[i
] = savestring (vlist
[i
]->name
);
415 sl
->list
[sl
->list_len
= n
] = (char *)NULL
;
420 it_init_arrayvars (itp
)
423 #if defined (ARRAY_VARS)
424 init_itemlist_from_varlist (itp
, all_array_variables
);
432 it_init_bindings (itp
)
438 /* rl_funmap_names allocates blist, but not its members */
439 blist
= (char **)rl_funmap_names (); /* XXX fix const later */
440 sl
= strlist_create (0);
443 sl
->list_len
= strvec_len (sl
->list
);
444 itp
->flags
|= LIST_DONTFREEMEMBERS
;
451 it_init_builtins (itp
)
457 sl
= strlist_create (num_shell_builtins
);
458 for (i
= n
= 0; i
< num_shell_builtins
; i
++)
459 if (shell_builtins
[i
].function
)
460 sl
->list
[n
++] = shell_builtins
[i
].name
;
461 sl
->list
[sl
->list_len
= n
] = (char *)NULL
;
462 itp
->flags
|= LIST_DONTFREEMEMBERS
;
468 it_init_enabled (itp
)
474 sl
= strlist_create (num_shell_builtins
);
475 for (i
= n
= 0; i
< num_shell_builtins
; i
++)
477 if (shell_builtins
[i
].function
&& (shell_builtins
[i
].flags
& BUILTIN_ENABLED
))
478 sl
->list
[n
++] = shell_builtins
[i
].name
;
480 sl
->list
[sl
->list_len
= n
] = (char *)NULL
;
481 itp
->flags
|= LIST_DONTFREEMEMBERS
;
487 it_init_disabled (itp
)
493 sl
= strlist_create (num_shell_builtins
);
494 for (i
= n
= 0; i
< num_shell_builtins
; i
++)
496 if (shell_builtins
[i
].function
&& ((shell_builtins
[i
].flags
& BUILTIN_ENABLED
) == 0))
497 sl
->list
[n
++] = shell_builtins
[i
].name
;
499 sl
->list
[sl
->list_len
= n
] = (char *)NULL
;
500 itp
->flags
|= LIST_DONTFREEMEMBERS
;
506 it_init_exported (itp
)
509 init_itemlist_from_varlist (itp
, all_exported_variables
);
514 it_init_functions (itp
)
517 init_itemlist_from_varlist (itp
, all_visible_functions
);
521 /* Like it_init_builtins, but includes everything the help builtin looks at,
522 not just builtins with an active implementing function. */
524 it_init_helptopics (itp
)
530 sl
= strlist_create (num_shell_builtins
);
531 for (i
= n
= 0; i
< num_shell_builtins
; i
++)
532 sl
->list
[n
++] = shell_builtins
[i
].name
;
533 sl
->list
[sl
->list_len
= n
] = (char *)NULL
;
534 itp
->flags
|= LIST_DONTFREEMEMBERS
;
540 it_init_hostnames (itp
)
545 sl
= strlist_create (0);
546 sl
->list
= get_hostname_list ();
547 sl
->list_len
= sl
->list
? strvec_len (sl
->list
) : 0;
548 sl
->list_size
= sl
->list_len
;
550 itp
->flags
|= LIST_DONTFREEMEMBERS
|LIST_DONTFREE
;
555 it_init_joblist (itp
, jstate
)
559 #if defined (JOB_CONTROL)
565 JOB_STATE ws
; /* wanted state */
570 else if (jstate
== 1)
573 sl
= strlist_create (js
.j_jobslots
);
574 for (i
= js
.j_jobslots
- 1; i
>= 0; i
--)
576 j
= get_job_by_jid (i
);
580 if (jstate
== -1 || JOBSTATE(i
) == ws
)
582 s
= savestring (p
->command
);
583 t
= strpbrk (s
, " \t\n");
586 sl
->list
[sl
->list_len
++] = s
;
591 itp
->slist
= (STRINGLIST
*)NULL
;
600 return (it_init_joblist (itp
, -1));
604 it_init_running (itp
)
607 return (it_init_joblist (itp
, 0));
611 it_init_stopped (itp
)
614 return (it_init_joblist (itp
, 1));
618 it_init_keywords (itp
)
624 for (n
= 0; word_token_alist
[n
].word
; n
++)
626 sl
= strlist_create (n
);
627 for (i
= 0; i
< n
; i
++)
628 sl
->list
[i
] = word_token_alist
[i
].word
;
629 sl
->list
[sl
->list_len
= i
] = (char *)NULL
;
630 itp
->flags
|= LIST_DONTFREEMEMBERS
;
636 it_init_signals (itp
)
641 sl
= strlist_create (0);
642 sl
->list
= signal_names
;
643 sl
->list_len
= strvec_len (sl
->list
);
644 itp
->flags
|= LIST_DONTFREE
;
650 it_init_variables (itp
)
653 init_itemlist_from_varlist (itp
, all_visible_variables
);
658 it_init_setopts (itp
)
663 sl
= strlist_create (0);
664 sl
->list
= get_minus_o_opts ();
665 sl
->list_len
= strvec_len (sl
->list
);
667 itp
->flags
|= LIST_DONTFREEMEMBERS
;
677 sl
= strlist_create (0);
678 sl
->list
= get_shopt_options ();
679 sl
->list_len
= strvec_len (sl
->list
);
681 itp
->flags
|= LIST_DONTFREEMEMBERS
;
685 /* Generate a list of all matches for TEXT using the STRINGLIST in itp->slist
686 as the list of possibilities. If the itemlist has been marked dirty or
687 it should be regenerated every time, destroy the old STRINGLIST and make a
688 new one before trying the match. TEXT is dequoted before attempting a
691 gen_matches_from_itemlist (itp
, text
)
695 STRINGLIST
*ret
, *sl
;
699 if ((itp
->flags
& (LIST_DIRTY
|LIST_DYNAMIC
)) ||
700 (itp
->flags
& LIST_INITIALIZED
) == 0)
702 if (itp
->flags
& (LIST_DIRTY
|LIST_DYNAMIC
))
703 clean_itemlist (itp
);
704 if ((itp
->flags
& LIST_INITIALIZED
) == 0)
705 initialize_itemlist (itp
);
708 return ((STRINGLIST
*)NULL
);
709 ret
= strlist_create (itp
->slist
->list_len
+1);
712 ntxt
= bush_dequote_text (text
);
713 tlen
= STRLEN (ntxt
);
715 for (i
= n
= 0; i
< sl
->list_len
; i
++)
717 if (tlen
== 0 || STREQN (sl
->list
[i
], ntxt
, tlen
))
718 ret
->list
[n
++] = STRDUP (sl
->list
[i
]);
720 ret
->list
[ret
->list_len
= n
] = (char *)NULL
;
726 /* A wrapper for rl_filename_completion_function that dequotes the filename
727 before attempting completions. */
729 pcomp_filename_completion_function (text
, state
)
733 static char *dfn
; /* dequoted filename */
734 int iscompgen
, iscompleting
;
739 /* remove backslashes quoting special characters in filenames. */
740 /* There are roughly three paths we can follow to get here:
742 2. compgen -f "$word" from a completion function
743 3. compgen -f "$word" from the command line
744 They all need to be handled.
746 In the first two cases, readline will run the filename dequoting
747 function in rl_filename_completion_function if it found a filename
748 quoting character in the word to be completed
749 (rl_completion_found_quote). We run the dequoting function here
750 if we're running compgen, we're not completing, and the
751 rl_filename_completion_function won't dequote the filename
752 (rl_completion_found_quote == 0). */
753 iscompgen
= this_shell_builtin
== compgen_builtin
;
754 iscompleting
= RL_ISSTATE (RL_STATE_COMPLETING
);
755 if (iscompgen
&& iscompleting
== 0 && rl_completion_found_quote
== 0
756 && rl_filename_dequoting_function
)
758 /* Use rl_completion_quote_character because any single or
759 double quotes have been removed by the time TEXT makes it
760 here, and we don't want to remove backslashes inside
762 dfn
= (*rl_filename_dequoting_function
) ((char *)text
, rl_completion_quote_character
);
764 /* Intended to solve a mismatched assumption by bush-completion. If
765 the text to be completed is empty, but bush-completion turns it into
766 a quoted string ('') assuming that this code will dequote it before
767 calling readline, do the dequoting. */
768 else if (iscompgen
&& iscompleting
&&
769 pcomp_curtxt
&& *pcomp_curtxt
== 0 &&
770 text
&& (*text
== '\'' || *text
== '"') && text
[1] == text
[0] && text
[2] == 0 &&
771 rl_filename_dequoting_function
)
772 dfn
= (*rl_filename_dequoting_function
) ((char *)text
, rl_completion_quote_character
);
773 /* Another mismatched assumption by bush-completion. If compgen is being
774 run as part of bush-completion, and the argument to compgen is not
775 the same as the word originally passed to the programmable completion
776 code, dequote the argument if it has quote characters. It's an
777 attempt to detect when bush-completion is quoting its filename
778 argument before calling compgen. */
779 /* We could check whether gen_shell_function_matches is in the call
780 stack by checking whether the gen-shell-function-matches tag is in
781 the unwind-protect stack, but there's no function to do that yet.
782 We could simply check whether we're executing in a function by
783 checking variable_context, and may end up doing that. */
784 else if (iscompgen
&& iscompleting
&& rl_filename_dequoting_function
&&
785 pcomp_curtxt
&& text
&&
786 STREQ (pcomp_curtxt
, text
) == 0 &&
788 sh_contains_quotes (text
)) /* guess */
789 dfn
= (*rl_filename_dequoting_function
) ((char *)text
, rl_completion_quote_character
);
791 dfn
= savestring (text
);
794 return (rl_filename_completion_function (dfn
, state
));
797 #define GEN_COMPS(bmap, flag, it, text, glist, tlist) \
801 tlist = gen_matches_from_itemlist (it, text); \
804 glist = strlist_append (glist, tlist); \
805 strlist_dispose (tlist); \
810 #define GEN_XCOMPS(bmap, flag, text, func, cmatches, glist, tlist) \
814 cmatches = rl_completion_matches (text, func); \
815 tlist = completions_to_stringlist (cmatches); \
816 glist = strlist_append (glist, tlist); \
817 strvec_dispose (cmatches); \
818 strlist_dispose (tlist); \
822 /* Functions to generate lists of matches from the actions member of CS. */
825 gen_action_completions (cs
, text
)
829 STRINGLIST
*ret
, *tmatches
;
830 char **cmatches
; /* from rl_completion_matches ... */
834 ret
= tmatches
= (STRINGLIST
*)NULL
;
837 GEN_COMPS (flags
, CA_ALIAS
, &it_aliases
, text
, ret
, tmatches
);
838 GEN_COMPS (flags
, CA_ARRAYVAR
, &it_arrayvars
, text
, ret
, tmatches
);
839 GEN_COMPS (flags
, CA_BINDING
, &it_bindings
, text
, ret
, tmatches
);
840 GEN_COMPS (flags
, CA_BUILTIN
, &it_builtins
, text
, ret
, tmatches
);
841 GEN_COMPS (flags
, CA_DISABLED
, &it_disabled
, text
, ret
, tmatches
);
842 GEN_COMPS (flags
, CA_ENABLED
, &it_enabled
, text
, ret
, tmatches
);
843 GEN_COMPS (flags
, CA_EXPORT
, &it_exports
, text
, ret
, tmatches
);
844 GEN_COMPS (flags
, CA_FUNCTION
, &it_functions
, text
, ret
, tmatches
);
845 GEN_COMPS (flags
, CA_HELPTOPIC
, &it_helptopics
, text
, ret
, tmatches
);
846 GEN_COMPS (flags
, CA_HOSTNAME
, &it_hostnames
, text
, ret
, tmatches
);
847 GEN_COMPS (flags
, CA_JOB
, &it_jobs
, text
, ret
, tmatches
);
848 GEN_COMPS (flags
, CA_KEYWORD
, &it_keywords
, text
, ret
, tmatches
);
849 GEN_COMPS (flags
, CA_RUNNING
, &it_running
, text
, ret
, tmatches
);
850 GEN_COMPS (flags
, CA_SETOPT
, &it_setopts
, text
, ret
, tmatches
);
851 GEN_COMPS (flags
, CA_SHOPT
, &it_shopts
, text
, ret
, tmatches
);
852 GEN_COMPS (flags
, CA_SIGNAL
, &it_signals
, text
, ret
, tmatches
);
853 GEN_COMPS (flags
, CA_STOPPED
, &it_stopped
, text
, ret
, tmatches
);
854 GEN_COMPS (flags
, CA_VARIABLE
, &it_variables
, text
, ret
, tmatches
);
856 GEN_XCOMPS(flags
, CA_COMMAND
, text
, command_word_completion_function
, cmatches
, ret
, tmatches
);
857 GEN_XCOMPS(flags
, CA_FILE
, text
, pcomp_filename_completion_function
, cmatches
, ret
, tmatches
);
858 GEN_XCOMPS(flags
, CA_USER
, text
, rl_username_completion_function
, cmatches
, ret
, tmatches
);
859 GEN_XCOMPS(flags
, CA_GROUP
, text
, bush_groupname_completion_function
, cmatches
, ret
, tmatches
);
860 GEN_XCOMPS(flags
, CA_SERVICE
, text
, bush_servicename_completion_function
, cmatches
, ret
, tmatches
);
862 /* And lastly, the special case for directories */
863 if (flags
& CA_DIRECTORY
)
865 t
= rl_filename_completion_desired
;
866 rl_completion_mark_symlink_dirs
= 1; /* override user preference */
867 cmatches
= bush_directory_completion_matches (text
);
868 /* If we did not want filename completion before this, and there are
869 no matches, turn off rl_filename_completion_desired so whatever
870 matches we get are not treated as filenames (it gets turned on by
871 rl_filename_completion_function unconditionally). */
872 if (t
== 0 && cmatches
== 0 && rl_filename_completion_desired
== 1)
873 rl_filename_completion_desired
= 0;
874 tmatches
= completions_to_stringlist (cmatches
);
875 ret
= strlist_append (ret
, tmatches
);
876 strvec_dispose (cmatches
);
877 strlist_dispose (tmatches
);
883 /* Generate a list of matches for CS->globpat. Unresolved: should this use
884 TEXT as a match prefix, or just go without? Currently, the code does not
885 use TEXT, just globs CS->globpat and returns the results. If we do decide
886 to use TEXT, we should call quote_string_for_globbing before the call to
889 gen_globpat_matches (cs
, text
)
895 sl
= strlist_create (0);
896 sl
->list
= glob_filename (cs
->globpat
, 0);
897 if (GLOB_FAILED (sl
->list
))
898 sl
->list
= (char **)NULL
;
900 sl
->list_len
= sl
->list_size
= strvec_len (sl
->list
);
904 /* Perform the shell word expansions on CS->words and return the results.
905 Again, this ignores TEXT. */
907 gen_wordlist_matches (cs
, text
)
914 char *ntxt
; /* dequoted TEXT to use in comparisons */
916 if (cs
->words
== 0 || cs
->words
[0] == '\0')
917 return ((STRINGLIST
*)NULL
);
919 /* This used to be a simple expand_string(cs->words, 0), but that won't
920 do -- there's no way to split a simple list into individual words
921 that way, since the shell semantics say that word splitting is done
922 only on the results of expansion. split_at_delims also handles embedded
923 quoted strings and preserves the quotes for the expand_words_shellexp
924 function call that follows. */
925 /* XXX - this is where this function spends most of its time */
926 l
= split_at_delims (cs
->words
, strlen (cs
->words
), (char *)NULL
, -1, 0, (int *)NULL
, (int *)NULL
);
928 return ((STRINGLIST
*)NULL
);
929 /* This will jump back to the top level if the expansion fails... */
930 l2
= expand_words_shellexp (l
);
933 nw
= list_length (l2
);
934 sl
= strlist_create (nw
+ 1);
936 ntxt
= bush_dequote_text (text
);
937 tlen
= STRLEN (ntxt
);
939 for (nw
= 0, l
= l2
; l
; l
= l
->next
)
941 if (tlen
== 0 || STREQN (l
->word
->word
, ntxt
, tlen
))
942 sl
->list
[nw
++] = STRDUP (l
->word
->word
);
944 sl
->list
[sl
->list_len
= nw
] = (char *)NULL
;
954 bind_comp_words (lwords
)
959 v
= find_variable_noref ("COMP_WORDS");
961 v
= make_new_array_variable ("COMP_WORDS");
963 VUNSETATTR (v
, att_nameref
);
966 VUNSETATTR (v
, att_readonly
);
968 if (array_p (v
) == 0)
969 v
= convert_var_to_array (v
);
970 v
= assign_array_var_from_word_list (v
, lwords
, 0);
972 VUNSETATTR (v
, att_invisible
);
975 #endif /* ARRAY_VARS */
978 bind_compfunc_variables (line
, ind
, lwords
, cw
, exported
)
984 char ibuf
[INT_STRLEN_BOUND(int) + 1];
990 /* Set the variables that the function expects while it executes. Maybe
991 these should be in the function environment (temporary_env). */
992 v
= bind_variable ("COMP_LINE", line
, 0);
994 VSETATTR(v
, att_exported
);
996 /* Post bush-4.2: COMP_POINT is characters instead of bytes. */
999 llen
= MB_STRLEN (line
);
1001 value
= inttostr (llen
, ibuf
, sizeof(ibuf
));
1002 v
= bind_int_variable ("COMP_POINT", value
, 0);
1004 VSETATTR(v
, att_exported
);
1006 value
= inttostr (rl_completion_type
, ibuf
, sizeof (ibuf
));
1007 v
= bind_int_variable ("COMP_TYPE", value
, 0);
1009 VSETATTR(v
, att_exported
);
1011 value
= inttostr (rl_completion_invoking_key
, ibuf
, sizeof (ibuf
));
1012 v
= bind_int_variable ("COMP_KEY", value
, 0);
1014 VSETATTR(v
, att_exported
);
1016 /* Since array variables can't be exported, we don't bother making the
1021 v
= bind_comp_words (lwords
);
1022 value
= inttostr (cw
, ibuf
, sizeof(ibuf
));
1023 bind_int_variable ("COMP_CWORD", value
, 0);
1027 array_needs_making
= 1;
1031 unbind_compfunc_variables (exported
)
1034 unbind_variable_noref ("COMP_LINE");
1035 unbind_variable_noref ("COMP_POINT");
1036 unbind_variable_noref ("COMP_TYPE");
1037 unbind_variable_noref ("COMP_KEY");
1039 unbind_variable_noref ("COMP_WORDS");
1040 unbind_variable_noref ("COMP_CWORD");
1043 array_needs_making
= 1;
1046 /* Build the list of words to pass to a function or external command
1047 as arguments. When the function or command is invoked,
1049 $0 == function or command being invoked
1051 $2 == word to be completed (possibly null)
1054 Functions can access all of the words in the current command line
1055 with the COMP_WORDS array. External commands cannot; they have to
1056 make do with the COMP_LINE and COMP_POINT variables. */
1059 build_arg_list (cmd
, cname
, text
, lwords
, ind
)
1066 WORD_LIST
*ret
, *cl
, *l
;
1070 ret
= (WORD_LIST
*)NULL
;
1071 w
= make_word (cmd
);
1072 ret
= make_word_list (w
, (WORD_LIST
*)NULL
); /* $0 */
1074 w
= make_word (cname
); /* $1 */
1075 cl
= ret
->next
= make_word_list (w
, (WORD_LIST
*)NULL
);
1077 w
= make_word (text
);
1078 cl
->next
= make_word_list (w
, (WORD_LIST
*)NULL
); /* $2 */
1081 /* Search lwords for current word */
1082 for (l
= lwords
, i
= 1; l
&& i
< ind
-1; l
= l
->next
, i
++)
1084 w
= (l
&& l
->word
) ? copy_word (l
->word
) : make_word ("");
1085 cl
->next
= make_word_list (w
, (WORD_LIST
*)NULL
);
1090 /* Build a command string with
1091 $0 == cs->funcname (function to execute for completion list)
1092 $1 == command name (command being completed)
1093 $2 = word to be completed (possibly null)
1095 and run in the current shell. The function should put its completion
1096 list into the array variable COMPREPLY. We build a STRINGLIST
1097 from the results and return it.
1099 Since the shell function should return its list of matches in an array
1100 variable, this does nothing if arrays are not compiled into the shell. */
1103 gen_shell_function_matches (cs
, cmd
, text
, line
, ind
, lwords
, nw
, cw
, foundp
)
1118 sh_parser_state_t ps
;
1119 sh_parser_state_t
* restrict pps
;
1120 #if defined (ARRAY_VARS)
1128 funcname
= cs
->funcname
;
1129 f
= find_function (funcname
);
1132 internal_error (_("completion: function `%s' not found"), funcname
);
1135 return ((STRINGLIST
*)NULL
);
1138 #if !defined (ARRAY_VARS)
1139 return ((STRINGLIST
*)NULL
);
1142 /* We pass cw - 1 because command_line_to_word_list returns indices that are
1143 1-based, while bush arrays are 0-based. */
1144 bind_compfunc_variables (line
, ind
, lwords
, cw
- 1, 0);
1146 cmdlist
= build_arg_list (funcname
, cmd
, text
, lwords
, cw
);
1149 save_parser_state (pps
);
1150 begin_unwind_frame ("gen-shell-function-matches");
1151 add_unwind_protect (restore_parser_state
, (char *)pps
);
1152 add_unwind_protect (dispose_words
, (char *)cmdlist
);
1153 add_unwind_protect (unbind_compfunc_variables
, (char *)0);
1155 fval
= execute_shell_function (f
, cmdlist
);
1157 discard_unwind_frame ("gen-shell-function-matches");
1158 restore_parser_state (pps
);
1160 found
= fval
!= EX_NOTFOUND
;
1161 if (fval
== EX_RETRYFAIL
)
1162 found
|= PCOMP_RETRYFAIL
;
1166 /* Now clean up and destroy everything. */
1167 dispose_words (cmdlist
);
1168 unbind_compfunc_variables (0);
1170 /* The list of completions is returned in the array variable COMPREPLY. */
1171 v
= find_variable ("COMPREPLY");
1173 return ((STRINGLIST
*)NULL
);
1174 if (array_p (v
) == 0 && assoc_p (v
) == 0)
1175 v
= convert_var_to_array (v
);
1177 VUNSETATTR (v
, att_invisible
);
1180 if (found
== 0 || (found
& PCOMP_RETRYFAIL
) || a
== 0 || array_p (v
) == 0 || array_empty (a
))
1181 sl
= (STRINGLIST
*)NULL
;
1184 /* XXX - should we filter the list of completions so only those matching
1185 TEXT are returned? Right now, we do not. */
1186 sl
= strlist_create (0);
1187 sl
->list
= array_to_argv (a
, 0);
1188 sl
->list_len
= sl
->list_size
= array_num_elements (a
);
1191 /* XXX - should we unbind COMPREPLY here? */
1192 unbind_variable_noref ("COMPREPLY");
1198 /* Build a command string with
1199 $0 == cs->command (command to execute for completion list)
1200 $1 == command name (command being completed)
1201 $2 == word to be completed (possibly null)
1203 and run it with command substitution. Parse the results, one word
1204 per line, with backslashes allowed to escape newlines. Build a
1205 STRINGLIST from the results and return it. */
1208 gen_command_matches (cs
, cmd
, text
, line
, ind
, lwords
, nw
, cw
)
1217 char *csbuf
, *cscmd
, *t
;
1218 int cmdlen
, cmdsize
, n
, ws
, we
;
1219 WORD_LIST
*cmdlist
, *cl
;
1223 bind_compfunc_variables (line
, ind
, lwords
, cw
, 1);
1224 cmdlist
= build_arg_list (cs
->command
, cmd
, text
, lwords
, cw
);
1226 /* Estimate the size needed for the buffer. */
1227 n
= strlen (cs
->command
);
1229 for (cl
= cmdlist
->next
; cl
; cl
= cl
->next
)
1230 cmdsize
+= STRLEN (cl
->word
->word
) + 3;
1233 /* allocate the string for the command and fill it in. */
1234 cscmd
= (char *)xmalloc (cmdsize
+ 1);
1236 strcpy (cscmd
, cs
->command
); /* $0 */
1238 cscmd
[cmdlen
++] = ' ';
1239 for (cl
= cmdlist
->next
; cl
; cl
= cl
->next
) /* $1, $2, $3, ... */
1241 t
= sh_single_quote (cl
->word
->word
? cl
->word
->word
: "");
1243 RESIZE_MALLOCED_BUFFER (cscmd
, cmdlen
, n
+ 2, cmdsize
, 64);
1244 strcpy (cscmd
+ cmdlen
, t
);
1247 cscmd
[cmdlen
++] = ' ';
1250 cscmd
[cmdlen
] = '\0';
1252 tw
= command_substitute (cscmd
, 0, 0);
1253 csbuf
= tw
? tw
->word
: (char *)NULL
;
1255 dispose_word_desc (tw
);
1257 /* Now clean up and destroy everything. */
1258 dispose_words (cmdlist
);
1260 unbind_compfunc_variables (1);
1262 if (csbuf
== 0 || *csbuf
== '\0')
1265 return ((STRINGLIST
*)NULL
);
1268 /* Now break CSBUF up at newlines, with backslash allowed to escape a
1269 newline, and put the individual words into a STRINGLIST. */
1270 sl
= strlist_create (16);
1271 for (ws
= 0; csbuf
[ws
]; )
1274 while (csbuf
[we
] && csbuf
[we
] != '\n')
1276 if (csbuf
[we
] == '\\' && csbuf
[we
+1] == '\n')
1280 t
= substring (csbuf
, ws
, we
);
1281 if (sl
->list_len
>= sl
->list_size
- 1)
1282 strlist_resize (sl
, sl
->list_size
+ 16);
1283 sl
->list
[sl
->list_len
++] = t
;
1284 while (csbuf
[we
] == '\n') we
++;
1287 sl
->list
[sl
->list_len
] = (char *)NULL
;
1294 command_line_to_word_list (line
, llen
, sentinel
, nwp
, cwp
)
1296 int llen
, sentinel
, *nwp
, *cwp
;
1302 delims
= "()<>;&| \t\n"; /* shell metacharacters break words */
1304 delims
= rl_completer_word_break_characters
;
1306 ret
= split_at_delims (line
, llen
, delims
, sentinel
, SD_NOQUOTEDELIM
|SD_COMPLETE
, nwp
, cwp
);
1310 /* Evaluate COMPSPEC *cs and return all matches for WORD. */
1313 gen_compspec_completions (cs
, cmd
, word
, start
, end
, foundp
)
1320 STRINGLIST
*ret
, *tmatches
;
1322 int llen
, nw
, cw
, found
, foundf
;
1330 debug_printf ("gen_compspec_completions (%s, %s, %d, %d)", cmd
, word
, start
, end
);
1331 debug_printf ("gen_compspec_completions: %s -> %p", cmd
, cs
);
1333 ret
= gen_action_completions (cs
, word
);
1335 if (ret
&& progcomp_debug
)
1337 debug_printf ("gen_action_completions (%p, %s) -->", cs
, word
);
1338 strlist_print (ret
, "\t");
1343 /* Now we start generating completions based on the other members of CS. */
1346 tmatches
= gen_globpat_matches (cs
, word
);
1352 debug_printf ("gen_globpat_matches (%p, %s) -->", cs
, word
);
1353 strlist_print (tmatches
, "\t");
1357 ret
= strlist_append (ret
, tmatches
);
1358 strlist_dispose (tmatches
);
1359 rl_filename_completion_desired
= 1;
1365 tmatches
= gen_wordlist_matches (cs
, word
);
1371 debug_printf ("gen_wordlist_matches (%p, %s) -->", cs
, word
);
1372 strlist_print (tmatches
, "\t");
1376 ret
= strlist_append (ret
, tmatches
);
1377 strlist_dispose (tmatches
);
1381 lwords
= (WORD_LIST
*)NULL
;
1382 line
= (char *)NULL
;
1383 if (cs
->command
|| cs
->funcname
)
1385 /* If we have a command or function to execute, we need to first break
1386 the command line into individual words, find the number of words,
1387 and find the word in the list containing the word to be completed. */
1388 line
= substring (pcomp_line
, start
, end
);
1392 debug_printf ("command_line_to_word_list (%s, %d, %d, %p, %p)",
1393 line
, llen
, pcomp_ind
- start
, &nw
, &cw
);
1395 lwords
= command_line_to_word_list (line
, llen
, pcomp_ind
- start
, &nw
, &cw
);
1396 /* If we skipped a NULL word at the beginning of the line, add it back */
1397 if (lwords
&& lwords
->word
&& cmd
[0] == 0 && lwords
->word
->word
[0] != 0)
1399 lw
= make_bare_word (cmd
);
1400 lwords
= make_word_list (lw
, lwords
);
1405 if (lwords
== 0 && llen
> 0)
1406 debug_printf ("ERROR: command_line_to_word_list returns NULL");
1407 else if (progcomp_debug
)
1409 debug_printf ("command_line_to_word_list -->");
1411 print_word_list (lwords
, "!");
1422 tmatches
= gen_shell_function_matches (cs
, cmd
, word
, line
, pcomp_ind
- start
, lwords
, nw
, cw
, &foundf
);
1430 debug_printf ("gen_shell_function_matches (%p, %s, %s, %p, %d, %d) -->", cs
, cmd
, word
, lwords
, nw
, cw
);
1431 strlist_print (tmatches
, "\t");
1435 ret
= strlist_append (ret
, tmatches
);
1436 strlist_dispose (tmatches
);
1442 tmatches
= gen_command_matches (cs
, cmd
, word
, line
, pcomp_ind
- start
, lwords
, nw
, cw
);
1448 debug_printf ("gen_command_matches (%p, %s, %s, %p, %d, %d) -->", cs
, cmd
, word
, lwords
, nw
, cw
);
1449 strlist_print (tmatches
, "\t");
1453 ret
= strlist_append (ret
, tmatches
);
1454 strlist_dispose (tmatches
);
1458 if (cs
->command
|| cs
->funcname
)
1461 dispose_words (lwords
);
1468 if (found
== 0 || (found
& PCOMP_RETRYFAIL
))
1470 strlist_dispose (ret
);
1476 tmatches
= filter_stringlist (ret
, cs
->filterpat
, word
);
1480 debug_printf ("filter_stringlist (%p, %s, %s) -->", ret
, cs
->filterpat
, word
);
1481 strlist_print (tmatches
, "\t");
1485 if (ret
&& ret
!= tmatches
)
1493 if (cs
->prefix
|| cs
->suffix
)
1494 ret
= strlist_prefix_suffix (ret
, cs
->prefix
, cs
->suffix
);
1496 /* If no matches have been generated and the user has specified that
1497 directory completion should be done as a default, call
1498 gen_action_completions again to generate a list of matching directory
1500 if ((ret
== 0 || ret
->list_len
== 0) && (cs
->options
& COPT_DIRNAMES
))
1502 tcs
= compspec_create ();
1503 tcs
->actions
= CA_DIRECTORY
;
1505 ret
= gen_action_completions (tcs
, word
);
1506 compspec_dispose (tcs
);
1508 else if (cs
->options
& COPT_PLUSDIRS
)
1510 tcs
= compspec_create ();
1511 tcs
->actions
= CA_DIRECTORY
;
1512 tmatches
= gen_action_completions (tcs
, word
);
1513 ret
= strlist_append (ret
, tmatches
);
1514 strlist_dispose (tmatches
);
1515 compspec_dispose (tcs
);
1522 pcomp_set_readline_variables (flags
, nval
)
1525 /* If the user specified that the compspec returns filenames, make
1526 sure that readline knows it. */
1527 if (flags
& COPT_FILENAMES
)
1528 rl_filename_completion_desired
= nval
;
1529 /* If the user doesn't want a space appended, tell readline. */
1530 if (flags
& COPT_NOSPACE
)
1531 rl_completion_suppress_append
= nval
;
1532 /* The value here is inverted, since the default is on and the `noquote'
1533 option is supposed to turn it off */
1534 if (flags
& COPT_NOQUOTE
)
1535 rl_filename_quoting_desired
= 1 - nval
;
1536 if (flags
& COPT_NOSORT
)
1537 rl_sort_completion_matches
= 1 - nval
;
1540 /* Set or unset FLAGS in the options word of the current compspec.
1541 SET_OR_UNSET is 1 for setting, 0 for unsetting. */
1543 pcomp_set_compspec_options (cs
, flags
, set_or_unset
)
1545 int flags
, set_or_unset
;
1547 if (cs
== 0 && ((cs
= pcomp_curcs
) == 0))
1550 cs
->options
|= flags
;
1552 cs
->options
&= ~flags
;
1556 gen_progcomp_completions (ocmd
, cmd
, word
, start
, end
, foundp
, retryp
, lastcs
)
1561 int *foundp
, *retryp
;
1564 COMPSPEC
*cs
, *oldcs
;
1565 const char *oldcmd
, *oldtxt
;
1568 cs
= progcomp_search (ocmd
);
1570 if (cs
== 0 || cs
== *lastcs
)
1580 compspec_dispose (*lastcs
);
1581 cs
->refcount
++; /* XXX */
1584 cs
= compspec_copy (cs
);
1586 oldcs
= pcomp_curcs
;
1587 oldcmd
= pcomp_curcmd
;
1588 oldtxt
= pcomp_curtxt
;
1592 pcomp_curtxt
= word
;
1594 ret
= gen_compspec_completions (cs
, cmd
, word
, start
, end
, foundp
);
1596 pcomp_curcs
= oldcs
;
1597 pcomp_curcmd
= oldcmd
;
1598 pcomp_curtxt
= oldtxt
;
1600 /* We need to conditionally handle setting *retryp here */
1602 *retryp
= foundp
&& (*foundp
& PCOMP_RETRYFAIL
);
1606 *foundp
&= ~PCOMP_RETRYFAIL
;
1607 *foundp
|= cs
->options
;
1610 compspec_dispose (cs
);
1614 /* The driver function for the programmable completion code. Returns a list
1615 of matches for WORD, which is an argument to command CMD. START and END
1616 bound the command currently being completed in pcomp_line (usually
1619 programmable_completions (cmd
, word
, start
, end
, foundp
)
1622 int start
, end
, *foundp
;
1626 char **rmatches
, *t
;
1627 int found
, retry
, count
;
1637 pcomp_line
= rl_line_buffer
;
1638 pcomp_ind
= rl_point
;
1647 /* We look at the basename of CMD if the full command does not have
1648 an associated COMPSPEC. */
1649 ret
= gen_progcomp_completions (ocmd
, ocmd
, word
, start
, oend
, &found
, &retry
, &lastcs
);
1652 t
= strrchr (ocmd
, '/');
1654 ret
= gen_progcomp_completions (t
, ocmd
, word
, start
, oend
, &found
, &retry
, &lastcs
);
1658 ret
= gen_progcomp_completions (DEFAULTCMD
, ocmd
, word
, start
, oend
, &found
, &retry
, &lastcs
);
1661 /* Look up any alias for CMD, try to gen completions for it */
1662 /* Look up the alias, find the value, build a new line replacing CMD
1663 with that value, offsetting PCOMP_IND and END appropriately, reset
1664 PCOMP_LINE to the new line and OCMD with the new command name, then
1665 call gen_progcomp_completions again. We could use alias_expand for
1666 this, but it does more (and less) than we need right now. */
1667 if (found
== 0 && retry
== 0 && progcomp_alias
&& (al
= find_alias (ocmd
)))
1669 char *ncmd
, *nline
, *ntxt
;
1671 size_t nlen
, olen
, llen
;
1673 /* We found an alias for OCMD. Take the value and build a new line */
1675 nlen
= strlen (ntxt
);
1678 olen
= strlen (ocmd
);
1679 lendiff
= nlen
- olen
; /* can be negative */
1680 llen
= strlen (pcomp_line
);
1682 nline
= (char *)xmalloc (llen
+ lendiff
+ 1);
1684 strncpy (nline
, pcomp_line
, start
);
1685 strncpy (nline
+ start
, ntxt
, nlen
);
1686 strcpy (nline
+ start
+ nlen
, pcomp_line
+ start
+ olen
);
1688 /* Find the first word of the alias value and use that as OCMD. We
1689 don't check the alias value to see whether it begins with a valid
1690 command name, so this can be fooled. */
1691 ind
= skip_to_delim (ntxt
, 0, "()<>;&| \t\n", SD_NOJMP
|SD_COMPLETE
);
1693 ncmd
= substring (ntxt
, 0, ind
);
1697 break; /* will free pcomp_line and ocmd later */
1700 /* Adjust PCOMP_IND and OEND appropriately */
1701 pcomp_ind
+= lendiff
;
1704 /* Set up values with new line. WORD stays the same. */
1707 if (pcomp_line
!= rl_line_buffer
)
1713 /* And go back and start over. */
1722 internal_warning (_("programmable_completion: %s: possible retry loop"), cmd
);
1728 if (pcomp_line
!= rl_line_buffer
)
1735 rmatches
= ret
->list
;
1739 rmatches
= (char **)NULL
;
1744 if (lastcs
) /* XXX - should be while? */
1745 compspec_dispose (lastcs
);
1747 /* XXX restore pcomp_line and pcomp_ind? */
1748 pcomp_line
= rl_line_buffer
;
1749 pcomp_ind
= rl_point
;
1754 #endif /* PROGRAMMABLE_COMPLETION */