]> git.ipfire.org Git - thirdparty/bash.git/blob - pcomplete.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/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 */