]> git.ipfire.org Git - thirdparty/bash.git/blame - bashline.c
Imported from ../bash-2.0.tar.gz.
[thirdparty/bash.git] / bashline.c
CommitLineData
726f6388
JA
1/* bashline.c -- Bash's interface to the readline library. */
2
3/* Copyright (C) 1987,1991 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 it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 1, or (at your option)
10 any later version.
11
12 Bash is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash; see the file COPYING. If not, write to the Free
19 Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
ccc6cda3
JA
21#include "config.h"
22
23#if defined (READLINE)
24
726f6388
JA
25#include "bashtypes.h"
26#include "posixstat.h"
27
ccc6cda3
JA
28#if defined (HAVE_UNISTD_H)
29# include <unistd.h>
30#endif
31
726f6388
JA
32#include <stdio.h>
33#include "bashansi.h"
726f6388
JA
34#include "shell.h"
35#include "builtins.h"
726f6388 36#include "bashhist.h"
ccc6cda3 37#include "bashline.h"
726f6388 38#include "execute_cmd.h"
ccc6cda3
JA
39#include "pathexp.h"
40#include "builtins/common.h"
41#include <readline/rlconf.h>
42#include <readline/readline.h>
43#include <readline/history.h>
44
45#include <glob/glob.h>
726f6388
JA
46
47#if defined (ALIAS)
48# include "alias.h"
49#endif
50
726f6388
JA
51#if defined (BRACE_COMPLETION)
52extern void bash_brace_completion ();
53#endif /* BRACE_COMPLETION */
54
55/* Functions bound to keys in Readline for Bash users. */
56static void shell_expand_line ();
57static void display_shell_version (), operate_and_get_next ();
58static void history_expand_line (), bash_ignore_filenames ();
59
60/* Helper functions for Readline. */
61static int bash_directory_completion_hook ();
62static void filename_completion_ignore ();
63static void bash_push_line ();
64
65static char **attempt_shell_completion ();
66static char *variable_completion_function ();
67static char *hostname_completion_function ();
68static char *command_word_completion_function ();
69static char *command_subst_completion_function ();
ccc6cda3
JA
70static void dynamic_complete_history ();
71
72static char *glob_complete_word ();
73static void bash_glob_expand_word ();
74static void bash_glob_list_expansions ();
726f6388
JA
75
76static void snarf_hosts_from_file (), add_host_name ();
726f6388 77
ccc6cda3
JA
78static char *bash_dequote_filename ();
79static char *bash_quote_filename ();
80
81#if defined (ALIAS)
82static int posix_edit_macros ();
83#endif
726f6388
JA
84
85/* Variables used here but defined in other files. */
86extern int posixly_correct, no_symbolic_links;
87extern int rl_explicit_arg;
88extern char *current_prompt_string, *ps1_prompt;
89extern STRING_INT_ALIST word_token_alist[];
90extern Function *rl_last_func;
91extern int rl_filename_completion_desired;
92
ccc6cda3
JA
93/* Helper functions from subst.c */
94extern int char_is_quoted ();
95extern int unclosed_pair ();
96
726f6388
JA
97/* SPECIFIC_COMPLETION_FUNCTIONS specifies that we have individual
98 completion functions which indicate what type of completion should be
99 done (at or before point) that can be bound to key sequences with
100 the readline library. */
101#define SPECIFIC_COMPLETION_FUNCTIONS
102
103#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
ccc6cda3
JA
104static void bash_specific_completion ();
105static void bash_complete_filename (), bash_possible_filename_completions ();
106static void bash_complete_filename_internal ();
107static void bash_complete_username (), bash_possible_username_completions ();
108static void bash_complete_username_internal ();
109static void bash_complete_hostname (), bash_possible_hostname_completions ();
110static void bash_complete_hostname_internal ();
111static void bash_complete_variable (), bash_possible_variable_completions ();
112static void bash_complete_variable_internal ();
113static void bash_complete_command (), bash_possible_command_completions ();
114static void bash_complete_command_internal ();
726f6388
JA
115#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
116
726f6388
JA
117#if defined (VI_MODE)
118static void vi_edit_and_execute_command ();
726f6388
JA
119#endif
120
ccc6cda3
JA
121/* Non-zero once initalize_readline () has been called. */
122int bash_readline_initialized = 0;
123
124/* If non-zero, we do hostname completion, breaking words at `@' and
125 trying to complete the stuff after the `@' from our own internal
126 host list. */
127int perform_hostname_completion = 1;
128
129static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
130static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
131
726f6388
JA
132static Function *old_rl_startup_hook = (Function *) NULL;
133
ccc6cda3
JA
134/* What kind of quoting is performed by bash_quote_filename:
135 COMPLETE_DQUOTE = double-quoting the filename
136 COMPLETE_SQUOTE = single_quoting the filename
137 COMPLETE_BSQUOTE = backslash-quoting special chars in the filename
138*/
139#define COMPLETE_DQUOTE 1
140#define COMPLETE_SQUOTE 2
141#define COMPLETE_BSQUOTE 3
142static int completion_quoting_style = COMPLETE_BSQUOTE;
143
726f6388
JA
144/* Change the readline VI-mode keymaps into or out of Posix.2 compliance.
145 Called when the shell is put into or out of `posix' mode. */
146void
147posix_readline_initialize (on_or_off)
148 int on_or_off;
149{
ccc6cda3
JA
150 if (on_or_off)
151 rl_variable_bind ("comment-begin", "#");
726f6388 152#if defined (VI_MODE)
ccc6cda3
JA
153 rl_bind_key_in_map (CTRL('I'), on_or_off ? rl_insert : rl_complete, vi_insertion_keymap);
154#endif
155}
156
157void
158enable_hostname_completion (on_or_off)
159 int on_or_off;
160{
726f6388
JA
161 if (on_or_off)
162 {
ccc6cda3
JA
163 perform_hostname_completion = 1;
164 rl_special_prefixes = "$@";
165 rl_completer_word_break_characters = bash_completer_word_break_characters;
726f6388
JA
166 }
167 else
ccc6cda3
JA
168 {
169 perform_hostname_completion = 0;
170 rl_special_prefixes = "$";
171 rl_completer_word_break_characters = bash_nohostname_word_break_characters;
172 }
173}
726f6388
JA
174
175/* Called once from parse.y if we are going to use readline. */
176void
177initialize_readline ()
178{
179 if (bash_readline_initialized)
180 return;
181
182 rl_terminal_name = get_string_value ("TERM");
183 rl_instream = stdin;
184 rl_outstream = stderr;
726f6388
JA
185
186 /* Allow conditional parsing of the ~/.inputrc file. */
187 rl_readline_name = "Bash";
188
189 /* Bind up our special shell functions. */
190 rl_add_defun ("shell-expand-line", (Function *)shell_expand_line, -1);
ccc6cda3 191 rl_bind_key_in_map (CTRL('E'), (Function *)shell_expand_line, emacs_meta_keymap);
726f6388
JA
192
193 /* Bind up our special shell functions. */
194 rl_add_defun ("history-expand-line", (Function *)history_expand_line, -1);
195 rl_bind_key_in_map ('^', (Function *)history_expand_line, emacs_meta_keymap);
196
197 /* Backwards compatibility. */
198 rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1);
199
200 rl_add_defun
201 ("operate-and-get-next", (Function *)operate_and_get_next, CTRL('O'));
202
203 rl_add_defun
204 ("display-shell-version", (Function *)display_shell_version, -1);
726f6388
JA
205 rl_bind_key_in_map
206 (CTRL ('V'), (Function *)display_shell_version, emacs_ctlx_keymap);
207
208 /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
209 so it is not necessary to allow C-M-j for context switching. Turn
210 off this occasionally confusing behaviour. */
211 rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
212 rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap);
213#if defined (VI_MODE)
214 rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap);
215#endif
ccc6cda3 216
726f6388
JA
217#if defined (BRACE_COMPLETION)
218 rl_add_defun ("complete-into-braces", bash_brace_completion, -1);
219 rl_bind_key_in_map ('{', bash_brace_completion, emacs_meta_keymap);
220#endif /* BRACE_COMPLETION */
221
222#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
223 rl_add_defun ("complete-filename", bash_complete_filename, -1);
224 rl_bind_key_in_map ('/', bash_complete_filename, emacs_meta_keymap);
225 rl_add_defun ("possible-filename-completions",
226 bash_possible_filename_completions, -1);
ccc6cda3 227 rl_bind_key_in_map ('/', bash_possible_filename_completions, emacs_ctlx_keymap);
726f6388
JA
228
229 rl_add_defun ("complete-username", bash_complete_username, -1);
230 rl_bind_key_in_map ('~', bash_complete_username, emacs_meta_keymap);
231 rl_add_defun ("possible-username-completions",
232 bash_possible_username_completions, -1);
ccc6cda3 233 rl_bind_key_in_map ('~', bash_possible_username_completions, emacs_ctlx_keymap);
726f6388
JA
234
235 rl_add_defun ("complete-hostname", bash_complete_hostname, -1);
236 rl_bind_key_in_map ('@', bash_complete_hostname, emacs_meta_keymap);
237 rl_add_defun ("possible-hostname-completions",
238 bash_possible_hostname_completions, -1);
ccc6cda3 239 rl_bind_key_in_map ('@', bash_possible_hostname_completions, emacs_ctlx_keymap);
726f6388
JA
240
241 rl_add_defun ("complete-variable", bash_complete_variable, -1);
242 rl_bind_key_in_map ('$', bash_complete_variable, emacs_meta_keymap);
243 rl_add_defun ("possible-variable-completions",
244 bash_possible_variable_completions, -1);
ccc6cda3 245 rl_bind_key_in_map ('$', bash_possible_variable_completions, emacs_ctlx_keymap);
726f6388
JA
246
247 rl_add_defun ("complete-command", bash_complete_command, -1);
248 rl_bind_key_in_map ('!', bash_complete_command, emacs_meta_keymap);
249 rl_add_defun ("possible-command-completions",
250 bash_possible_command_completions, -1);
ccc6cda3
JA
251 rl_bind_key_in_map ('!', bash_possible_command_completions, emacs_ctlx_keymap);
252
253 rl_add_defun ("glob-expand-word", bash_glob_expand_word, -1);
254 rl_add_defun ("glob-list-expansions", bash_glob_list_expansions, -1);
255 rl_bind_key_in_map ('*', bash_glob_expand_word, emacs_ctlx_keymap);
256 rl_bind_key_in_map ('g', bash_glob_list_expansions, emacs_ctlx_keymap);
726f6388
JA
257
258#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
259
726f6388
JA
260 rl_add_defun ("dynamic-complete-history", dynamic_complete_history, -1);
261 rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap);
726f6388
JA
262
263 /* Tell the completer that we want a crack first. */
264 rl_attempted_completion_function = (CPPFunction *)attempt_shell_completion;
265
266 /* Tell the completer that we might want to follow symbolic links or
267 do other expansion on directory names. */
268 rl_directory_completion_hook = bash_directory_completion_hook;
269
270 /* Tell the filename completer we want a chance to ignore some names. */
271 rl_ignore_some_completions_function = (Function *)filename_completion_ignore;
272
273#if defined (VI_MODE)
274 rl_bind_key_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap);
ccc6cda3
JA
275# if defined (ALIAS)
276 rl_bind_key_in_map ('@', posix_edit_macros, vi_movement_keymap);
277# endif
726f6388
JA
278#endif
279
280 rl_completer_quote_characters = "'\"";
ccc6cda3
JA
281
282 /* This sets rl_completer_word_break_characters and rl_special_prefixes
283 to the appropriate values, depending on whether or not hostname
284 completion is enabled. */
285 enable_hostname_completion (perform_hostname_completion);
286
287 /* characters that need to be quoted when appearing in filenames. */
288 rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!";
289 rl_filename_quoting_function = bash_quote_filename;
290 rl_filename_dequoting_function = bash_dequote_filename;
291 rl_char_is_quoted_p = char_is_quoted;
726f6388
JA
292
293 if (posixly_correct)
294 posix_readline_initialize (1);
295
296 bash_readline_initialized = 1;
297}
298
299/* On Sun systems at least, rl_attempted_completion_function can end up
300 getting set to NULL, and rl_completion_entry_function set to do command
301 word completion if Bash is interrupted while trying to complete a command
302 word. This just resets all the completion functions to the right thing.
303 It's called from throw_to_top_level(). */
304void
305bashline_reinitialize ()
306{
307 tilde_initialize ();
308 rl_attempted_completion_function = attempt_shell_completion;
309 rl_completion_entry_function = (Function *)NULL;
310 rl_directory_completion_hook = bash_directory_completion_hook;
311 rl_ignore_some_completions_function = (Function *)filename_completion_ignore;
312}
313
314/* Contains the line to push into readline. */
315static char *push_to_readline = (char *)NULL;
316
317/* Push the contents of push_to_readline into the
318 readline buffer. */
319static void
320bash_push_line ()
321{
322 if (push_to_readline)
323 {
324 rl_insert_text (push_to_readline);
325 free (push_to_readline);
326 push_to_readline = (char *)NULL;
327 rl_startup_hook = old_rl_startup_hook;
328 }
329}
330
331/* Call this to set the initial text for the next line to read
332 from readline. */
333int
334bash_re_edit (line)
335 char *line;
336{
ccc6cda3 337 FREE (push_to_readline);
726f6388
JA
338
339 push_to_readline = savestring (line);
340 old_rl_startup_hook = rl_startup_hook;
341 rl_startup_hook = (Function *)bash_push_line;
342
343 return (0);
344}
345
346static void
347display_shell_version (count, c)
348 int count, c;
349{
350 crlf ();
ccc6cda3 351 show_shell_version (0);
726f6388
JA
352 putc ('\r', rl_outstream);
353 fflush (rl_outstream);
354 rl_on_new_line ();
355 rl_redisplay ();
356}
357
358/* **************************************************************** */
359/* */
360/* Readline Stuff */
361/* */
362/* **************************************************************** */
363
364/* If the user requests hostname completion, then simply build a list
365 of hosts, and complete from that forever more. */
726f6388
JA
366
367/* The kept list of hostnames. */
368static char **hostname_list = (char **)NULL;
369
370/* The physical size of the above list. */
ccc6cda3 371static int hostname_list_size;
726f6388 372
ccc6cda3
JA
373/* The number of hostnames in the above list. */
374static int hostname_list_length;
726f6388
JA
375
376/* Whether or not HOSTNAME_LIST has been initialized. */
377int hostname_list_initialized = 0;
378
726f6388
JA
379/* Initialize the hostname completion table. */
380static void
381initialize_hostname_list ()
382{
383 char *temp;
384
385 temp = get_string_value ("HOSTFILE");
ccc6cda3 386 if (temp == 0)
726f6388 387 temp = get_string_value ("hostname_completion_file");
ccc6cda3
JA
388 if (temp == 0)
389 temp = DEFAULT_HOSTS_FILE;
726f6388
JA
390
391 snarf_hosts_from_file (temp);
726f6388
JA
392
393 if (hostname_list)
394 hostname_list_initialized++;
395}
396
397/* Add NAME to the list of hosts. */
398static void
399add_host_name (name)
400 char *name;
401{
ccc6cda3
JA
402 long size;
403
726f6388
JA
404 if (hostname_list_length + 2 > hostname_list_size)
405 {
ccc6cda3
JA
406 hostname_list_size = (hostname_list_size + 32) - (hostname_list_size % 32);
407 size = hostname_list_size * sizeof (char *);
408 hostname_list = (char **)xrealloc (hostname_list, size);
726f6388
JA
409 }
410
ccc6cda3
JA
411 hostname_list[hostname_list_length++] = savestring (name);
412 hostname_list[hostname_list_length] = (char *)NULL;
726f6388
JA
413}
414
415#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
416
417static void
418snarf_hosts_from_file (filename)
419 char *filename;
420{
ccc6cda3 421 FILE *file;
726f6388
JA
422 char *temp, buffer[256], name[256];
423 register int i, start;
424
ccc6cda3
JA
425 file = fopen (filename, "r");
426 if (file == 0)
726f6388
JA
427 return;
428
429 while (temp = fgets (buffer, 255, file))
430 {
431 /* Skip to first character. */
ccc6cda3
JA
432 for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++)
433 ;
726f6388 434
ccc6cda3
JA
435 /* If comment or blank line, ignore. */
436 if (buffer[i] == '\0' || buffer[i] == '#')
726f6388
JA
437 continue;
438
439 /* If `preprocessor' directive, do the include. */
ccc6cda3 440 if (strncmp (buffer + i, "$include ", 9) == 0)
726f6388 441 {
ccc6cda3 442 char *incfile, *t;
726f6388
JA
443
444 /* Find start of filename. */
ccc6cda3
JA
445 for (incfile = buffer + i + 9; *incfile && whitespace (*incfile); incfile++)
446 ;
726f6388
JA
447
448 /* Find end of filename. */
ccc6cda3
JA
449 for (t = incfile; *t && cr_whitespace (*t) == 0; t++)
450 ;
726f6388
JA
451
452 *t = '\0';
453
ccc6cda3 454 snarf_hosts_from_file (incfile);
726f6388
JA
455 continue;
456 }
457
ccc6cda3
JA
458 /* Skip internet address if present. */
459 if (digit (buffer[i]))
460 for (; buffer[i] && cr_whitespace (buffer[i]) == 0; i++);
726f6388
JA
461
462 /* Gobble up names. Each name is separated with whitespace. */
ccc6cda3 463 while (buffer[i])
726f6388 464 {
ccc6cda3
JA
465 for (; cr_whitespace (buffer[i]); i++)
466 ;
467 if (buffer[i] == '\0' || buffer[i] == '#')
468 break;
469
470 /* Isolate the current word. */
471 for (start = i; buffer[i] && cr_whitespace (buffer[i]) == 0; i++)
472 ;
473 if (i == start)
726f6388
JA
474 continue;
475 strncpy (name, buffer + start, i - start);
476 name[i - start] = '\0';
477 add_host_name (name);
478 }
479 }
480 fclose (file);
481}
482
483/* Return a NULL terminated list of hostnames which begin with TEXT.
484 Initialize the hostname list the first time if neccessary.
485 The array is malloc ()'ed, but not the individual strings. */
486static char **
487hostnames_matching (text)
488 char *text;
489{
ccc6cda3
JA
490 register int i, len, nmatch, rsize;
491 char **result;
726f6388 492
ccc6cda3
JA
493 if (hostname_list_initialized == 0)
494 initialize_hostname_list ();
726f6388 495
ccc6cda3
JA
496 if (hostname_list_initialized == 0)
497 return ((char **)NULL);
726f6388
JA
498
499 /* Special case. If TEXT consists of nothing, then the whole list is
500 what is desired. */
ccc6cda3 501 if (*text == '\0')
726f6388
JA
502 {
503 result = (char **)xmalloc ((1 + hostname_list_length) * sizeof (char *));
504 for (i = 0; i < hostname_list_length; i++)
505 result[i] = hostname_list[i];
506 result[i] = (char *)NULL;
507 return (result);
508 }
509
510 /* Scan until found, or failure. */
ccc6cda3
JA
511 len = strlen (text);
512 result = (char **)NULL;
513 for (i = nmatch = rsize = 0; i < hostname_list_length; i++)
726f6388 514 {
ccc6cda3
JA
515 if (STREQN (text, hostname_list[i], len) == 0)
516 continue;
726f6388 517
ccc6cda3
JA
518 /* OK, it matches. Add it to the list. */
519 if (nmatch >= rsize)
726f6388 520 {
ccc6cda3
JA
521 rsize = (rsize + 16) - (rsize % 16);
522 result = (char **)xrealloc (result, rsize * sizeof (char *));
726f6388
JA
523 }
524
ccc6cda3 525 result[nmatch++] = hostname_list[i];
726f6388 526 }
ccc6cda3
JA
527 if (nmatch)
528 result[nmatch] = (char *)NULL;
529 return (result);
726f6388
JA
530}
531
ccc6cda3 532/* The equivalent of the Korn shell C-o operate-and-get-next-history-line
726f6388 533 editing command. */
ccc6cda3 534static int saved_history_line_to_use = -1;
726f6388
JA
535
536static void
537set_saved_history ()
538{
ccc6cda3 539 if (saved_history_line_to_use >= 0)
726f6388 540 rl_get_previous_history (history_length - saved_history_line_to_use);
ccc6cda3 541 saved_history_line_to_use = -1;
726f6388 542 rl_startup_hook = old_rl_startup_hook;
ccc6cda3 543}
726f6388
JA
544
545static void
546operate_and_get_next (count, c)
547 int count, c;
548{
549 int where;
550
551 /* Accept the current line. */
ccc6cda3 552 rl_newline ();
726f6388
JA
553
554 /* Find the current line, and find the next line to use. */
555 where = where_history ();
556
557 if ((history_is_stifled () && (history_length >= max_input_history)) ||
558 (where >= history_length - 1))
559 saved_history_line_to_use = where;
560 else
561 saved_history_line_to_use = where + 1;
562
563 old_rl_startup_hook = rl_startup_hook;
564 rl_startup_hook = (Function *)set_saved_history;
565}
566
567#if defined (VI_MODE)
568/* This vi mode command causes VI_EDIT_COMMAND to be run on the current
569 command being entered (if no explicit argument is given), otherwise on
570 a command from the history file. */
571
572#define VI_EDIT_COMMAND "fc -e ${VISUAL:-${EDITOR:-vi}}"
573
574static void
575vi_edit_and_execute_command (count, c)
ccc6cda3 576 int count, c;
726f6388
JA
577{
578 char *command;
579
580 /* Accept the current line. */
ccc6cda3 581 rl_newline ();
726f6388
JA
582
583 if (rl_explicit_arg)
584 {
585 command = xmalloc (strlen (VI_EDIT_COMMAND) + 8);
586 sprintf (command, "%s %d", VI_EDIT_COMMAND, count);
587 }
588 else
589 {
590 /* Take the command we were just editing, add it to the history file,
591 then call fc to operate on it. We have to add a dummy command to
592 the end of the history because fc ignores the last command (assumes
593 it's supposed to deal with the command before the `fc'). */
594 using_history ();
595 add_history (rl_line_buffer);
596 add_history ("");
597 history_lines_this_session++;
598 using_history ();
599 command = savestring (VI_EDIT_COMMAND);
600 }
601 parse_and_execute (command, "v", -1);
ccc6cda3 602 rl_line_buffer[0] = '\0'; /* XXX */
726f6388
JA
603}
604#endif /* VI_MODE */
605
ccc6cda3
JA
606#if defined (ALIAS)
607static int
608posix_edit_macros (count, key)
609 int count, key;
610{
611 int c;
612 char alias_name[3], *alias_value, *macro;
613
614 c = rl_read_key ();
615 alias_name[0] = '_';
616 alias_name[1] = c;
617 alias_name[2] = '\0';
618
619 alias_value = get_alias_value (alias_name);
620 if (alias_value && *alias_value)
621 {
622 macro = savestring (alias_value);
623 rl_push_macro_input (macro);
624 }
625 return 0;
626}
627#endif
628
726f6388
JA
629/* **************************************************************** */
630/* */
631/* How To Do Shell Completion */
632/* */
633/* **************************************************************** */
634
635/* Do some completion on TEXT. The indices of TEXT in RL_LINE_BUFFER are
636 at START and END. Return an array of matches, or NULL if none. */
637static char **
638attempt_shell_completion (text, start, end)
639 char *text;
640 int start, end;
641{
642 int in_command_position, ti;
ccc6cda3 643 char **matches, *command_separator_chars;
726f6388 644
ccc6cda3
JA
645 command_separator_chars = ";|&{(`";
646 matches = (char **)NULL;
647 rl_ignore_some_completions_function = (Function *)filename_completion_ignore;
726f6388
JA
648
649 /* Determine if this could be a command word. It is if it appears at
650 the start of the line (ignoring preceding whitespace), or if it
651 appears after a character that separates commands. It cannot be a
652 command word if we aren't at the top-level prompt. */
653 ti = start - 1;
654
655 while ((ti > -1) && (whitespace (rl_line_buffer[ti])))
656 ti--;
657
658 in_command_position = 0;
659 if (ti < 0)
660 {
661 /* Only do command completion at the start of a line when we
662 are prompting at the top level. */
663 if (current_prompt_string == ps1_prompt)
664 in_command_position++;
665 }
666 else if (member (rl_line_buffer[ti], command_separator_chars))
667 {
668 register int this_char, prev_char;
669
670 in_command_position++;
671
672 /* Handle the two character tokens `>&', `<&', and `>|'.
673 We are not in a command position after one of these. */
674 this_char = rl_line_buffer[ti];
675 prev_char = rl_line_buffer[ti - 1];
676
677 if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
678 (this_char == '|' && prev_char == '>'))
679 in_command_position = 0;
ccc6cda3
JA
680 else if ((this_char == '{' && prev_char == '$') ||
681 (char_is_quoted (rl_line_buffer, ti)))
726f6388
JA
682 in_command_position = 0;
683 }
684 else
685 {
686 /* This still could be in command position. It is possible
687 that all of the previous words on the line are variable
688 assignments. */
689 }
690
ccc6cda3 691 /* Special handling for command substitution. */
726f6388
JA
692 if (*text == '`' && unclosed_pair (rl_line_buffer, start, "`"))
693 matches = completion_matches (text, command_subst_completion_function);
694
695 /* Variable name? */
696 if (!matches && *text == '$')
697 matches = completion_matches (text, variable_completion_function);
698
699 /* If the word starts in `~', and there is no slash in the word, then
700 try completing this word as a username. */
701 if (!matches && *text == '~' && !strchr (text, '/'))
702 matches = completion_matches (text, username_completion_function);
703
704 /* Another one. Why not? If the word starts in '@', then look through
705 the world of known hostnames for completion first. */
ccc6cda3 706 if (!matches && perform_hostname_completion && *text == '@')
726f6388
JA
707 matches = completion_matches (text, hostname_completion_function);
708
709 /* And last, (but not least) if this word is in a command position, then
710 complete over possible command names, including aliases, functions,
711 and command names. */
712 if (!matches && in_command_position)
713 {
714 matches = completion_matches (text, command_word_completion_function);
715 /* If we are attempting command completion and nothing matches, we
716 do not want readline to perform filename completion for us. We
717 still want to be able to complete partial pathnames, so set the
718 completion ignore function to something which will remove filenames
719 and leave directories in the match list. */
720 if (!matches)
721 rl_ignore_some_completions_function = (Function *)bash_ignore_filenames;
722 }
723
ccc6cda3
JA
724 /* This could be a globbing pattern, so try to expand it using pathname
725 expansion. */
726 if (!matches && glob_pattern_p (text))
727 matches = completion_matches (text, glob_complete_word);
728
726f6388
JA
729 return (matches);
730}
731
732/* This is the function to call when the word to complete is in a position
733 where a command word can be found. It grovels $PATH, looking for commands
734 that match. It also scans aliases, function names, and the shell_builtin
735 table. */
736static char *
737command_word_completion_function (hint_text, state)
738 char *hint_text;
739 int state;
740{
741 static char *hint = (char *)NULL;
742 static char *path = (char *)NULL;
743 static char *val = (char *)NULL;
744 static char *filename_hint = (char *)NULL;
745 static int path_index, hint_len, istate;
746 static int mapping_over, local_index;
747 static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
748#if defined (ALIAS)
ccc6cda3 749 static alias_t **alias_list = (alias_t **)NULL;
726f6388
JA
750#endif /* ALIAS */
751
752 /* We have to map over the possibilities for command words. If we have
753 no state, then make one just for that purpose. */
726f6388
JA
754 if (!state)
755 {
756 if (hint)
757 free (hint);
758
759 mapping_over = 0;
760 val = (char *)NULL;
761
762 /* If this is an absolute program name, do not check it against
763 aliases, reserved words, functions or builtins. We must check
764 whether or not it is unique, and, if so, whether that filename
765 is executable. */
766 if (absolute_program (hint_text))
767 {
768 /* Perform tilde expansion on what's passed, so we don't end up
769 passing filenames with tildes directly to stat(). */
770 if (*hint_text == '~')
ccc6cda3 771 hint = bash_tilde_expand (hint_text);
726f6388
JA
772 else
773 hint = savestring (hint_text);
774 hint_len = strlen (hint);
775
776 if (filename_hint)
777 free (filename_hint);
778 filename_hint = savestring (hint);
779
780 mapping_over = 4;
781 istate = 0;
782 goto inner;
783 }
784
785 hint = savestring (hint_text);
786 hint_len = strlen (hint);
787
788 path = get_string_value ("PATH");
789 path_index = 0;
790
791 /* Initialize the variables for each type of command word. */
792 local_index = 0;
793
794 if (varlist)
795 free (varlist);
796
797 varlist = all_visible_functions ();
798
799#if defined (ALIAS)
800 if (alias_list)
801 free (alias_list);
802
803 alias_list = all_aliases ();
804#endif /* ALIAS */
805 }
806
807 /* mapping_over says what we are currently hacking. Note that every case
808 in this list must fall through when there are no more possibilities. */
809
810 switch (mapping_over)
811 {
812 case 0: /* Aliases come first. */
813#if defined (ALIAS)
814 while (alias_list && alias_list[local_index])
815 {
816 register char *alias;
817
818 alias = alias_list[local_index++]->name;
819
820 if (STREQN (alias, hint, hint_len))
821 return (savestring (alias));
822 }
823#endif /* ALIAS */
824 local_index = 0;
825 mapping_over++;
826
827 case 1: /* Then shell reserved words. */
828 {
829 while (word_token_alist[local_index].word)
830 {
831 register char *reserved_word;
832
833 reserved_word = word_token_alist[local_index++].word;
834
835 if (STREQN (reserved_word, hint, hint_len))
836 return (savestring (reserved_word));
837 }
838 local_index = 0;
839 mapping_over++;
840 }
841
842 case 2: /* Then function names. */
843 while (varlist && varlist[local_index])
844 {
845 register char *varname;
846
847 varname = varlist[local_index++]->name;
848
849 if (STREQN (varname, hint, hint_len))
850 return (savestring (varname));
851 }
852 local_index = 0;
853 mapping_over++;
854
855 case 3: /* Then shell builtins. */
856 for (; local_index < num_shell_builtins; local_index++)
857 {
858 /* Ignore it if it doesn't have a function pointer or if it
859 is not currently enabled. */
860 if (!shell_builtins[local_index].function ||
861 (shell_builtins[local_index].flags & BUILTIN_ENABLED) == 0)
862 continue;
863
864 if (STREQN (shell_builtins[local_index].name, hint, hint_len))
865 {
866 int i = local_index++;
867
868 return (savestring (shell_builtins[i].name));
869 }
870 }
871 local_index = 0;
872 mapping_over++;
873 }
874
ccc6cda3 875 /* Repeatedly call filename_completion_function while we have
726f6388
JA
876 members of PATH left. Question: should we stat each file?
877 Answer: we call executable_file () on each file. */
878 outer:
879
880 istate = (val != (char *)NULL);
881
882 if (!istate)
883 {
884 char *current_path;
885
886 /* Get the next directory from the path. If there is none, then we
887 are all done. */
888 if (!path || !path[path_index] ||
889 (current_path = extract_colon_unit (path, &path_index)) == 0)
890 return ((char *)NULL);
891
892 if (*current_path == 0)
893 {
894 free (current_path);
895 current_path = savestring (".");
896 }
897
898 if (*current_path == '~')
899 {
900 char *t;
901
ccc6cda3 902 t = bash_tilde_expand (current_path);
726f6388
JA
903 free (current_path);
904 current_path = t;
905 }
906
907 if (filename_hint)
908 free (filename_hint);
909
910 filename_hint = xmalloc (2 + strlen (current_path) + hint_len);
911 sprintf (filename_hint, "%s/%s", current_path, hint);
912
913 free (current_path);
914 }
915
916 inner:
917 val = filename_completion_function (filename_hint, istate);
918 istate = 1;
919
ccc6cda3 920 if (val == 0)
726f6388
JA
921 {
922 /* If the hint text is an absolute program, then don't bother
923 searching through PATH. */
924 if (absolute_program (hint))
925 return ((char *)NULL);
926
927 goto outer;
928 }
929 else
930 {
931 int match;
932 char *temp;
933
934 if (absolute_program (hint))
935 {
936 match = strncmp (val, hint, hint_len) == 0;
937 /* If we performed tilde expansion, restore the original
938 filename. */
939 if (*hint_text == '~')
940 {
941 int l, tl, vl;
942 vl = strlen (val);
943 tl = strlen (hint_text);
944 l = vl - hint_len; /* # of chars added */
945 temp = xmalloc (l + 2 + tl);
946 strcpy (temp, hint_text);
947 strcpy (temp + tl, val + vl - l);
948 }
949 else
950 temp = savestring (val);
951 }
952 else
953 {
954 temp = strrchr (val, '/');
955
956 if (temp)
957 {
958 temp++;
959 match = strncmp (temp, hint, hint_len) == 0;
960 if (match)
961 temp = savestring (temp);
962 }
963 else
964 match = 0;
965 }
966
ccc6cda3
JA
967 /* If we have found a match, and it is an executable file or a
968 directory name, return it. */
969 if (match && (executable_file (val) || is_directory (val)))
726f6388
JA
970 {
971 free (val);
972 val = ""; /* So it won't be NULL. */
973 return (temp);
974 }
975 else
976 {
977 free (val);
978 goto inner;
979 }
980 }
981}
982
983static char *
984command_subst_completion_function (text, state)
726f6388 985 char *text;
ccc6cda3 986 int state;
726f6388
JA
987{
988 static char **matches = (char **)NULL;
989 static char *orig_start, *filename_text = (char *)NULL;
990 static int cmd_index, start_len;
ccc6cda3 991 char *value;
726f6388
JA
992
993 if (state == 0)
994 {
995 if (filename_text)
996 free (filename_text);
997 orig_start = text;
998 if (*text == '`')
999 text++;
1000 else if (*text == '$' && text[1] == '(')
1001 text += 2;
1002 start_len = text - orig_start;
1003 filename_text = savestring (text);
1004 if (matches)
1005 free (matches);
1006 matches = completion_matches (filename_text, command_word_completion_function);
1007 cmd_index = 0;
1008 }
1009
1010 if (!matches || !matches[cmd_index])
1011 {
1012 rl_filename_quoting_desired = 0; /* disable quoting */
1013 return ((char *)NULL);
1014 }
1015 else
1016 {
726f6388
JA
1017 value = xmalloc (1 + start_len + strlen (matches[cmd_index]));
1018
1019 if (start_len == 1)
1020 value[0] = *orig_start;
1021 else
1022 strncpy (value, orig_start, start_len);
1023
1024 strcpy (value + start_len, matches[cmd_index]);
1025
1026 cmd_index++;
1027 return (value);
1028 }
1029}
1030
1031/* Okay, now we write the entry_function for variable completion. */
1032static char *
1033variable_completion_function (text, state)
1034 int state;
1035 char *text;
1036{
1037 register SHELL_VAR *var = (SHELL_VAR *)NULL;
1038 static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
1039 static int varlist_index;
1040 static char *varname = (char *)NULL;
1041 static int namelen;
1042 static int first_char, first_char_loc;
1043
1044 if (!state)
1045 {
1046 if (varname)
1047 free (varname);
1048
1049 first_char_loc = 0;
1050 first_char = text[0];
1051
1052 if (first_char == '$')
1053 first_char_loc++;
1054
ccc6cda3
JA
1055 if (text[first_char_loc] == '{')
1056 first_char_loc++;
1057
726f6388
JA
1058 varname = savestring (text + first_char_loc);
1059
1060 namelen = strlen (varname);
1061 if (varlist)
1062 free (varlist);
1063 varlist = all_visible_variables ();
1064 varlist_index = 0;
1065 }
1066
1067 while (varlist && varlist[varlist_index])
1068 {
1069 var = varlist[varlist_index];
1070
1071 /* Compare. You can't do better than Zayre. No text is also
1072 a match. */
1073 if (!*varname || (strncmp (varname, var->name, namelen) == 0))
1074 break;
1075 varlist_index++;
1076 }
1077
1078 if (!varlist || !varlist[varlist_index])
1079 {
1080 return ((char *)NULL);
1081 }
1082 else
1083 {
ccc6cda3 1084 char *value = xmalloc (4 + strlen (var->name));
726f6388
JA
1085
1086 if (first_char_loc)
ccc6cda3
JA
1087 {
1088 value[0] = first_char;
1089 if (first_char_loc == 2)
1090 value[1] = '{';
1091 }
726f6388
JA
1092
1093 strcpy (&value[first_char_loc], var->name);
ccc6cda3
JA
1094 if (first_char_loc == 2)
1095 strcat (value, "}");
726f6388
JA
1096
1097 varlist_index++;
1098 return (value);
1099 }
1100}
1101
1102/* How about a completion function for hostnames? */
1103static char *
1104hostname_completion_function (text, state)
1105 int state;
1106 char *text;
1107{
1108 static char **list = (char **)NULL;
1109 static int list_index = 0;
1110 static int first_char, first_char_loc;
1111
1112 /* If we don't have any state, make some. */
ccc6cda3 1113 if (state == 0)
726f6388 1114 {
ccc6cda3 1115 FREE (list);
726f6388
JA
1116
1117 list = (char **)NULL;
1118
1119 first_char_loc = 0;
1120 first_char = *text;
1121
1122 if (first_char == '@')
1123 first_char_loc++;
1124
1125 list = hostnames_matching (&text[first_char_loc]);
1126 list_index = 0;
1127 }
1128
1129 if (list && list[list_index])
1130 {
ccc6cda3 1131 char *t;
726f6388 1132
ccc6cda3 1133 t = xmalloc (2 + strlen (list[list_index]));
726f6388
JA
1134 *t = first_char;
1135 strcpy (t + first_char_loc, list[list_index]);
1136 list_index++;
1137 return (t);
1138 }
ccc6cda3
JA
1139
1140 return ((char *)NULL);
726f6388
JA
1141}
1142
1143/* History and alias expand the line. */
1144static char *
1145history_expand_line_internal (line)
1146 char *line;
1147{
1148 char *new_line;
1149
1150 new_line = pre_process_line (line, 0, 0);
1151 return new_line;
1152}
1153
1154#if defined (ALIAS)
1155/* Perform alias expansion on LINE and return the new line. */
1156static char *
1157alias_expand_line_internal (line)
1158 char *line;
1159{
1160 char *alias_line;
1161
1162 alias_line = alias_expand (line);
1163 return alias_line;
1164}
1165#endif
1166
1167/* There was an error in expansion. Let the preprocessor print
1168 the error here. */
1169static void
1170cleanup_expansion_error ()
1171{
1172 char *to_free;
1173
1174 fprintf (rl_outstream, "\r\n");
1175 to_free = pre_process_line (rl_line_buffer, 1, 0);
1176 free (to_free);
1177 putc ('\r', rl_outstream);
1178 rl_forced_update_display ();
1179}
1180
1181/* If NEW_LINE differs from what is in the readline line buffer, add an
1182 undo record to get from the readline line buffer contents to the new
1183 line and make NEW_LINE the current readline line. */
1184static void
1185maybe_make_readline_line (new_line)
1186 char *new_line;
1187{
1188 if (strcmp (new_line, rl_line_buffer) != 0)
1189 {
1190 rl_point = rl_end;
1191
1192 rl_add_undo (UNDO_BEGIN, 0, 0, 0);
1193 rl_delete_text (0, rl_point);
1194 rl_point = rl_end = 0;
1195 rl_insert_text (new_line);
1196 rl_add_undo (UNDO_END, 0, 0, 0);
1197 }
1198}
1199
1200/* Make NEW_LINE be the current readline line. This frees NEW_LINE. */
1201static void
1202set_up_new_line (new_line)
1203 char *new_line;
1204{
1205 int old_point = rl_point;
1206 int at_end = rl_point == rl_end;
1207
1208 /* If the line was history and alias expanded, then make that
1209 be one thing to undo. */
1210 maybe_make_readline_line (new_line);
1211 free (new_line);
1212
1213 /* Place rl_point where we think it should go. */
1214 if (at_end)
1215 rl_point = rl_end;
1216 else if (old_point < rl_end)
1217 {
1218 rl_point = old_point;
1219 if (!whitespace (rl_line_buffer[rl_point]))
1220 rl_forward_word (1);
1221 }
1222}
1223
1224/* History expand the line. */
1225static void
1226history_expand_line (ignore)
1227 int ignore;
1228{
1229 char *new_line;
1230
1231 new_line = history_expand_line_internal (rl_line_buffer);
1232
1233 if (new_line)
1234 set_up_new_line (new_line);
1235 else
1236 cleanup_expansion_error ();
1237}
ccc6cda3 1238
726f6388
JA
1239/* History and alias expand the line. */
1240static void
1241history_and_alias_expand_line (ignore)
1242 int ignore;
1243{
1244 char *new_line;
1245
1246 new_line = pre_process_line (rl_line_buffer, 0, 0);
1247
1248#if defined (ALIAS)
1249 if (new_line)
1250 {
1251 char *alias_line;
1252
1253 alias_line = alias_expand (new_line);
1254 free (new_line);
1255 new_line = alias_line;
1256 }
1257#endif /* ALIAS */
1258
1259 if (new_line)
1260 set_up_new_line (new_line);
1261 else
1262 cleanup_expansion_error ();
1263}
1264
1265/* History and alias expand the line, then perform the shell word
1266 expansions by calling expand_string. */
1267static void
1268shell_expand_line (ignore)
1269 int ignore;
1270{
1271 char *new_line;
ccc6cda3 1272 WORD_LIST *expanded_string;
726f6388
JA
1273
1274 new_line = pre_process_line (rl_line_buffer, 0, 0);
1275
1276#if defined (ALIAS)
1277 if (new_line)
1278 {
1279 char *alias_line;
1280
1281 alias_line = alias_expand (new_line);
1282 free (new_line);
1283 new_line = alias_line;
1284 }
1285#endif /* ALIAS */
1286
1287 if (new_line)
1288 {
1289 int old_point = rl_point;
1290 int at_end = rl_point == rl_end;
1291
1292 /* If the line was history and alias expanded, then make that
1293 be one thing to undo. */
1294 maybe_make_readline_line (new_line);
1295 free (new_line);
1296
1297 /* If there is variable expansion to perform, do that as a separate
1298 operation to be undone. */
ccc6cda3
JA
1299 expanded_string = expand_string (rl_line_buffer, 0);
1300 if (expanded_string == 0)
1301 {
1302 new_line = xmalloc (1);
1303 new_line[0] = '\0';
1304 }
1305 else
1306 {
1307 new_line = string_list (expanded_string);
1308 dispose_words (expanded_string);
1309 }
726f6388 1310
ccc6cda3
JA
1311 maybe_make_readline_line (new_line);
1312 free (new_line);
726f6388 1313
ccc6cda3
JA
1314 /* Place rl_point where we think it should go. */
1315 if (at_end)
1316 rl_point = rl_end;
1317 else if (old_point < rl_end)
1318 {
1319 rl_point = old_point;
1320 if (!whitespace (rl_line_buffer[rl_point]))
1321 rl_forward_word (1);
1322 }
726f6388
JA
1323 }
1324 else
1325 cleanup_expansion_error ();
1326}
1327
ccc6cda3
JA
1328/* If FIGNORE is set, then don't match files with the given suffixes when
1329 completing filenames. If only one of the possibilities has an acceptable
726f6388
JA
1330 suffix, delete the others, else just return and let the completer
1331 signal an error. It is called by the completer when real
1332 completions are done on filenames by the completer's internal
1333 function, not for completion lists (M-?) and not on "other"
ccc6cda3 1334 completion types, such as hostnames or commands. */
726f6388 1335
ccc6cda3 1336static struct ignorevar fignore =
726f6388 1337{
ccc6cda3
JA
1338 "FIGNORE",
1339 (struct ign *)0,
1340 0,
1341 (char *)0,
1342 (Function *) 0,
1343};
726f6388 1344
726f6388 1345static void
ccc6cda3 1346_ignore_completion_names (names, name_func)
726f6388
JA
1347 char **names;
1348 Function *name_func;
1349{
1350 char **newnames;
1351 int idx, nidx;
1352
1353 /* If there is only one completion, see if it is acceptable. If it is
1354 not, free it up. In any case, short-circuit and return. This is a
1355 special case because names[0] is not the prefix of the list of names
1356 if there is only one completion; it is the completion itself. */
1357 if (names[1] == (char *)0)
1358 {
1359 if ((*name_func) (names[0]) == 0)
1360 {
1361 free (names[0]);
1362 names[0] = (char *)NULL;
1363 }
1364 return;
1365 }
1366
1367 /* Allocate space for array to hold list of pointers to matching
1368 filenames. The pointers are copied back to NAMES when done. */
1369 for (nidx = 1; names[nidx]; nidx++)
1370 ;
1371 newnames = (char **)xmalloc ((nidx + 1) * (sizeof (char *)));
1372
1373 newnames[0] = names[0];
1374 for (idx = nidx = 1; names[idx]; idx++)
1375 {
1376 if ((*name_func) (names[idx]))
1377 newnames[nidx++] = names[idx];
1378 else
ccc6cda3 1379 free (names[idx]);
726f6388
JA
1380 }
1381
1382 newnames[nidx] = (char *)NULL;
1383
1384 /* If none are acceptable then let the completer handle it. */
1385 if (nidx == 1)
1386 {
1387 free (names[0]);
1388 names[0] = (char *)NULL;
1389 free (newnames);
1390 return;
1391 }
1392
1393 /* If only one is acceptable, copy it to names[0] and return. */
1394 if (nidx == 2)
1395 {
1396 free (names[0]);
1397 names[0] = newnames[1];
1398 names[1] = (char *)NULL;
1399 free (newnames);
1400 return;
1401 }
ccc6cda3 1402
726f6388
JA
1403 /* Copy the acceptable names back to NAMES, set the new array end,
1404 and return. */
1405 for (nidx = 1; newnames[nidx]; nidx++)
1406 names[nidx] = newnames[nidx];
1407 names[nidx] = (char *)NULL;
ccc6cda3
JA
1408 free (newnames);
1409}
1410
1411static int
1412name_is_acceptable (name)
1413 char *name;
1414{
1415 struct ign *p;
1416 int nlen;
1417
1418 for (nlen = strlen (name), p = fignore.ignores; p->val; p++)
1419 {
1420 if (nlen > p->len && p->len > 0 && STREQ (p->val, &name[nlen - p->len]))
1421 return (0);
1422 }
1423
1424 return (1);
726f6388
JA
1425}
1426
1427static void
1428filename_completion_ignore (names)
1429 char **names;
1430{
ccc6cda3 1431 setup_ignore_patterns (&fignore);
726f6388 1432
ccc6cda3 1433 if (fignore.num_ignores == 0)
726f6388
JA
1434 return;
1435
ccc6cda3 1436 _ignore_completion_names (names, name_is_acceptable);
726f6388
JA
1437}
1438
1439/* Return 1 if NAME is a directory. */
1440static int
1441test_for_directory (name)
1442 char *name;
1443{
1444 struct stat finfo;
1445 char *fn;
1446
ccc6cda3 1447 fn = bash_tilde_expand (name);
726f6388
JA
1448 if (stat (fn, &finfo) != 0)
1449 {
1450 free (fn);
1451 return 0;
1452 }
1453 free (fn);
1454 return (S_ISDIR (finfo.st_mode));
1455}
1456
1457/* Remove files from NAMES, leaving directories. */
1458static void
1459bash_ignore_filenames (names)
1460 char **names;
1461{
ccc6cda3 1462 _ignore_completion_names (names, test_for_directory);
726f6388
JA
1463}
1464
1465/* Handle symbolic link references and other directory name
1466 expansions while hacking completion. */
1467static int
1468bash_directory_completion_hook (dirname)
1469 char **dirname;
1470{
1471 char *local_dirname, *t;
1472 int return_value = 0;
1473 WORD_LIST *wl;
1474
1475 local_dirname = *dirname;
1476 if (strchr (local_dirname, '$') || strchr (local_dirname, '`'))
1477 {
1478 wl = expand_string (local_dirname, 0);
1479 if (wl)
1480 {
1481 *dirname = string_list (wl);
1482 /* Tell the completer to replace the directory name only if we
1483 actually expanded something. */
1484 return_value = STREQ (local_dirname, *dirname) == 0;
1485 free (local_dirname);
1486 dispose_words (wl);
1487 local_dirname = *dirname;
1488 }
1489 else
1490 {
1491 free (local_dirname);
ccc6cda3
JA
1492 *dirname = xmalloc (1);
1493 **dirname = '\0';
726f6388
JA
1494 return 1;
1495 }
1496 }
1497
1498 if (!no_symbolic_links && (local_dirname[0] != '.' || local_dirname[1]))
1499 {
1500 char *temp1, *temp2;
1501 int len1, len2;
1502
1503 t = get_working_directory ("symlink-hook");
1504 temp1 = make_absolute (local_dirname, t);
1505 free (t);
1506 temp2 = canonicalize_pathname (temp1);
ccc6cda3
JA
1507 /* If we can't canonicalize, bail. */
1508 if (temp2 == 0)
1509 {
1510 free (temp1);
1511 return 1;
1512 }
726f6388
JA
1513 len1 = strlen (temp1);
1514 if (temp1[len1 - 1] == '/')
1515 {
1516 len2 = strlen (temp2);
1517 temp2 = xrealloc (temp2, len2 + 2);
1518 temp2[len2] = '/';
1519 temp2[len2 + 1] = '\0';
1520 }
1521 free (local_dirname);
1522 *dirname = temp2;
1523 free (temp1);
1524 }
1525 return (return_value);
1526}
1527
726f6388 1528static char **history_completion_array = (char **)NULL;
ccc6cda3
JA
1529static int harry_size;
1530static int harry_len;
726f6388
JA
1531
1532static void
1533build_history_completion_array ()
1534{
ccc6cda3
JA
1535 register int i, j;
1536 HIST_ENTRY **hlist;
1537 char **tokens;
726f6388
JA
1538
1539 /* First, clear out the current dynamic history completion list. */
1540 if (harry_size)
1541 {
1542 for (i = 0; history_completion_array[i]; i++)
1543 free (history_completion_array[i]);
1544
1545 free (history_completion_array);
1546
1547 history_completion_array = (char **)NULL;
1548 harry_size = 0;
1549 harry_len = 0;
1550 }
1551
1552 /* Next, grovel each line of history, making each shell-sized token
1553 a separate entry in the history_completion_array. */
ccc6cda3 1554 hlist = history_list ();
726f6388 1555
ccc6cda3
JA
1556 if (hlist)
1557 {
1558 for (i = 0; hlist[i]; i++)
1559 {
1560 /* Separate each token, and place into an array. */
1561 tokens = history_tokenize (hlist[i]->line);
726f6388 1562
ccc6cda3
JA
1563 for (j = 0; tokens && tokens[j]; j++)
1564 {
1565 if (harry_len + 2 > harry_size)
1566 {
1567 harry_size += 10;
726f6388 1568 history_completion_array = (char **) xrealloc
ccc6cda3
JA
1569 (history_completion_array, harry_size * sizeof (char *));
1570 }
726f6388 1571
ccc6cda3
JA
1572 history_completion_array[harry_len++] = tokens[j];
1573 history_completion_array[harry_len] = (char *)NULL;
1574 }
1575 free (tokens);
1576 }
726f6388 1577
ccc6cda3
JA
1578 /* Sort the complete list of tokens. */
1579 qsort (history_completion_array, harry_len, sizeof (char *), (Function *)qsort_string_compare);
1580 }
726f6388
JA
1581}
1582
1583static char *
1584history_completion_generator (hint_text, state)
1585 char *hint_text;
1586 int state;
1587{
ccc6cda3
JA
1588 static int local_index, len;
1589 static char *text;
726f6388
JA
1590
1591 /* If this is the first call to the generator, then initialize the
1592 list of strings to complete over. */
ccc6cda3 1593 if (state == 0)
726f6388
JA
1594 {
1595 local_index = 0;
1596 build_history_completion_array ();
1597 text = hint_text;
1598 len = strlen (text);
1599 }
1600
1601 while (history_completion_array && history_completion_array[local_index])
1602 {
1603 if (strncmp (text, history_completion_array[local_index++], len) == 0)
1604 return (savestring (history_completion_array[local_index - 1]));
1605 }
1606 return ((char *)NULL);
1607}
1608
1609static void
1610dynamic_complete_history (count, key)
1611 int count, key;
1612{
1613 Function *orig_func;
1614 CPPFunction *orig_attempt_func;
1615
1616 orig_func = rl_completion_entry_function;
1617 orig_attempt_func = rl_attempted_completion_function;
1618 rl_completion_entry_function = (Function *)history_completion_generator;
1619 rl_attempted_completion_function = (CPPFunction *)NULL;
1620
1621 if (rl_last_func == (Function *)dynamic_complete_history)
1622 rl_complete_internal ('?');
1623 else
1624 rl_complete_internal (TAB);
1625
1626 rl_completion_entry_function = orig_func;
1627 rl_attempted_completion_function = orig_attempt_func;
1628}
1629
726f6388
JA
1630#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
1631static void
1632bash_complete_username (ignore, ignore2)
1633 int ignore, ignore2;
1634{
1635 bash_complete_username_internal (TAB);
1636}
1637
1638static void
1639bash_possible_username_completions (ignore, ignore2)
1640 int ignore, ignore2;
1641{
1642 bash_complete_username_internal ('?');
1643}
1644
1645static void
1646bash_complete_username_internal (what_to_do)
1647 int what_to_do;
1648{
1649 bash_specific_completion
1650 (what_to_do, (Function *)username_completion_function);
1651}
1652
1653static void
1654bash_complete_filename (ignore, ignore2)
1655 int ignore, ignore2;
1656{
1657 bash_complete_filename_internal (TAB);
1658}
1659
1660static void
1661bash_possible_filename_completions (ignore, ignore2)
1662 int ignore, ignore2;
1663{
1664 bash_complete_filename_internal ('?');
1665}
1666
1667static void
1668bash_complete_filename_internal (what_to_do)
1669 int what_to_do;
1670{
1671 Function *orig_func, *orig_dir_func;
1672 CPPFunction *orig_attempt_func;
1673 char *orig_rl_completer_word_break_characters;
1674
1675 orig_func = rl_completion_entry_function;
1676 orig_attempt_func = rl_attempted_completion_function;
1677 orig_dir_func = rl_directory_completion_hook;
1678 orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
1679 rl_completion_entry_function = (Function *)filename_completion_function;
1680 rl_attempted_completion_function = (CPPFunction *)NULL;
1681 rl_directory_completion_hook = (Function *)NULL;
1682 rl_completer_word_break_characters = " \t\n\"\'";
1683
1684 rl_complete_internal (what_to_do);
1685
1686 rl_completion_entry_function = orig_func;
1687 rl_attempted_completion_function = orig_attempt_func;
1688 rl_directory_completion_hook = orig_dir_func;
1689 rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
1690}
1691
1692static void
1693bash_complete_hostname (ignore, ignore2)
1694 int ignore, ignore2;
1695{
1696 bash_complete_hostname_internal (TAB);
1697}
1698
1699static void
1700bash_possible_hostname_completions (ignore, ignore2)
1701 int ignore, ignore2;
1702{
1703 bash_complete_hostname_internal ('?');
1704}
1705
1706static void
1707bash_complete_variable (ignore, ignore2)
1708 int ignore, ignore2;
1709{
1710 bash_complete_variable_internal (TAB);
1711}
1712
1713static void
1714bash_possible_variable_completions (ignore, ignore2)
1715 int ignore, ignore2;
1716{
1717 bash_complete_variable_internal ('?');
1718}
1719
1720static void
1721bash_complete_command (ignore, ignore2)
1722 int ignore, ignore2;
1723{
1724 bash_complete_command_internal (TAB);
1725}
1726
1727static void
1728bash_possible_command_completions (ignore, ignore2)
1729 int ignore, ignore2;
1730{
1731 bash_complete_command_internal ('?');
1732}
1733
1734static void
1735bash_complete_hostname_internal (what_to_do)
1736 int what_to_do;
1737{
1738 bash_specific_completion
1739 (what_to_do, (Function *)hostname_completion_function);
1740}
1741
1742static void
1743bash_complete_variable_internal (what_to_do)
1744 int what_to_do;
1745{
1746 bash_specific_completion
1747 (what_to_do, (Function *)variable_completion_function);
1748}
1749
1750static void
1751bash_complete_command_internal (what_to_do)
1752 int what_to_do;
1753{
1754 bash_specific_completion
1755 (what_to_do, (Function *)command_word_completion_function);
1756}
1757
ccc6cda3
JA
1758static char *
1759glob_complete_word (text, state)
1760 char *text;
1761 int state;
1762{
1763 static char **matches = (char **)NULL;
1764 static int ind;
1765 char *ret;
1766
1767 if (state == 0)
1768 {
1769 if (matches)
1770 free (matches);
1771 matches = shell_glob_filename (text);
1772 if (GLOB_FAILED (matches))
1773 matches = (char **)NULL;
1774 ind = 0;
1775 }
1776
1777 ret = matches ? matches[ind] : (char *)NULL;
1778 ind++;
1779 return ret;
1780}
1781
1782static void
1783bash_glob_completion_internal (what_to_do)
1784 int what_to_do;
1785{
1786 bash_specific_completion (what_to_do, (Function *)glob_complete_word);
1787}
1788
1789static void
1790bash_glob_expand_word (count, key)
1791 int count, key;
1792{
1793 bash_glob_completion_internal ('*');
1794}
1795
1796static void
1797bash_glob_list_expansions (count, key)
1798 int count, key;
1799{
1800 bash_glob_completion_internal ('?');
1801}
1802
726f6388
JA
1803static void
1804bash_specific_completion (what_to_do, generator)
1805 int what_to_do;
1806 Function *generator;
1807{
1808 Function *orig_func;
1809 CPPFunction *orig_attempt_func;
1810
1811 orig_func = rl_completion_entry_function;
1812 orig_attempt_func = rl_attempted_completion_function;
1813 rl_completion_entry_function = generator;
1814 rl_attempted_completion_function = (CPPFunction *)NULL;
1815
1816 rl_complete_internal (what_to_do);
1817
1818 rl_completion_entry_function = orig_func;
1819 rl_attempted_completion_function = orig_attempt_func;
1820}
1821
1822#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
ccc6cda3
JA
1823
1824/* Filename quoting for completion. */
1825/* A function to strip quotes that are not protected by backquotes. It
1826 allows single quotes to appear within double quotes, and vice versa.
1827 It should be smarter. */
1828static char *
1829bash_dequote_filename (text, quote_char)
1830 char *text;
1831{
1832 char *ret, *p, *r;
1833 int l, quoted;
1834
1835 l = strlen (text);
1836 ret = xmalloc (l + 1);
1837 for (quoted = quote_char, p = text, r = ret; p && *p; p++)
1838 {
1839 /* Allow backslash-quoted characters to pass through unscathed. */
1840 if (*p == '\\')
1841 {
1842 *r++ = *++p;
1843 if (*p == '\0')
1844 break;
1845 continue;
1846 }
1847 /* Close quote. */
1848 if (quoted && *p == quoted)
1849 {
1850 quoted = 0;
1851 continue;
1852 }
1853 /* Open quote. */
1854 if (quoted == 0 && (*p == '\'' || *p == '"'))
1855 {
1856 quoted = *p;
1857 continue;
1858 }
1859 *r++ = *p;
1860 }
1861 *r = '\0';
1862 return ret;
1863}
1864
1865/* Quote a filename using double quotes. */
1866static char *
1867bash_quote_filename (s, rtype, qcp)
1868 char *s;
1869 int rtype;
1870 char *qcp;
1871{
1872 char *rtext, *mtext, *ret;
1873 int rlen, cs;
1874
1875 rtext = (char *)NULL;
1876
1877 /* If RTYPE == MULT_MATCH, it means that there is
1878 more than one match. In this case, we do not add
1879 the closing quote or attempt to perform tilde
1880 expansion. If RTYPE == SINGLE_MATCH, we try
1881 to perform tilde expansion, because single and double
1882 quotes inhibit tilde expansion by the shell. */
1883
1884 mtext = s;
1885 if (mtext[0] == '~' && rtype == SINGLE_MATCH)
1886 mtext = bash_tilde_expand (s);
1887
1888 cs = completion_quoting_style;
1889 /* Might need to modify the default completion style based on *qcp,
1890 since it's set to any user-provided opening quote. */
1891 if (*qcp == '"')
1892 cs = COMPLETE_DQUOTE;
1893 else if (*qcp == '\'')
1894 cs = COMPLETE_SQUOTE;
1895#if defined (BANG_HISTORY)
1896 else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
1897 history_expansion_inhibited == 0 && strchr (mtext, '!'))
1898 cs = COMPLETE_BSQUOTE;
1899#endif
1900
1901 switch (cs)
1902 {
1903 case COMPLETE_DQUOTE:
1904 rtext = double_quote (mtext);
1905 break;
1906 case COMPLETE_SQUOTE:
1907 rtext = single_quote (mtext);
1908 break;
1909 case COMPLETE_BSQUOTE:
1910 rtext = backslash_quote (mtext);
1911 break;
1912 }
1913
1914 if (mtext != s)
1915 free (mtext);
1916
1917 /* Leave the opening quote intact. The readline completion code takes
1918 care of avoiding doubled opening quotes. */
1919 rlen = strlen (rtext);
1920 ret = xmalloc (rlen + 1);
1921 strcpy (ret, rtext);
1922
1923 /* If there are multiple matches, cut off the closing quote. */
1924 if (rtype == MULT_MATCH && cs != COMPLETE_BSQUOTE)
1925 ret[rlen - 1] = '\0';
1926 free (rtext);
1927 return ret;
1928}
1929
1930#endif /* READLINE */