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