commit bash-20090903 snapshot

This commit is contained in:
Chet Ramey
2011-12-08 20:15:12 -05:00
parent af98a2a636
commit 824dfe6803
38 changed files with 876 additions and 72 deletions
+65
View File
@@ -8702,3 +8702,68 @@ subst.c
execute_cmd.c
- add fflush(stdout) and fflush(stderr) to child coproc code before
calling exit after execute_in_subshell
8/31
----
lib/readline/{{bind,readline}.c,rlprivate.h}
- new bindable variable, "echo-control-characters", enabled by default.
This controls whether or not readline honors the tty ECHOCTL bit
and displays characters corresponding to keyboard-generated signals.
Controlled by _rl_echo_control_chars variable, declared in readline.c
lib/readline/signals.c
- if _rl_echo_control_chars == 0, don't go through _rl_echo_signal_char
lib/readline/doc/{readline.3,rluser.texi}
- document "echo-control-characters" bindable variable
9/1
---
lib/readline/histexpand.c
- hist_string_extract_single_quoted now takes an additional argument:
a flags word. The only defined value (flags & 1) allows backslash
to quote the single quote. This is to inhibit history expansion
inside $'...' containing an escaped single quote.
- change history_expand to call hist_string_extract_single_quoted
with flags == 1 if it sees $'. Fixes bug reported by Sean
Donner <sean.donner@gmail.com>
9/2
---
builtins/printf.def
- add a call to sh_wrerror if ferror() succeeds in the PRETURN macro,
to print an error message in the case that the final fflush fails
(for instance, because it attempts to write data that didn't have a
trailing newline). Fixes bug reported by Stefano Lattarini
<stefano.lattarini@gmail.com>
9/7
---
arrayfunc.c
- some fixes to assign_compound_array_list to avoid null pointer
dereferences pointed out by clang/scan-build
lib/glob/glob.c
- fixes to udequote_pathname and wdequote_pathname to avoid possible
null pointer dereferences pointed out by clang/scan-build
lib/readline/undo.c
- fix to _rl_copy_undo_list (function unused) to avoid deref of
uninitialized pointer pointed out by clang/scan-build
general.c
- fix string_to_rlimtype so it works if passed a null pointer (though
it never is)
builtins/mapfile.def
- fix to mapfile() to avoid possible null pointer dereference pointed
out by clang/scan-build
variables.c
- fix to valid_exportstr to avoid possible null pointer dereferences
pointed out by clang/scan-build
bashline.c
- fix to bash_execute_unix_command to avoid possible null pointer
dereference if READLINE_LINE or READLINE_POINT is not bound
+62 -1
View File
@@ -8128,7 +8128,7 @@ lib/sh/casemod.c
multibyte character
lib/readline/mbutil.c
- fix _rl_find_next_mbchar_internalto not call mbrtowc at the end of
- fix _rl_find_next_mbchar_internal to not call mbrtowc at the end of
the string, since implementations return different values -- just
break the loop immediately
@@ -8702,3 +8702,64 @@ subst.c
execute_cmd.c
- add fflush(stdout) and fflush(stderr) to child coproc code before
calling exit after execute_in_subshell
8/31
----
lib/readline/{{bind,readline}.c,rlprivate.h}
- new bindable variable, "echo-control-characters", enabled by default.
This controls whether or not readline honors the tty ECHOCTL bit
and displays characters corresponding to keyboard-generated signals.
Controlled by _rl_echo_control_chars variable, declared in readline.c
lib/readline/signals.c
- if _rl_echo_control_chars == 0, don't go through _rl_echo_signal_char
lib/readline/doc/{readline.3,rluser.texi}
- document "echo-control-characters" bindable variable
9/1
---
lib/readline/histexpand.c
- hist_string_extract_single_quoted now takes an additional argument:
a flags word. The only defined value (flags & 1) allows backslash
to quote the single quote. This is to inhibit history expansion
inside $'...' containing an escaped single quote.
- change history_expand to call hist_string_extract_single_quoted
with flags == 1 if it sees $'. Fixes bug reported by Sean
Donner <sean.donner@gmail.com>
9/2
---
builtins/printf.def
- add a call to sh_wrerror if ferror() succeeds in the PRETURN macro,
to print an error message in the case that the final fflush fails
(for instance, because it attempts to write data that didn't have a
trailing newline). Fixes bug reported by Stefano Lattarini
<stefano.lattarini@gmail.com>
9/7
---
arrayfunc.c
- some fixes to assign_compound_array_list to avoid null pointer
dereferences pointed out by clang/scan-build
lib/glob/glob.c
- fixes to udequote_pathname and wdequote_pathname to avoid possible
null pointer dereferences pointed out by clang/scan-build
lib/readline/undo.c
- fix to _rl_copy_undo_list (function unused) to avoid deref of
uninitialized pointer pointed out by clang/scan-build
general.c
- fix string_to_rlimtype so it works if passed a null pointer (though
it never is)
builtins/mapfile.def
- fix to mapfile() to avoid possible null pointer dereference pointed
out by clang/scan-build
variables.c
- fix to valid_exportstr to avoid possible null pointer dereferences
pointed out by clang/scan-build
+1
View File
@@ -907,6 +907,7 @@ tests/new-exp7.sub f
tests/new-exp.right f
tests/nquote.tests f
tests/nquote.right f
tests/nquote1.sub f
tests/nquote1.tests f
tests/nquote1.right f
tests/nquote2.tests f
+5 -1
View File
@@ -344,4 +344,8 @@ Platform-Specific Configuration and Operation Notes
Apple ships inadequate dynamic libreadline and libhistory "replacements"
as standard libraries.
20. If you're on a system like SGI Irix, and you get an error about not
being able to refer to a dynamic symbol
(ld: non-dynamic relocations refer to dynamic symbol PC), add
-DNEED_EXTERN_PC to the LOCAL_CFLAGS variable in lib/readline/Makefile.in
and rebuild.
+4 -3
View File
@@ -407,6 +407,7 @@ expand_compound_array_assignment (var, value, flags)
return nlist;
}
/* Callers ensure that VAR is not NULL */
void
assign_compound_array_list (var, nlist, flags)
SHELL_VAR *var;
@@ -431,9 +432,9 @@ assign_compound_array_list (var, nlist, flags)
value. */
if ((flags & ASS_APPEND) == 0)
{
if (array_p (var) && a)
if (a && array_p (var))
array_flush (a);
else if (assoc_p (var) && h)
else if (h && assoc_p (var))
assoc_flush (h);
}
@@ -447,7 +448,7 @@ assign_compound_array_list (var, nlist, flags)
/* We have a word of the form [ind]=value */
if ((list->word->flags & W_ASSIGNMENT) && w[0] == '[')
{
len = skipsubscript (w, 0, assoc_p (var) != 0);
len = skipsubscript (w, 0, (var && assoc_p (var) != 0));
/* XXX - changes for `+=' */
if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))
+26 -11
View File
@@ -98,7 +98,7 @@ convert_var_to_assoc (var)
oldval = value_cell (var);
hash = assoc_create (0);
if (oldval)
assoc_insert (hash, "0", oldval);
assoc_insert (hash, savestring ("0"), oldval);
FREE (value_cell (var));
var_setassoc (var, hash);
@@ -431,9 +431,9 @@ assign_compound_array_list (var, nlist, flags)
value. */
if ((flags & ASS_APPEND) == 0)
{
if (array_p (var) && a)
if (a && array_p (var))
array_flush (a);
else if (assoc_p (var) && h)
else if (h && assoc_p (var))
assoc_flush (h);
}
@@ -447,7 +447,7 @@ assign_compound_array_list (var, nlist, flags)
/* We have a word of the form [ind]=value */
if ((list->word->flags & W_ASSIGNMENT) && w[0] == '[')
{
len = skipsubscript (w, 0);
len = skipsubscript (w, 0, (var && assoc_p (var) != 0));
/* XXX - changes for `+=' */
if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))
@@ -560,8 +560,9 @@ quote_assign (string)
{
size_t slen;
int saw_eq;
char *temp, *t;
char *temp, *t, *subs;
const char *s, *send;
int ss, se;
DECLARE_MBSTATE;
slen = strlen (string);
@@ -573,6 +574,20 @@ quote_assign (string)
{
if (*s == '=')
saw_eq = 1;
if (saw_eq == 0 && *s == '[') /* looks like a subscript */
{
ss = s - string;
se = skipsubscript (string, ss, 0);
subs = substring (s, ss, se);
*t++ = '\\';
strcpy (t, subs);
t += se - ss;
*t++ = '\\';
*t++ = ']';
s += se + 1;
free (subs);
continue;
}
if (saw_eq == 0 && (glob_char_p (s) || isifs (*s)))
*t++ = '\\';
@@ -596,7 +611,7 @@ quote_array_assignment_chars (list)
if (l->word == 0 || l->word->word == 0 || l->word->word[0] == '\0')
continue; /* should not happen, but just in case... */
/* Don't bother if it doesn't look like [ind]=value */
if (l->word->word[0] != '[' || xstrchr (l->word->word, '=') == 0) /* ] */
if (l->word->word[0] != '[' || mbschr (l->word->word, '=') == 0) /* ] */
continue;
nword = quote_assign (l->word->word);
free (l->word->word);
@@ -619,7 +634,7 @@ unbind_array_element (var, sub)
char *akey;
ARRAY_ELEMENT *ae;
len = skipsubscript (sub, 0);
len = skipsubscript (sub, 0, 0);
if (sub[len] != ']' || len == 0)
{
builtin_error ("%s[%s: %s", var->name, sub, _(bash_badsub_errmsg));
@@ -713,7 +728,7 @@ valid_array_reference (name)
char *t;
int r, len;
t = xstrchr (name, '['); /* ] */
t = mbschr (name, '['); /* ] */
if (t)
{
*t = '\0';
@@ -722,7 +737,7 @@ valid_array_reference (name)
if (r == 0)
return 0;
/* Check for a properly-terminated non-blank subscript. */
len = skipsubscript (t, 0);
len = skipsubscript (t, 0, 0);
if (t[len] != ']' || len == 1)
return 0;
for (r = 1; r < len; r++)
@@ -773,7 +788,7 @@ array_variable_name (s, subp, lenp)
char *t, *ret;
int ind, ni;
t = xstrchr (s, '[');
t = mbschr (s, '[');
if (t == 0)
{
if (subp)
@@ -783,7 +798,7 @@ array_variable_name (s, subp, lenp)
return ((char *)NULL);
}
ind = t - s;
ni = skipsubscript (s, ind);
ni = skipsubscript (s, ind, 0);
if (ni <= ind + 1 || s[ni] != ']')
{
err_badarraysub (s);
+4 -3
View File
@@ -3433,7 +3433,7 @@ bash_execute_unix_command (count, key)
register int i, r;
intmax_t mi;
sh_parser_state_t ps;
char *cmd, *value, *l, *ce;
char *cmd, *value, *l, *l1, *ce;
SHELL_VAR *v;
char ibuf[INT_STRLEN_BOUND(int) + 1];
@@ -3482,7 +3482,7 @@ bash_execute_unix_command (count, key)
v = bind_variable ("READLINE_LINE", rl_line_buffer, 0);
if (v)
VSETATTR (v, att_exported);
l = value_cell (v);
l = v ? value_cell (v) : 0;
value = inttostr (rl_point, ibuf, sizeof (ibuf));
v = bind_int_variable ("READLINE_POINT", value);
if (v)
@@ -3494,7 +3494,8 @@ bash_execute_unix_command (count, key)
restore_parser_state (&ps);
v = find_variable ("READLINE_LINE");
if (value_cell (v) != l)
l1 = v ? value_cell (v) : 0;
if (l1 != l)
maybe_make_readline_line (value_cell (v));
v = find_variable ("READLINE_POINT");
if (v && legal_number (value_cell (v), &mi))
+2
View File
@@ -502,6 +502,8 @@ initialize_readline ()
do other expansion on directory names. */
rl_directory_completion_hook = bash_directory_completion_hook;
rl_filename_rewrite_hook = bash_filename_rewrite_hook;
/* Tell the filename completer we want a chance to ignore some names. */
rl_ignore_some_completions_function = filename_completion_ignore;
+1 -1
View File
@@ -153,7 +153,7 @@ mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_n
entry = find_or_make_array_variable (array_name, 1);
if (entry == 0 || readonly_p (entry) || noassign_p (entry))
{
if (readonly_p (entry))
if (entry && readonly_p (entry))
err_readonly (array_name);
return (EXECUTION_FAILURE);
+1 -1
View File
@@ -281,7 +281,7 @@ mapfile_builtin (list)
break;
case 'c':
code = legal_number (list_optarg, &intval);
if (code == 0 || intval < 0 || intval != (unsigned)intval)
if (code == 0 || intval <= 0 || intval != (unsigned)intval)
{
builtin_error (_("%s: invalid callback quantum"), list_optarg);
return (EXECUTION_FAILURE);
+1
View File
@@ -156,6 +156,7 @@ extern int errno;
fflush (stdout); \
if (ferror (stdout)) \
{ \
sh_wrerror (); \
clearerr (stdout); \
return (EXECUTION_FAILURE); \
} \
+7 -2
View File
@@ -5,12 +5,12 @@
.\" Case Western Reserve University
.\" chet@po.cwru.edu
.\"
.\" Last Change: Sat Aug 22 12:02:47 EDT 2009
.\" Last Change: Mon Aug 31 08:59:57 EDT 2009
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2009 August 22" "GNU Bash-4.0"
.TH BASH 1 "2009 August 31" "GNU Bash-4.0"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -4947,6 +4947,11 @@ can be set to either
or
.BR vi .
.TP
.B echo\-control\-characters (On)
When set to \fBOn\fP, on operating systems that indicate they support it,
readline echoes a character corresponding to a signal generated from the
keyboard.
.TP
.B enable\-keypad (Off)
When set to \fBOn\fP, readline will try to enable the application
keypad when it is called. Some systems need this to enable the
+1 -1
View File
@@ -98,7 +98,7 @@ string_to_rlimtype (s)
neg = 0;
while (s && *s && whitespace (*s))
s++;
if (*s == '-' || *s == '+')
if (s && (*s == '-' || *s == '+'))
{
neg = *s == '-';
s++;
+2 -2
View File
@@ -285,7 +285,7 @@ assignment (string, flags)
#if defined (ARRAY_VARS)
if (c == '[')
{
newi = skipsubscript (string, indx);
newi = skipsubscript (string, indx, 0);
if (string[newi++] != ']')
return (0);
if (string[newi] == '+' && string[newi+1] == '=')
@@ -577,7 +577,7 @@ int
absolute_program (string)
const char *string;
{
return ((char *)xstrchr (string, '/') != (char *)NULL);
return ((char *)mbschr (string, '/') != (char *)NULL);
}
/* **************************************************************** */
+4 -2
View File
@@ -246,7 +246,8 @@ udequote_pathname (pathname)
if (pathname[i - 1] == 0)
break;
}
pathname[j] = '\0';
if (pathname)
pathname[j] = '\0';
}
#if HANDLE_MULTIBYTE
@@ -279,7 +280,8 @@ wdequote_pathname (pathname)
if (wpathname[i - 1] == L'\0')
break;
}
wpathname[j] = L'\0';
if (wpathname)
wpathname[j] = L'\0';
/* Convert the wide character string into unibyte character set. */
memset (&ps, '\0', sizeof(mbstate_t));
+1 -1
View File
@@ -637,7 +637,7 @@ glob_vector (pat, dir, flags)
continue;
}
convfn = fnxform (dp->d_name, D_NAMLEN (dp));
convfn = fnx_fromfs (dp->d_name, D_NAMLEN (dp));
if (strmatch (pat, convfn, mflags) != FNM_NOMATCH)
{
if (nalloca < ALLOCA_MAX)
+1
View File
@@ -1426,6 +1426,7 @@ static const struct {
{ "completion-ignore-case", &_rl_completion_case_fold, 0 },
{ "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 },
{ "disable-completion", &rl_inhibit_completion, 0 },
{ "echo-control-characters", &_rl_echo_control_chars, 0 },
{ "enable-keypad", &_rl_enable_keypad, 0 },
{ "expand-tilde", &rl_complete_with_tilde_expansion, 0 },
{ "history-preserve-point", &_rl_history_preserve_point, 0 },
+5
View File
@@ -401,6 +401,11 @@ can be set to either
or
.BR vi .
.TP
.B echo\-control\-characters (On)
When set to \fBOn\fP, on operating systems that indicate they support it,
readline echoes a character corresponding to a signal generated from the
keyboard.
.TP
.B enable\-keypad (Off)
When set to \fBOn\fP, readline will try to enable the application
keypad when it is called. Some systems need this to enable the
+5
View File
@@ -474,6 +474,11 @@ key bindings is used. By default, Readline starts up in Emacs editing
mode, where the keystrokes are most similar to Emacs. This variable can be
set to either @samp{emacs} or @samp{vi}.
@item echo-control-characters
When set to @samp{on}, on operating systems that indicate they support it,
readline echoes a character corresponding to a signal generated from the
keyboard. The default is @samp{on}.
@item enable-keypad
@vindex enable-keypad
When set to @samp{on}, Readline will try to enable the application
+2 -2
View File
@@ -4,7 +4,7 @@ Copyright (C) 1988-2009 Free Software Foundation, Inc.
@set EDITION 6.0
@set VERSION 6.0
@set UPDATED 22 August 2009
@set UPDATED 31 August 2009
@set UPDATED-MONTH August 2009
@set LASTCHANGE Sat Aug 22 12:02:34 EDT 2009
@set LASTCHANGE Mon Aug 31 09:01:30 EDT 2009
+26 -16
View File
@@ -305,16 +305,20 @@ get_history_event (string, caller_index, delimiting_quote)
/* Extract the contents of STRING as if it is enclosed in single quotes.
SINDEX, when passed in, is the offset of the character immediately
following the opening single quote; on exit, SINDEX is left pointing
to the closing single quote. */
to the closing single quote. FLAGS currently used to allow backslash
to escape a single quote (e.g., for bash $'...'). */
static void
hist_string_extract_single_quoted (string, sindex)
hist_string_extract_single_quoted (string, sindex, flags)
char *string;
int *sindex;
int *sindex, flags;
{
register int i;
for (i = *sindex; string[i] && string[i] != '\''; i++)
;
{
if ((flags & 1) && string[i] == '\\' && string[i+1])
i++;
}
*sindex = i;
}
@@ -924,7 +928,7 @@ history_expand (hstring, output)
char **output;
{
register int j;
int i, r, l, passc, cc, modified, eindex, only_printing, dquote;
int i, r, l, passc, cc, modified, eindex, only_printing, dquote, flag;
char *string;
/* The output string, and its length. */
@@ -1044,8 +1048,9 @@ history_expand (hstring, output)
else if (dquote == 0 && history_quotes_inhibit_expansion && string[i] == '\'')
{
/* If this is bash, single quotes inhibit history expansion. */
flag = (i > 0 && string[i - 1] == '$');
i++;
hist_string_extract_single_quoted (string, &i);
hist_string_extract_single_quoted (string, &i, flag);
}
else if (history_quotes_inhibit_expansion && string[i] == '\\')
{
@@ -1130,8 +1135,9 @@ history_expand (hstring, output)
{
int quote, slen;
flag = (i > 0 && string[i - 1] == '$');
quote = i++;
hist_string_extract_single_quoted (string, &i);
hist_string_extract_single_quoted (string, &i, flag);
slen = i - quote + 2;
temp = (char *)xmalloc (slen);
@@ -1435,17 +1441,21 @@ history_tokenize_word (string, ind)
i += 2;
return i;
}
else
else if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
(peek == '>' && string[i] == '&') ||
(peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
(peek == '(' && string[i] == '$')) /* ) */
{
if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
(peek == '>' && string[i] == '&') ||
(peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
(peek == '(' && string[i] == '$')) /* ) */
{
i += 2;
return i;
}
i += 2;
return i;
}
#if 0
else if (peek == '\'' && string[i] == '$')
{
i += 2; /* XXX */
return i;
}
#endif
if (string[i] != '$')
{
+4
View File
@@ -275,6 +275,10 @@ int _rl_bind_stty_chars = 1;
its initial state. */
int _rl_revert_all_at_newline = 0;
/* Non-zero means to honor the termios ECHOCTL bit and echo control
characters corresponding to keyboard-generated signals. */
int _rl_echo_control_chars = 1;
/* **************************************************************** */
/* */
/* Top Level Functions */
+1
View File
@@ -421,6 +421,7 @@ extern int _rl_convert_meta_chars_to_ascii;
extern int _rl_output_meta_chars;
extern int _rl_bind_stty_chars;
extern int _rl_revert_all_at_newline;
extern int _rl_echo_control_chars;
extern char *_rl_comment_begin;
extern unsigned char _rl_parsing_conditionalized_out;
extern Keymap _rl_keymap;
+3 -2
View File
@@ -101,7 +101,8 @@ int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */
int _rl_interrupt_immediately = 0;
int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including <signal.h> everywhere */
/* If non-zero, print characters corresponding to received signals. */
/* If non-zero, print characters corresponding to received signals as long as
the user has indicated his desire to do so (_rl_echo_control_chars). */
int _rl_echoctl = 0;
int _rl_intr_char = 0;
@@ -637,7 +638,7 @@ rl_echo_signal_char (sig)
char cstr[3];
int cslen, c;
if (_rl_echoctl == 0)
if (_rl_echoctl == 0 || _rl_echo_control_chars == 0)
return;
switch (sig)
+1 -1
View File
@@ -1151,7 +1151,7 @@ int
rl_delete_horizontal_space (count, ignore)
int count, ignore;
{
int start = rl_point;
int start;
while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
rl_point--;
+6 -3
View File
@@ -189,10 +189,13 @@ _rl_replace_text (text, start, end)
{
int n;
n = 0;
rl_begin_undo_group ();
rl_delete_text (start, end + 1);
if (start <= end)
rl_delete_text (start, end + 1);
rl_point = start;
n = rl_insert_text (text);
if (*text)
n = rl_insert_text (text);
rl_end_undo_group ();
return n;
@@ -583,7 +586,7 @@ rl_skip_csi_sequence (count, key)
RL_SETSTATE (RL_STATE_MOREINPUT);
do
ch = rl_read_key ();
while (ch >= 0x20 && ch < 0x40)
while (ch >= 0x20 && ch < 0x40);
RL_UNSETSTATE (RL_STATE_MOREINPUT);
return 0;
+3
View File
@@ -139,6 +139,9 @@ _rl_copy_undo_list (head)
{
UNDO_LIST *list, *new, *roving, *c;
if (head == 0)
return head;
list = head;
new = 0;
while (list)
+328
View File
@@ -0,0 +1,328 @@
/* readline.c -- a general facility for reading lines of input
with emacs style editing and completion. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
Readline is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Readline is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Readline. If not, see <http://www.gnu.org/licenses/>.
*/
#define READLINE_LIBRARY
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h> /* for _POSIX_VERSION */
#endif /* HAVE_UNISTD_H */
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
#include <stdio.h>
/* System-specific feature definitions and include files. */
#include "rldefs.h"
/* Some standard library routines. */
#include "readline.h"
#include "history.h"
#include "rlprivate.h"
#include "xmalloc.h"
extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
/* Non-zero tells rl_delete_text and rl_insert_text to not add to
the undo list. */
int _rl_doing_an_undo = 0;
/* How many unclosed undo groups we currently have. */
int _rl_undo_group_level = 0;
/* The current undo list for THE_LINE. */
UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
/* **************************************************************** */
/* */
/* Undo, and Undoing */
/* */
/* **************************************************************** */
static UNDO_LIST *
alloc_undo_entry (what, start, end, text)
enum undo_code what;
int start, end;
char *text;
{
UNDO_LIST *temp;
temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
temp->what = what;
temp->start = start;
temp->end = end;
temp->text = text;
temp->next = (UNDO_LIST *)NULL;
return temp;
}
/* Remember how to undo something. Concatenate some undos if that
seems right. */
void
rl_add_undo (what, start, end, text)
enum undo_code what;
int start, end;
char *text;
{
UNDO_LIST *temp;
temp = alloc_undo_entry (what, start, end, text);
temp->next = rl_undo_list;
rl_undo_list = temp;
}
/* Free the existing undo list. */
void
rl_free_undo_list ()
{
UNDO_LIST *release, *orig_list;
orig_list = rl_undo_list;
while (rl_undo_list)
{
release = rl_undo_list;
rl_undo_list = rl_undo_list->next;
if (release->what == UNDO_DELETE)
xfree (release->text);
xfree (release);
}
rl_undo_list = (UNDO_LIST *)NULL;
replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
}
UNDO_LIST *
_rl_copy_undo_entry (entry)
UNDO_LIST *entry;
{
UNDO_LIST *new;
new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
new->text = entry->text ? savestring (entry->text) : 0;
return new;
}
UNDO_LIST *
_rl_copy_undo_list (head)
UNDO_LIST *head;
{
UNDO_LIST *list, *new, *roving, *c;
list = head;
new = 0;
while (list)
{
c = _rl_copy_undo_entry (list);
if (new == 0)
roving = new = c;
else
{
roving->next = c;
roving = roving->next;
}
list = list->next;
}
roving->next = 0;
return new;
}
/* Undo the next thing in the list. Return 0 if there
is nothing to undo, or non-zero if there was. */
int
rl_do_undo ()
{
UNDO_LIST *release;
int waiting_for_begin, start, end;
#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
start = end = waiting_for_begin = 0;
do
{
if (rl_undo_list == 0)
return (0);
_rl_doing_an_undo = 1;
RL_SETSTATE(RL_STATE_UNDOING);
/* To better support vi-mode, a start or end value of -1 means
rl_point, and a value of -2 means rl_end. */
if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
{
start = TRANS (rl_undo_list->start);
end = TRANS (rl_undo_list->end);
}
switch (rl_undo_list->what)
{
/* Undoing deletes means inserting some text. */
case UNDO_DELETE:
rl_point = start;
rl_insert_text (rl_undo_list->text);
xfree (rl_undo_list->text);
break;
/* Undoing inserts means deleting some text. */
case UNDO_INSERT:
rl_delete_text (start, end);
rl_point = start;
break;
/* Undoing an END means undoing everything 'til we get to a BEGIN. */
case UNDO_END:
waiting_for_begin++;
break;
/* Undoing a BEGIN means that we are done with this group. */
case UNDO_BEGIN:
if (waiting_for_begin)
waiting_for_begin--;
else
rl_ding ();
break;
}
_rl_doing_an_undo = 0;
RL_UNSETSTATE(RL_STATE_UNDOING);
release = rl_undo_list;
rl_undo_list = rl_undo_list->next;
replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
xfree (release);
}
while (waiting_for_begin);
return (1);
}
#undef TRANS
int
_rl_fix_last_undo_of_type (type, start, end)
int type, start, end;
{
UNDO_LIST *rl;
for (rl = rl_undo_list; rl; rl = rl->next)
{
if (rl->what == type)
{
rl->start = start;
rl->end = end;
return 0;
}
}
return 1;
}
/* Begin a group. Subsequent undos are undone as an atomic operation. */
int
rl_begin_undo_group ()
{
rl_add_undo (UNDO_BEGIN, 0, 0, 0);
_rl_undo_group_level++;
return 0;
}
/* End an undo group started with rl_begin_undo_group (). */
int
rl_end_undo_group ()
{
rl_add_undo (UNDO_END, 0, 0, 0);
_rl_undo_group_level--;
return 0;
}
/* Save an undo entry for the text from START to END. */
int
rl_modifying (start, end)
int start, end;
{
if (start > end)
{
SWAP (start, end);
}
if (start != end)
{
char *temp = rl_copy_text (start, end);
rl_begin_undo_group ();
rl_add_undo (UNDO_DELETE, start, end, temp);
rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
rl_end_undo_group ();
}
return 0;
}
/* Revert the current line to its previous state. */
int
rl_revert_line (count, key)
int count, key;
{
if (rl_undo_list == 0)
rl_ding ();
else
{
while (rl_undo_list)
rl_do_undo ();
#if defined (VI_MODE)
if (rl_editing_mode == vi_mode)
rl_point = rl_mark = 0; /* rl_end should be set correctly */
#endif
}
return 0;
}
/* Do some undoing of things that were done. */
int
rl_undo_command (count, key)
int count, key;
{
if (count < 0)
return 0; /* Nothing to do. */
while (count)
{
if (rl_do_undo ())
count--;
else
{
rl_ding ();
break;
}
}
return 0;
}
+1 -1
View File
@@ -92,7 +92,7 @@ uconvert(s, ip, up)
ipart = (ipart * 10) + (*p - '0');
}
if (*p == 0)
if (p == 0 || *p == 0) /* callers ensure p can never be 0; this is to shut up clang */
RETURN(1);
if (*p == DECIMAL)
+116
View File
@@ -0,0 +1,116 @@
/* uconvert - convert string representations of decimal numbers into whole
number/fractional value pairs. */
/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "bashtypes.h"
#if defined (TIME_WITH_SYS_TIME)
# include <sys/time.h>
# include <time.h>
#else
# if defined (HAVE_SYS_TIME_H)
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <stdio.h>
#include "chartypes.h"
#include "shell.h"
#include "builtins.h"
#define DECIMAL '.' /* XXX - should use locale */
#define RETURN(x) \
do { \
if (ip) *ip = ipart * mult; \
if (up) *up = upart; \
return (x); \
} while (0)
/*
* An incredibly simplistic floating point converter.
*/
static int multiplier[7] = { 1, 100000, 10000, 1000, 100, 10, 1 };
/* Take a decimal number int-part[.[micro-part]] and convert it to the whole
and fractional portions. The fractional portion is returned in
millionths (micro); callers are responsible for multiplying appropriately.
Return 1 if value converted; 0 if invalid integer for either whole or
fractional parts. */
int
uconvert(s, ip, up)
char *s;
long *ip, *up;
{
int n, mult;
long ipart, upart;
char *p;
ipart = upart = 0;
mult = 1;
if (s && (*s == '-' || *s == '+'))
{
mult = (*s == '-') ? -1 : 1;
p = s + 1;
}
else
p = s;
for ( ; p && *p; p++)
{
if (*p == DECIMAL) /* decimal point */
break;
if (DIGIT(*p) == 0)
RETURN(0);
ipart = (ipart * 10) + (*p - '0');
}
if (*p == 0)
RETURN(1);
if (*p == DECIMAL)
p++;
/* Look for up to six digits past a decimal point. */
for (n = 0; n < 6 && p[n]; n++)
{
if (DIGIT(p[n]) == 0)
RETURN(0);
upart = (upart * 10) + (p[n] - '0');
}
/* Now convert to millionths */
upart *= multiplier[n];
if (n == 6 && p[6] >= '5' && p[6] <= '9')
upart++; /* round up 1 */
RETURN(1);
}
+1 -1
View File
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
#define PATCHLEVEL 28
#define PATCHLEVEL 33
#endif /* _PATCHLEVEL_H_ */
+1 -2
View File
@@ -1031,7 +1031,7 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
char *charlist;
int flags;
{
register int i = *sindex;
register int i;
#if defined (HANDLE_MULTIBYTE)
size_t clen;
wchar_t *wcharlist;
@@ -2662,7 +2662,6 @@ do_assignment_internal (word, expand)
}
else
#endif
if (expand && temp[0])
value = expand_string_if_necessary (temp, 0, expand_string_assignment);
else
+147 -14
View File
@@ -314,6 +314,135 @@ static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
/* */
/* **************************************************************** */
#if defined (DEBUG)
void
dump_word_flags (flags)
int flags;
{
int f;
f = flags;
fprintf (stderr, "%d -> ", f);
if (f & W_ASSIGNASSOC)
{
f &= ~W_ASSIGNASSOC;
fprintf (stderr, "W_ASSIGNASSOC%s", f ? "|" : "");
}
if (f & W_HASCTLESC)
{
f &= ~W_HASCTLESC;
fprintf (stderr, "W_HASCTLESC%s", f ? "|" : "");
}
if (f & W_NOPROCSUB)
{
f &= ~W_NOPROCSUB;
fprintf (stderr, "W_NOPROCSUB%s", f ? "|" : "");
}
if (f & W_DQUOTE)
{
f &= ~W_DQUOTE;
fprintf (stderr, "W_DQUOTE%s", f ? "|" : "");
}
if (f & W_HASQUOTEDNULL)
{
f &= ~W_HASQUOTEDNULL;
fprintf (stderr, "W_HASQUOTEDNULL%s", f ? "|" : "");
}
if (f & W_ASSIGNARG)
{
f &= ~W_ASSIGNARG;
fprintf (stderr, "W_ASSIGNARG%s", f ? "|" : "");
}
if (f & W_ASSNBLTIN)
{
f &= ~W_ASSNBLTIN;
fprintf (stderr, "W_ASSNBLTIN%s", f ? "|" : "");
}
if (f & W_COMPASSIGN)
{
f &= ~W_COMPASSIGN;
fprintf (stderr, "W_COMPASSIGN%s", f ? "|" : "");
}
if (f & W_NOEXPAND)
{
f &= ~W_NOEXPAND;
fprintf (stderr, "W_NOEXPAND%s", f ? "|" : "");
}
if (f & W_ITILDE)
{
f &= ~W_ITILDE;
fprintf (stderr, "W_ITILDE%s", f ? "|" : "");
}
if (f & W_NOTILDE)
{
f &= ~W_NOTILDE;
fprintf (stderr, "W_NOTILDE%s", f ? "|" : "");
}
if (f & W_ASSIGNRHS)
{
f &= ~W_ASSIGNRHS;
fprintf (stderr, "W_ASSIGNRHS%s", f ? "|" : "");
}
if (f & W_NOCOMSUB)
{
f &= ~W_NOCOMSUB;
fprintf (stderr, "W_NOCOMSUB%s", f ? "|" : "");
}
if (f & W_DOLLARSTAR)
{
f &= ~W_DOLLARSTAR;
fprintf (stderr, "W_DOLLARSTAR%s", f ? "|" : "");
}
if (f & W_DOLLARAT)
{
f &= ~W_DOLLARAT;
fprintf (stderr, "W_DOLLARAT%s", f ? "|" : "");
}
if (f & W_TILDEEXP)
{
f &= ~W_TILDEEXP;
fprintf (stderr, "W_TILDEEXP%s", f ? "|" : "");
}
if (f & W_NOSPLIT2)
{
f &= ~W_NOSPLIT2;
fprintf (stderr, "W_NOSPLIT2%s", f ? "|" : "");
}
if (f & W_NOGLOB)
{
f &= ~W_NOGLOB;
fprintf (stderr, "W_NOGLOB%s", f ? "|" : "");
}
if (f & W_NOSPLIT)
{
f &= ~W_NOSPLIT;
fprintf (stderr, "W_NOSPLIT%s", f ? "|" : "");
}
if (f & W_GLOBEXP)
{
f &= ~W_GLOBEXP;
fprintf (stderr, "W_GLOBEXP%s", f ? "|" : "");
}
if (f & W_ASSIGNMENT)
{
f &= ~W_ASSIGNMENT;
fprintf (stderr, "W_ASSIGNMENT%s", f ? "|" : "");
}
if (f & W_QUOTED)
{
f &= ~W_QUOTED;
fprintf (stderr, "W_QUOTED%s", f ? "|" : "");
}
if (f & W_HASDOLLAR)
{
f &= ~W_HASDOLLAR;
fprintf (stderr, "W_HASDOLLAR%s", f ? "|" : "");
}
fprintf (stderr, "\n");
fflush (stderr);
}
#endif
#ifdef INCLUDE_UNUSED
static char *
quoted_substring (string, start, end)
@@ -588,7 +717,7 @@ string_extract (string, sindex, charlist, flags)
{
int ni;
/* If this is an array subscript, skip over it and continue. */
ni = skipsubscript (string, i);
ni = skipsubscript (string, i, 0);
if (string[ni] == ']')
i = ni;
}
@@ -902,7 +1031,7 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
char *charlist;
int flags;
{
register int i = *sindex;
register int i;
#if defined (HANDLE_MULTIBYTE)
size_t clen;
wchar_t *wcharlist;
@@ -1380,7 +1509,10 @@ unquote_bang (string)
#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
/* This function assumes s[i] == open; returns with s[ret] == close; used to
parse array subscripts. FLAGS currently unused. */
parse array subscripts. FLAGS & 1 means to not attempt to skip over
matched pairs of quotes or backquotes, or skip word expansions; it is
intended to be used after expansion has been performed and during final
assignment parsing (see arrayfunc.c:assign_compound_array_list()). */
static int
skip_matched_pair (string, start, open, close, flags)
const char *string;
@@ -1421,13 +1553,13 @@ skip_matched_pair (string, start, open, close, flags)
ADVANCE_CHAR (string, slen, i);
continue;
}
else if (c == '`')
else if ((flags & 1) == 0 && c == '`')
{
backq = 1;
i++;
continue;
}
else if (c == open)
else if ((flags & 1) == 0 && c == open)
{
count++;
i++;
@@ -1441,13 +1573,13 @@ skip_matched_pair (string, start, open, close, flags)
i++;
continue;
}
else if (c == '\'' || c == '"')
else if ((flags & 1) == 0 && (c == '\'' || c == '"'))
{
i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
: skip_double_quoted (ss, slen, ++i);
/* no increment, the skip functions increment past the closing quote. */
}
else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
else if ((flags&1) == 0 && c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
{
si = i + 2;
if (string[si] == '\0')
@@ -1472,11 +1604,11 @@ skip_matched_pair (string, start, open, close, flags)
#if defined (ARRAY_VARS)
int
skipsubscript (string, start)
skipsubscript (string, start, flags)
const char *string;
int start;
int start, flags;
{
return (skip_matched_pair (string, start, '[', ']', 0));
return (skip_matched_pair (string, start, '[', ']', flags));
}
#endif
@@ -1810,8 +1942,9 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
/* Special case for SENTINEL at the end of STRING. If we haven't found
the word containing SENTINEL yet, and the index we're looking for is at
the end of STRING, add an additional null argument and set the current
word pointer to that. */
the end of STRING (or past the end of the previously-found token,
possible if the end of the line is composed solely of IFS whitespace)
add an additional null argument and set the current word pointer to that. */
if (cwp && cw == -1 && (sentinel >= slen || sentinel >= te))
{
if (whitespace (string[sentinel - 1]))
@@ -4865,7 +4998,7 @@ command_substitute (string, quoted)
if (wordexp_only && read_but_dont_execute)
{
last_command_exit_value = 125;
last_command_exit_value = EX_WEXPCOMSUB;
jump_to_top_level (EXITPROG);
}
@@ -6635,7 +6768,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
*contains_dollar_at = 1;
}
free (x);
free (xlist);
dispose_words (xlist);
free (temp1);
*indexp = sindex;
+3
View File
@@ -35,3 +35,6 @@ argv[1] = <hello, $world>
;foo
argv[1] = <^I>
argv[1] = <'A^IB'>
hello' world
hello world!
hello' world!
+2
View File
@@ -114,3 +114,5 @@ args ()
unset mytab
recho "${mytab:-$'\t'}"
recho "$( args $'A\tB' )"
${THIS_SH} ./nquote1.sub
+6
View File
@@ -0,0 +1,6 @@
set -o history
set -H
echo $'hello\' world'
echo $'hello world!'
echo $'hello\' world!'
+5
View File
@@ -3366,6 +3366,11 @@ valid_exportstr (v)
char *s;
s = v->exportstr;
if (s == 0)
{
internal_error (_("%s has null exportstr"), v->name);
return (0);
}
if (legal_variable_starter ((unsigned char)*s) == 0)
{
internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
+22 -1
View File
@@ -2226,7 +2226,7 @@ bind_variable_internal (name, value, table, hflags, aflags)
}
else if (assoc_p (entry))
{
assoc_insert (assoc_cell (entry), "0", newval);
assoc_insert (assoc_cell (entry), savestring ("0"), newval);
free (newval);
}
else
@@ -4644,11 +4644,32 @@ sv_xtracefd (name)
char *name;
{
SHELL_VAR *v;
char *t, *e;
int fd;
FILE *fp;
v = find_variable (name);
if (v == 0)
{
xtrace_reset ();
return;
}
t = value_cell (v);
if (t == 0 || *t == 0)
xtrace_reset ();
else
{
fd = (int)strtol (t, &e, 10);
if (e != t && *e == '\0' && sh_validfd (fd))
{
fp = fdopen (fd, "w");
if (fp == 0)
internal_error (_("%s: %s: cannot open as FILE"), name, value_cell (v));
else
xtrace_set (fd, fp);
}
else
internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v));
}
}