40fcc34f8325303455a38c81148bec760c9eb9a6
[platform/upstream/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; they have to
949    make do  with the COMP_LINE and COMP_POINT variables. */
950
951 static WORD_LIST *
952 build_arg_list (cmd, text, lwords, ind)
953      char *cmd;
954      const char *text;
955      WORD_LIST *lwords;
956      int ind;
957 {
958   WORD_LIST *ret, *cl, *l;
959   WORD_DESC *w;
960   int i;
961
962   ret = (WORD_LIST *)NULL;
963   w = make_word (cmd);
964   ret = make_word_list (w, (WORD_LIST *)NULL);
965
966   w = (lwords && lwords->word) ? copy_word (lwords->word) : make_word ("");
967   cl = ret->next = make_word_list (w, (WORD_LIST *)NULL);
968
969   w = make_word (text);
970   cl->next = make_word_list (w, (WORD_LIST *)NULL);
971   cl = cl->next;
972
973   /* Search lwords for current word */
974   for (l = lwords, i = 1; l && i < ind-1; l = l->next, i++)
975     ;
976   w = (l && l->word) ? copy_word (l->word) : make_word ("");
977   cl->next = make_word_list (w, (WORD_LIST *)NULL);
978
979   return ret;
980 }
981
982 /* Build a command string with
983         $0 == cs->funcname      (function to execute for completion list)
984         $1 == command name      (command being completed)
985         $2 = word to be completed (possibly null)
986         $3 = previous word
987    and run in the current shell.  The function should put its completion
988    list into the array variable COMPREPLY.  We build a STRINGLIST
989    from the results and return it.
990
991    Since the shell function should return its list of matches in an array
992    variable, this does nothing if arrays are not compiled into the shell. */
993
994 static STRINGLIST *
995 gen_shell_function_matches (cs, text, line, ind, lwords, nw, cw)
996      COMPSPEC *cs;
997      const char *text;
998      char *line;
999      int ind;
1000      WORD_LIST *lwords;
1001      int nw, cw;
1002 {
1003   char *funcname;
1004   STRINGLIST *sl;
1005   SHELL_VAR *f, *v;
1006   WORD_LIST *cmdlist;
1007   int fval;
1008   sh_parser_state_t ps;
1009   sh_parser_state_t * restrict pps;
1010 #if defined (ARRAY_VARS)
1011   ARRAY *a;
1012 #endif
1013
1014   funcname = cs->funcname;
1015   f = find_function (funcname);
1016   if (f == 0)
1017     {
1018       internal_error (_("completion: function `%s' not found"), funcname);
1019       rl_ding ();
1020       rl_on_new_line ();
1021       return ((STRINGLIST *)NULL);
1022     }
1023
1024 #if !defined (ARRAY_VARS)
1025   return ((STRINGLIST *)NULL);
1026 #else
1027
1028   /* We pass cw - 1 because command_line_to_word_list returns indices that are
1029      1-based, while bash arrays are 0-based. */
1030   bind_compfunc_variables (line, ind, lwords, cw - 1, 0);
1031
1032   cmdlist = build_arg_list (funcname, text, lwords, cw);
1033
1034   pps = &ps;
1035   save_parser_state (pps);
1036   begin_unwind_frame ("gen-shell-function-matches");
1037   add_unwind_protect (restore_parser_state, (char *)pps);
1038   add_unwind_protect (dispose_words, (char *)cmdlist);
1039   add_unwind_protect (unbind_compfunc_variables, (char *)0);
1040
1041   fval = execute_shell_function (f, cmdlist);  
1042
1043   discard_unwind_frame ("gen-shell-function-matches");
1044   restore_parser_state (pps);
1045
1046   /* Now clean up and destroy everything. */
1047   dispose_words (cmdlist);
1048   unbind_compfunc_variables (0);
1049
1050   /* The list of completions is returned in the array variable COMPREPLY. */
1051   v = find_variable ("COMPREPLY");
1052   if (v == 0)
1053     return ((STRINGLIST *)NULL);
1054   if (array_p (v) == 0)
1055     v = convert_var_to_array (v);
1056
1057   VUNSETATTR (v, att_invisible);
1058
1059   a = array_cell (v);
1060   if (a == 0 || array_empty (a))
1061     sl = (STRINGLIST *)NULL;
1062   else
1063     {
1064       /* XXX - should we filter the list of completions so only those matching
1065          TEXT are returned?  Right now, we do not. */
1066       sl = strlist_create (0);
1067       sl->list = array_to_argv (a);
1068       sl->list_len = sl->list_size = array_num_elements (a);
1069     }
1070
1071   /* XXX - should we unbind COMPREPLY here? */
1072   unbind_variable ("COMPREPLY");
1073
1074   return (sl);
1075 #endif
1076 }
1077
1078 /* Build a command string with
1079         $0 == cs->command       (command to execute for completion list)
1080         $1 == command name      (command being completed)
1081         $2 = word to be completed (possibly null)
1082         $3 = previous word
1083    and run in with command substitution.  Parse the results, one word
1084    per line, with backslashes allowed to escape newlines.  Build a
1085    STRINGLIST from the results and return it. */
1086
1087 static STRINGLIST *
1088 gen_command_matches (cs, text, line, ind, lwords, nw, cw)
1089      COMPSPEC *cs;
1090      const char *text;
1091      char *line;
1092      int ind;
1093      WORD_LIST *lwords;
1094      int nw, cw;
1095 {
1096   char *csbuf, *cscmd, *t;
1097   int cmdlen, cmdsize, n, ws, we;
1098   WORD_LIST *cmdlist, *cl;
1099   WORD_DESC *tw;
1100   STRINGLIST *sl;
1101
1102   bind_compfunc_variables (line, ind, lwords, cw, 1);
1103   cmdlist = build_arg_list (cs->command, text, lwords, cw);
1104
1105   /* Estimate the size needed for the buffer. */
1106   n = strlen (cs->command);
1107   cmdsize = n + 1;
1108   for (cl = cmdlist->next; cl; cl = cl->next)
1109     cmdsize += STRLEN (cl->word->word) + 3;
1110   cmdsize += 2;
1111
1112   /* allocate the string for the command and fill it in. */
1113   cscmd = (char *)xmalloc (cmdsize + 1);
1114
1115   strcpy (cscmd, cs->command);                  /* $0 */
1116   cmdlen = n;
1117   cscmd[cmdlen++] = ' ';
1118   for (cl = cmdlist->next; cl; cl = cl->next)   /* $1, $2, $3, ... */
1119     {
1120       t = sh_single_quote (cl->word->word ? cl->word->word : "");
1121       n = strlen (t);
1122       RESIZE_MALLOCED_BUFFER (cscmd, cmdlen, n + 2, cmdsize, 64);
1123       strcpy (cscmd + cmdlen, t);
1124       cmdlen += n;
1125       if (cl->next)
1126         cscmd[cmdlen++] = ' ';
1127       free (t);
1128     }
1129   cscmd[cmdlen] = '\0';
1130
1131   tw = command_substitute (cscmd, 0);
1132   csbuf = tw ? tw->word : (char *)NULL;
1133   dispose_word_desc (tw);
1134
1135   /* Now clean up and destroy everything. */
1136   dispose_words (cmdlist);
1137   free (cscmd);
1138   unbind_compfunc_variables (1);
1139
1140   if (csbuf == 0 || *csbuf == '\0')
1141     {
1142       FREE (csbuf);
1143       return ((STRINGLIST *)NULL);
1144     }
1145
1146   /* Now break CSBUF up at newlines, with backslash allowed to escape a
1147      newline, and put the individual words into a STRINGLIST. */
1148   sl = strlist_create (16);
1149   for (ws = 0; csbuf[ws]; )
1150     {
1151       we = ws;
1152       while (csbuf[we] && csbuf[we] != '\n')
1153         {
1154           if (csbuf[we] == '\\' && csbuf[we+1] == '\n')
1155             we++;
1156           we++;
1157         }
1158       t = substring (csbuf, ws, we);
1159       if (sl->list_len >= sl->list_size - 1)
1160         strlist_resize (sl, sl->list_size + 16);
1161       sl->list[sl->list_len++] = t;
1162       while (csbuf[we] == '\n') we++;
1163       ws = we;
1164     }
1165   sl->list[sl->list_len] = (char *)NULL;
1166
1167   free (csbuf);
1168   return (sl);
1169 }
1170
1171 static WORD_LIST *
1172 command_line_to_word_list (line, llen, sentinel, nwp, cwp)
1173      char *line;
1174      int llen, sentinel, *nwp, *cwp;
1175 {
1176   WORD_LIST *ret;
1177   char *delims;
1178   int i, j;
1179
1180   delims = xmalloc (strlen (rl_completer_word_break_characters) + 1);
1181   for (i = j = 0; rl_completer_word_break_characters[i]; i++)
1182     if (rl_completer_word_break_characters[i] != '\'' && rl_completer_word_break_characters[i] != '"')
1183       delims[j++] = rl_completer_word_break_characters[i];
1184   delims[j] = '\0';
1185   ret = split_at_delims (line, llen, delims, sentinel, nwp, cwp);
1186   free (delims);
1187   return (ret);
1188 }
1189
1190 /* Evaluate COMPSPEC *cs and return all matches for WORD. */
1191
1192 STRINGLIST *
1193 gen_compspec_completions (cs, cmd, word, start, end)
1194      COMPSPEC *cs;
1195      const char *cmd;
1196      const char *word;
1197      int start, end;
1198 {
1199   STRINGLIST *ret, *tmatches;
1200   char *line;
1201   int llen, nw, cw;
1202   WORD_LIST *lwords;
1203   COMPSPEC *tcs;
1204
1205 #ifdef DEBUG
1206   debug_printf ("gen_compspec_completions (%s, %s, %d, %d)", cmd, word, start, end);
1207   debug_printf ("gen_compspec_completions: %s -> %p", cmd, cs);
1208 #endif
1209   ret = gen_action_completions (cs, word);
1210 #ifdef DEBUG
1211   if (ret && progcomp_debug)
1212     {
1213       debug_printf ("gen_action_completions (%p, %s) -->", cs, word);
1214       strlist_print (ret, "\t");
1215       rl_on_new_line ();
1216     }
1217 #endif
1218
1219   /* Now we start generating completions based on the other members of CS. */
1220   if (cs->globpat)
1221     {
1222       tmatches = gen_globpat_matches (cs, word);
1223       if (tmatches)
1224         {
1225 #ifdef DEBUG
1226           if (progcomp_debug)
1227             {
1228               debug_printf ("gen_globpat_matches (%p, %s) -->", cs, word);
1229               strlist_print (tmatches, "\t");
1230               rl_on_new_line ();
1231             }
1232 #endif
1233           ret = strlist_append (ret, tmatches);
1234           strlist_dispose (tmatches);
1235           rl_filename_completion_desired = 1;
1236         }
1237     }
1238
1239   if (cs->words)
1240     {
1241       tmatches = gen_wordlist_matches (cs, word);
1242       if (tmatches)
1243         {
1244 #ifdef DEBUG
1245           if (progcomp_debug)
1246             {
1247               debug_printf ("gen_wordlist_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         }
1255     }
1256
1257   lwords = (WORD_LIST *)NULL;
1258   line = (char *)NULL;
1259   if (cs->command || cs->funcname)
1260     {
1261       /* If we have a command or function to execute, we need to first break
1262          the command line into individual words, find the number of words,
1263          and find the word in the list containing the word to be completed. */
1264       line = substring (rl_line_buffer, start, end);
1265       llen = end - start;
1266
1267 #ifdef DEBUG
1268       debug_printf ("command_line_to_word_list (%s, %d, %d, %p, %p)",
1269                 line, llen, rl_point - start, &nw, &cw);
1270 #endif
1271       lwords = command_line_to_word_list (line, llen, rl_point - start, &nw, &cw);
1272 #ifdef DEBUG
1273       if (lwords == 0 && llen > 0)
1274         debug_printf ("ERROR: command_line_to_word_list returns NULL");
1275       else if (progcomp_debug)
1276         {
1277           debug_printf ("command_line_to_word_list -->");
1278           printf ("\t");
1279           print_word_list (lwords, "!");
1280           printf ("\n");
1281           fflush(stdout);
1282           rl_on_new_line ();
1283         }
1284 #endif
1285     }
1286
1287   if (cs->funcname)
1288     {
1289       tmatches = gen_shell_function_matches (cs, word, line, rl_point - start, lwords, nw, cw);
1290       if (tmatches)
1291         {
1292 #ifdef DEBUG
1293           if (progcomp_debug)
1294             {
1295               debug_printf ("gen_shell_function_matches (%p, %s, %p, %d, %d) -->", cs, word, lwords, nw, cw);
1296               strlist_print (tmatches, "\t");
1297               rl_on_new_line ();
1298             }
1299 #endif
1300           ret = strlist_append (ret, tmatches);
1301           strlist_dispose (tmatches);
1302         }
1303     }
1304
1305   if (cs->command)
1306     {
1307       tmatches = gen_command_matches (cs, word, line, rl_point - start, lwords, nw, cw);
1308       if (tmatches)
1309         {
1310 #ifdef DEBUG
1311           if (progcomp_debug)
1312             {
1313               debug_printf ("gen_command_matches (%p, %s, %p, %d, %d) -->", cs, word, lwords, nw, cw);
1314               strlist_print (tmatches, "\t");
1315               rl_on_new_line ();
1316             }
1317 #endif
1318           ret = strlist_append (ret, tmatches);
1319           strlist_dispose (tmatches);
1320         }
1321     }
1322
1323   if (cs->command || cs->funcname)
1324     {
1325       if (lwords)
1326         dispose_words (lwords);
1327       FREE (line);
1328     }
1329
1330   if (cs->filterpat)
1331     {
1332       tmatches = filter_stringlist (ret, cs->filterpat, word);
1333 #ifdef DEBUG
1334       if (progcomp_debug)
1335         {
1336           debug_printf ("filter_stringlist (%p, %s, %s) -->", ret, cs->filterpat, word);
1337           strlist_print (tmatches, "\t");
1338           rl_on_new_line ();
1339         }
1340 #endif
1341       if (ret && ret != tmatches)
1342         {
1343           FREE (ret->list);
1344           free (ret);
1345         }
1346       ret = tmatches;
1347     }
1348
1349   if (cs->prefix || cs->suffix)
1350     ret = strlist_prefix_suffix (ret, cs->prefix, cs->suffix);
1351
1352   /* If no matches have been generated and the user has specified that
1353       directory completion should be done as a default, call
1354       gen_action_completions again to generate a list of matching directory
1355       names. */
1356   if ((ret == 0 || ret->list_len == 0) && (cs->options & COPT_DIRNAMES))
1357     {
1358       tcs = compspec_create ();
1359       tcs->actions = CA_DIRECTORY;
1360       ret = gen_action_completions (tcs, word);
1361       compspec_dispose (tcs);
1362     }
1363   else if (cs->options & COPT_PLUSDIRS)
1364     {
1365       tcs = compspec_create ();
1366       tcs->actions = CA_DIRECTORY;
1367       tmatches = gen_action_completions (tcs, word);
1368       ret = strlist_append (ret, tmatches);
1369       strlist_dispose (tmatches);
1370       compspec_dispose (tcs);
1371     }
1372
1373   return (ret);
1374 }
1375
1376 void
1377 pcomp_set_readline_variables (flags, nval)
1378      int flags, nval;
1379 {
1380   /* If the user specified that the compspec returns filenames, make
1381      sure that readline knows it. */
1382   if (flags & COPT_FILENAMES)
1383     rl_filename_completion_desired = nval;
1384   /* If the user doesn't want a space appended, tell readline. */
1385   if (flags & COPT_NOSPACE)
1386     rl_completion_suppress_append = nval;
1387 }
1388
1389 /* Set or unset FLAGS in the options word of the current compspec.
1390    SET_OR_UNSET is 1 for setting, 0 for unsetting. */
1391 void
1392 pcomp_set_compspec_options (cs, flags, set_or_unset)
1393      COMPSPEC *cs;
1394      int flags, set_or_unset;
1395 {
1396   if (cs == 0 && ((cs = pcomp_curcs) == 0))
1397     return;
1398   if (set_or_unset)
1399     cs->options |= flags;
1400   else
1401     cs->options &= ~flags;
1402 }
1403
1404 /* The driver function for the programmable completion code.  Returns a list
1405    of matches for WORD, which is an argument to command CMD.  START and END
1406    bound the command currently being completed in rl_line_buffer. */
1407 char **
1408 programmable_completions (cmd, word, start, end, foundp)
1409      const char *cmd;
1410      const char *word;
1411      int start, end, *foundp;
1412 {
1413   COMPSPEC *cs, *oldcs;
1414   STRINGLIST *ret;
1415   char **rmatches, *t;
1416   const char *oldcmd;
1417
1418   /* We look at the basename of CMD if the full command does not have
1419      an associated COMPSPEC. */
1420   cs = progcomp_search (cmd);
1421   if (cs == 0)
1422     {
1423       t = strrchr (cmd, '/');
1424       if (t)
1425         cs = progcomp_search (++t);
1426     }
1427   if (cs == 0)
1428     {
1429       if (foundp)
1430         *foundp = 0;
1431       return ((char **)NULL);
1432     }
1433
1434   cs = compspec_copy (cs);
1435
1436   oldcs = pcomp_curcs;
1437   oldcmd = pcomp_curcmd;
1438
1439   pcomp_curcs = cs;
1440   pcomp_curcmd = cmd;
1441
1442   /* Signal the caller that we found a COMPSPEC for this command, and pass
1443      back any meta-options associated with the compspec. */
1444   if (foundp)
1445     *foundp = 1|cs->options;
1446
1447   ret = gen_compspec_completions (cs, cmd, word, start, end);
1448
1449   pcomp_curcs = oldcs;
1450   pcomp_curcmd = oldcmd;
1451
1452   compspec_dispose (cs);
1453
1454   if (ret)
1455     {
1456       rmatches = ret->list;
1457       free (ret);
1458     }
1459   else
1460     rmatches = (char **)NULL;
1461
1462   return (rmatches);
1463 }
1464
1465 #endif /* PROGRAMMABLE_COMPLETION */