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