aboutsummaryrefslogtreecommitdiffstats
path: root/bashline.c
diff options
context:
space:
mode:
authorJari Aalto <jari.aalto@cante.net>1997-06-05 14:59:13 +0000
committerJari Aalto <jari.aalto@cante.net>2009-09-12 16:46:50 +0000
commitd166f048818e10cf3799aa24a174fb22835f1acc (patch)
tree1ca27f9243900f8b236d0cde6a3862002aea9e19 /bashline.c
parentccc6cda312fea9f0468ee65b8f368e9653e1380b (diff)
downloadandroid_external_bash-d166f048818e10cf3799aa24a174fb22835f1acc.tar.gz
android_external_bash-d166f048818e10cf3799aa24a174fb22835f1acc.tar.bz2
android_external_bash-d166f048818e10cf3799aa24a174fb22835f1acc.zip
Imported from ../bash-2.01.tar.gz.
Diffstat (limited to 'bashline.c')
-rw-r--r--bashline.c128
1 files changed, 108 insertions, 20 deletions
diff --git a/bashline.c b/bashline.c
index 7d2e5d7..fbd196a 100644
--- a/bashline.c
+++ b/bashline.c
@@ -56,6 +56,11 @@ extern void bash_brace_completion ();
static void shell_expand_line ();
static void display_shell_version (), operate_and_get_next ();
static void history_expand_line (), bash_ignore_filenames ();
+#ifdef ALIAS
+static void alias_expand_line ();
+#endif
+static void history_and_alias_expand_line ();
+static void cleanup_expansion_error (), set_up_new_line ();
/* Helper functions for Readline. */
static int bash_directory_completion_hook ();
@@ -194,6 +199,11 @@ initialize_readline ()
rl_add_defun ("history-expand-line", (Function *)history_expand_line, -1);
rl_bind_key_in_map ('^', (Function *)history_expand_line, emacs_meta_keymap);
+#ifdef ALIAS
+ rl_add_defun ("alias-expand-line", (Function *)alias_expand_line, -1);
+ rl_add_defun ("history-and-alias-expand-line", (Function *)history_and_alias_expand_line, -1);
+#endif
+
/* Backwards compatibility. */
rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1);
@@ -285,7 +295,7 @@ initialize_readline ()
enable_hostname_completion (perform_hostname_completion);
/* characters that need to be quoted when appearing in filenames. */
- rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!";
+ rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:";
rl_filename_quoting_function = bash_quote_filename;
rl_filename_dequoting_function = bash_dequote_filename;
rl_char_is_quoted_p = char_is_quoted;
@@ -592,13 +602,13 @@ vi_edit_and_execute_command (count, c)
the end of the history because fc ignores the last command (assumes
it's supposed to deal with the command before the `fc'). */
using_history ();
- add_history (rl_line_buffer);
- add_history ("");
+ bash_add_history (rl_line_buffer);
+ bash_add_history ("");
history_lines_this_session++;
using_history ();
command = savestring (VI_EDIT_COMMAND);
}
- parse_and_execute (command, "v", -1);
+ parse_and_execute (command, "v", SEVAL_NOHIST);
rl_line_buffer[0] = '\0'; /* XXX */
}
#endif /* VI_MODE */
@@ -688,8 +698,18 @@ attempt_shell_completion (text, start, end)
assignments. */
}
- /* Special handling for command substitution. */
- if (*text == '`' && unclosed_pair (rl_line_buffer, start, "`"))
+ /* Check that we haven't incorrectly flagged a closed command substitution
+ as indicating we're in a command position. */
+ if (in_command_position && rl_line_buffer[ti] == '`' && *text != '`' &&
+ unclosed_pair (rl_line_buffer, 0, "`") == 0)
+ in_command_position = 0;
+
+ /* Special handling for command substitution. If *TEXT is a backquote,
+ it can be the start or end of an old-style command substitution, or
+ unmatched. If it's unmatched, both calls to unclosed_pair will
+ succeed. */
+ if (*text == '`' && unclosed_pair (rl_line_buffer, start, "`") &&
+ unclosed_pair (rl_line_buffer, end, "`"))
matches = completion_matches (text, command_subst_completion_function);
/* Variable name? */
@@ -928,7 +948,7 @@ command_word_completion_function (hint_text, state)
}
else
{
- int match;
+ int match, freetemp;
char *temp;
if (absolute_program (hint))
@@ -948,6 +968,7 @@ command_word_completion_function (hint_text, state)
}
else
temp = savestring (val);
+ freetemp = 1;
}
else
{
@@ -956,12 +977,12 @@ command_word_completion_function (hint_text, state)
if (temp)
{
temp++;
- match = strncmp (temp, hint, hint_len) == 0;
+ freetemp = match = strncmp (temp, hint, hint_len) == 0;
if (match)
temp = savestring (temp);
}
else
- match = 0;
+ freetemp = match = 0;
}
/* If we have found a match, and it is an executable file or a
@@ -974,12 +995,15 @@ command_word_completion_function (hint_text, state)
}
else
{
+ if (freetemp)
+ free (temp);
free (val);
goto inner;
}
}
}
+/* Completion inside an unterminated command substitution. */
static char *
command_subst_completion_function (text, state)
char *text;
@@ -1148,19 +1172,23 @@ history_expand_line_internal (line)
char *new_line;
new_line = pre_process_line (line, 0, 0);
- return new_line;
+ return (new_line == line) ? savestring (line) : new_line;
}
#if defined (ALIAS)
-/* Perform alias expansion on LINE and return the new line. */
-static char *
-alias_expand_line_internal (line)
- char *line;
+/* Expand aliases in the current readline line. */
+static void
+alias_expand_line (ignore)
+ int ignore;
{
- char *alias_line;
+ char *new_line;
+
+ new_line = alias_expand (rl_line_buffer);
- alias_line = alias_expand (line);
- return alias_line;
+ if (new_line)
+ set_up_new_line (new_line);
+ else
+ cleanup_expansion_error ();
}
#endif
@@ -1173,7 +1201,8 @@ cleanup_expansion_error ()
fprintf (rl_outstream, "\r\n");
to_free = pre_process_line (rl_line_buffer, 1, 0);
- free (to_free);
+ if (to_free != rl_line_buffer)
+ free (to_free);
putc ('\r', rl_outstream);
rl_forced_update_display ();
}
@@ -1244,6 +1273,8 @@ history_and_alias_expand_line (ignore)
char *new_line;
new_line = pre_process_line (rl_line_buffer, 0, 0);
+ if (new_line == rl_line_buffer)
+ new_line = savestring (new_line);
#if defined (ALIAS)
if (new_line)
@@ -1272,6 +1303,8 @@ shell_expand_line (ignore)
WORD_LIST *expanded_string;
new_line = pre_process_line (rl_line_buffer, 0, 0);
+ if (new_line == rl_line_buffer)
+ new_line = savestring (new_line);
#if defined (ALIAS)
if (new_line)
@@ -1296,7 +1329,9 @@ shell_expand_line (ignore)
/* If there is variable expansion to perform, do that as a separate
operation to be undone. */
- expanded_string = expand_string (rl_line_buffer, 0);
+ new_line = savestring (rl_line_buffer);
+ expanded_string = expand_string (new_line, 0);
+ FREE (new_line);
if (expanded_string == 0)
{
new_line = xmalloc (1);
@@ -1862,7 +1897,44 @@ bash_dequote_filename (text, quote_char)
return ret;
}
-/* Quote a filename using double quotes. */
+/* Quote characters that the readline completion code would treat as
+ word break characters with backslashes. Pass backslash-quoted
+ characters through without examination. */
+static char *
+quote_word_break_chars (text)
+ char *text;
+{
+ char *ret, *r, *s;
+ int l;
+
+ l = strlen (text);
+ ret = xmalloc ((2 * l) + 1);
+ for (s = text, r = ret; *s; s++)
+ {
+ /* Pass backslash-quoted characters through, including the backslash. */
+ if (*s == '\\')
+ {
+ *r++ = '\\';
+ *r++ = *++s;
+ if (*s == '\0')
+ break;
+ continue;
+ }
+ /* OK, we have an unquoted character. Check its presence in
+ rl_completer_word_break_characters. */
+ if (strchr (rl_completer_word_break_characters, *s))
+ *r++ = '\\';
+ *r++ = *s;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* Quote a filename using double quotes, single quotes, or backslashes
+ depending on the value of completion_quoting_style. If we're
+ completing using backslashes, we need to quote some additional
+ characters (those that readline treats as word breaks), so we call
+ quote_word_break_chars on the result. */
static char *
bash_quote_filename (s, rtype, qcp)
char *s;
@@ -1896,6 +1968,13 @@ bash_quote_filename (s, rtype, qcp)
else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
history_expansion_inhibited == 0 && strchr (mtext, '!'))
cs = COMPLETE_BSQUOTE;
+
+ if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
+ history_expansion_inhibited == 0 && strchr (mtext, '!'))
+ {
+ cs = COMPLETE_BSQUOTE;
+ *qcp = '\0';
+ }
#endif
switch (cs)
@@ -1914,6 +1993,15 @@ bash_quote_filename (s, rtype, qcp)
if (mtext != s)
free (mtext);
+ /* We may need to quote additional characters: those that readline treats
+ as word breaks that are not quoted by backslash_quote. */
+ if (rtext && cs == COMPLETE_BSQUOTE)
+ {
+ mtext = quote_word_break_chars (rtext);
+ free (rtext);
+ rtext = mtext;
+ }
+
/* Leave the opening quote intact. The readline completion code takes
care of avoiding doubled opening quotes. */
rlen = strlen (rtext);