commit bash-20160527 snapshot

This commit is contained in:
Chet Ramey
2016-05-31 11:18:22 -04:00
parent bddda3d2e1
commit 80df5e5041
15 changed files with 490 additions and 60 deletions
+56
View File
@@ -11097,3 +11097,59 @@ variables.c
things based on whether or not we get it. Right now we don't do
anything different, but we could
5/24
----
lib/readline/display.c
- update_line,_rl_move_cursor_relative: save value of MB_CUR_MAX in a
variable and use it throughout the functions instead of recomputing it
every time (which possibly costs a function call)
5/25
----
builtins/declare.def
- declare_internal: only check whether the value being assigned to a
nameref variable is a valid identifier if we're not appending to an
existing value. Suggested by Grisha Levit <grishalevit@gmail.com>
- declare_internal: add a couple of more checks on nameref names:
o make sure `declare -n x[3]=y' is an error
o nameref variable self-references now produce a warning when in
function scope
o nameref variable self-references using subscripted arrays
(a=a[0]) now produce warnings at function scope and errors at
global scope
5/29
----
builtins/declare.def
- declare_internal: use name of readonly variable when calling sh_readonly
instead of name passed as argument to declare in case we've followed
a nameref chain
- declare_internal: when turning off attributes on a nameref variable
after following the nameref chain and turning them off on the target
variable, don't allow the readonly attribute to be removed. This is
primarily intended to turn off the nameref attribute. Issue pointed
out by Grisha Levit <grishalevit@gmail.com>
- declare_internal: if we are attempting to modify an existing global
nameref variable, and the -n option is supplied, operate on the
nameref variable itself, not the variable it references
doc/{bash.1,bashref.texi}
- change the descriptions of namerefs and declare -n slightly to note
that using the -n option to declare will operate on the nameref
variable itself rather than the variable it references
variables.c
- bind_variable_internal: if trying to assign to a read-only variable,
print the error message using the variable's name instead of the
name passed to bind_variable in case we followed a nameref
builtins/declare.def
- declare_internal: when we're creating a (possibly invisible) variable
as part of another operation, assigning NULL, make sure to use
ASS_FORCE to avoid warning messages from any existing nameref
variables we follow
- declare_internal: allow the nameref attribute to be removed from a
readonly nameref variable without a value but do not allow it to be
removed from a readonly nameref variable that has a value, even if it
doesn't reference an existing variable. This distinction is for ksh93
compatibility. Pointed out by Grisha Levit <grishalevit@gmail.com>
+3
View File
@@ -1085,6 +1085,9 @@ tests/nameref11.sub f
tests/nameref12.sub f
tests/nameref13.sub f
tests/nameref14.sub f
tests/nameref15.sub f
tests/nameref16.sub f
tests/nameref17.sub f
tests/nameref.right f
tests/new-exp.tests f
tests/new-exp1.sub f
+1 -1
View File
@@ -280,7 +280,7 @@ assign_array_element (name, value, flags)
{
char *sub, *vname;
int sublen;
SHELL_VAR *entry;
SHELL_VAR *entry, *nv;
vname = array_variable_name (name, &sub, &sublen);
+74 -13
View File
@@ -325,24 +325,46 @@ declare_internal (list, local_var)
that is specific to nameref variables. */
if (flags_on & att_nameref)
{
#if defined (ARRAY_VARIABLES)
#if defined (ARRAY_VARS)
if (valid_array_reference (name, 0))
{
builtin_error (_("%s: reference variable cannot be an array"), name);
assign_error++;
NEXT_VARIABLE ();
}
else if (valid_array_reference (value, 0))
{
t = array_variable_name (value, (int *)NULL, (int *)NULL);
if (t && STREQ (name, t))
{
if (variable_context == 0)
{
free (t);
builtin_error (_("%s: nameref variable self references not allowed"), name);
assign_error++;
NEXT_VARIABLE ();
}
else
builtin_warning (_("%s: circular name reference"), name);
}
free (t);
}
else
#endif
/* disallow self references at global scope */
if (STREQ (name, value) && variable_context == 0)
/* disallow self references at global scope, warn at function scope */
if (STREQ (name, value))
{
builtin_error (_("%s: nameref variable self references not allowed"), name);
assign_error++;
NEXT_VARIABLE ();
if (variable_context == 0)
{
builtin_error (_("%s: nameref variable self references not allowed"), name);
assign_error++;
NEXT_VARIABLE ();
}
else
builtin_warning (_("%s: circular name reference"), name);
}
#if 1
if (value && *value && valid_nameref_value (value, 0) == 0)
if (value && *value && (aflags & ASS_APPEND) == 0 && valid_nameref_value (value, 0) == 0)
{
builtin_error (_("`%s': invalid variable name for name reference"), value);
assign_error++;
@@ -430,6 +452,12 @@ declare_internal (list, local_var)
any_failed++;
NEXT_VARIABLE ();
}
if (var && nameref_p (var) && readonly_p (var) && nameref_cell (var) && (flags_off & att_nameref))
{
sh_readonly (name);
any_failed++;
NEXT_VARIABLE ();
}
}
else
var = (SHELL_VAR *)NULL;
@@ -493,18 +521,33 @@ declare_internal (list, local_var)
NEXT_VARIABLE ();
}
}
else /* declare -[aAirx] name [name...] */
else /* declare -[aAinrx] name [name...] */
{
/* Non-null if we just created or fetched a local variable. */
#if 0
/* This is bash-4.3 code. */
/* Here's what ksh93 seems to do. If we are modifying an existing
nameref variable, we don't follow the nameref chain past the last
nameref, and we set the nameref variable's value so future
references to that variable will return the value of the variable
we're assigning right now. */
#else
/* Here's what ksh93 seems to do as of the 2012 version: if we are
using declare -n to modify the value of an existing nameref
variable, don't follow the nameref chain at all and just search
for a nameref at the current context. If we have a nameref,
modify its value (changing which variable it references). */
#endif
if (var == 0 && (flags_on & att_nameref))
{
#if 0
/* See if we are trying to modify an existing nameref variable */
var = mkglobal ? find_global_variable_last_nameref (name, 1) : find_variable_last_nameref (name, 1);
#else
/* See if we are trying to modify an existing nameref variable,
but don't follow the nameref chain. */
var = mkglobal ? find_global_variable_noref (name) : find_variable_noref (name);
#endif
if (var && nameref_p (var) == 0)
var = 0;
}
@@ -519,6 +562,16 @@ declare_internal (list, local_var)
refvar = mkglobal ? find_global_variable_last_nameref (name, 0) : find_variable_last_nameref (name, 0);
if (refvar && nameref_p (refvar) == 0)
refvar = 0;
/* If the nameref is readonly but doesn't have a value, ksh93
allows the nameref attribute to be removed. If it's readonly
and has a value, even if the value doesn't reference an
existing variable, we disallow the modification */
if (refvar && nameref_cell (refvar) && readonly_p (refvar))
{
sh_readonly (name);
any_failed++;
NEXT_VARIABLE ();
}
if (refvar)
var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
}
@@ -574,7 +627,7 @@ declare_internal (list, local_var)
var = mkglobal ? bind_global_variable (name, (char *)NULL, ASS_FORCE) : bind_variable (name, (char *)NULL, ASS_FORCE);
else
{
var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
var = mkglobal ? bind_global_variable (name, (char *)NULL, ASS_FORCE) : bind_variable (name, (char *)NULL, ASS_FORCE);
if (var && no_invisible_vars == 0)
VSETATTR (var, att_invisible);
}
@@ -622,7 +675,7 @@ declare_internal (list, local_var)
/* Cannot use declare +r to turn off readonly attribute. */
if (readonly_p (var) && (flags_off & att_readonly))
{
sh_readonly (name);
sh_readonly (name_cell (var));
any_failed++;
NEXT_VARIABLE ();
}
@@ -758,7 +811,8 @@ declare_internal (list, local_var)
v = bind_variable_value (var, value, aflags);
if (v == 0 && (onref || nameref_p (var)))
{
sh_invalidid (value);
if (valid_nameref_value (value, 0) == 0)
sh_invalidid (value);
assign_error++;
/* XXX - unset this variable? or leave it as normal var? */
delete_var (var->name, mkglobal ? global_variables : shell_variables);
@@ -801,9 +855,16 @@ declare_internal (list, local_var)
flags_on |= onref;
VUNSETATTR (var, offref);
flags_off |= offref;
/* Yuck. ksh93 compatibility */
/* Yuck. ksh93 compatibility. XXX - need to investigate more but
definitely happens when turning off nameref attribute on nameref
(see comments above). Under no circumstances allow this to turn
off readonly attribute on readonly nameref variable. */
if (refvar)
VUNSETATTR (refvar, flags_off);
{
if (flags_off & att_readonly)
flags_off &= ~att_readonly;
VUNSETATTR (refvar, flags_off);
}
stupidly_hack_special_variables (name);
+5 -4
View File
@@ -5,12 +5,12 @@
.\" Case Western Reserve University
.\" chet.ramey@case.edu
.\"
.\" Last Change: Wed Apr 27 09:19:58 EDT 2016
.\" Last Change: Sun May 29 13:48:21 EDT 2016
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2016 April 27" "GNU Bash 4.4"
.TH BASH 1 "2016 May 29" "GNU Bash 4.4"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -1266,7 +1266,8 @@ A variable can be assigned the \fInameref\fP attribute using the
to create a \fInameref\fP, or a reference to another variable.
This allows variables to be manipulated indirectly.
Whenever the nameref variable is referenced, assigned to, unset, or has
its attributes modified (other than the \fInameref\fP attribute itself), the
its attributes modified (other than using or changing the \fInameref\fP
attribute itself), the
operation is actually performed on the variable specified by the nameref
variable's value.
A nameref is commonly used within shell functions to refer to a variable
@@ -7723,7 +7724,7 @@ Give each \fIname\fP the \fInameref\fP attribute, making
it a name reference to another variable.
That other variable is defined by the value of \fIname\fP.
All references, assignments, and attribute modifications
to \fIname\fP, except for changing the
to \fIname\fP, except those using or changing the
\fB\-n\fP attribute itself, are performed on the variable referenced by
\fIname\fP's value.
The nameref attribute cannot be applied to array variables.
+3 -2
View File
@@ -1518,7 +1518,8 @@ A variable can be assigned the @var{nameref} attribute using the
to create a @var{nameref}, or a reference to another variable.
This allows variables to be manipulated indirectly.
Whenever the nameref variable is referenced, assigned to, unset, or has
its attributes modified (other than the nameref attribute itself), the
its attributes modified (other than using or changing the nameref
attribute itself), the
operation is actually performed on the variable specified by the nameref
variable's value.
A nameref is commonly used within shell functions to refer to a variable
@@ -4052,7 +4053,7 @@ Give each @var{name} the @var{nameref} attribute, making
it a name reference to another variable.
That other variable is defined by the value of @var{name}.
All references, assignments, and attribute modifications
to @var{name}, except for changing the
to @var{name}, except for those using or changing the
@option{-n} attribute itself, are performed on the variable referenced by
@var{name}'s value.
The nameref attribute cannot be applied to array variables.
+3 -3
View File
@@ -2,10 +2,10 @@
Copyright (C) 1988-2016 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Wed Apr 27 09:19:38 EDT 2016
@set LASTCHANGE Sun May 29 13:48:02 EDT 2016
@set EDITION 4.4
@set VERSION 4.4
@set UPDATED 27 April 2016
@set UPDATED-MONTH April 2016
@set UPDATED 29 May 2016
@set UPDATED-MONTH May 2016
+32 -30
View File
@@ -1389,6 +1389,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
int current_invis_chars;
int col_lendiff, col_temp;
int bytes_to_insert;
int mb_cur_max = MB_CUR_MAX;
#if defined (HANDLE_MULTIBYTE)
mbstate_t ps_new, ps_old;
int new_offset, old_offset;
@@ -1399,7 +1400,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
the exact cursor position and cut-and-paste with certain terminal
emulators. In this calculation, TEMP is the physical screen
position of the cursor. */
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
temp = _rl_last_c_pos;
else
temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
@@ -1407,7 +1408,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
&& _rl_last_v_pos == current_line - 1)
{
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
wchar_t wc;
mbstate_t ps;
@@ -1421,7 +1422,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
_rl_clear_to_eol (line_state_visible->wrapped_line[current_line]);
memset (&ps, 0, sizeof (mbstate_t));
ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
ret = mbrtowc (&wc, new, mb_cur_max, &ps);
if (MB_INVALIDCH (ret))
{
tempwidth = 1;
@@ -1441,7 +1442,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
_rl_last_c_pos = tempwidth;
_rl_last_v_pos++;
memset (&ps, 0, sizeof (mbstate_t));
ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
ret = mbrtowc (&wc, old, mb_cur_max, &ps);
if (ret != 0 && bytes != 0)
{
if (MB_INVALIDCH (ret))
@@ -1480,7 +1481,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
/* Find first difference. */
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
/* See if the old line is a subset of the new line, so that the
only change is adding characters. */
@@ -1537,7 +1538,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
return;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
if (mb_cur_max > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
{
wchar_t wc;
mbstate_t ps = { 0 };
@@ -1546,7 +1547,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
/* If the first character in the difference is a zero-width character,
assume it's a combining character and back one up so the two base
characters no longer compare equivalently. */
t = mbrtowc (&wc, ofd, MB_CUR_MAX, &ps);
t = mbrtowc (&wc, ofd, mb_cur_max, &ps);
if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
{
old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
@@ -1560,7 +1561,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
wsatend = 1; /* flag for trailing whitespace */
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
@@ -1618,14 +1619,14 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
{
if (*ols) /* don't step past the NUL */
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
else
ols++;
}
if (*nls)
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
else
nls++;
@@ -1642,7 +1643,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
visible_wrap_offset based on what we know. */
if (current_line == 0)
visible_wrap_offset = prompt_invis_chars_first_line; /* XXX */
if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
if ((mb_cur_max == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
_rl_last_c_pos += visible_wrap_offset;
}
@@ -1687,7 +1688,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
if (modmark)
_rl_output_some_chars ("*", 1);
_rl_output_some_chars (local_prompt, lendiff);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
/* We take wrap_offset into account here so we can pass correct
information to _rl_move_cursor_relative. */
@@ -1723,7 +1724,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
if (temp > 0)
{
_rl_output_some_chars (nfd, temp);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
_rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1);
else
_rl_last_c_pos += temp;
@@ -1746,7 +1747,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
/* We need to indicate that the cursor position is correct in the presence of
invisible characters in the prompt string. Let's see if setting this when
we make sure we're at the end of the drawn prompt string works. */
if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 &&
if (current_line == 0 && mb_cur_max > 1 && rl_byte_oriented == 0 &&
(_rl_last_c_pos > 0 || o_cpos > 0) &&
_rl_last_c_pos == prompt_physical_chars)
cpos_adjusted = 1;
@@ -1757,7 +1758,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
col_lendiff == difference on screen (columns)
When not using multibyte characters, these are equal */
lendiff = (nls - nfd) - (ols - ofd);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1);
else
col_lendiff = lendiff;
@@ -1768,7 +1769,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
if (current_line == 0 && /* !_rl_horizontal_scroll_mode && */
current_invis_chars != visible_wrap_offset)
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
lendiff += visible_wrap_offset - current_invis_chars;
col_lendiff += visible_wrap_offset - current_invis_chars;
@@ -1786,7 +1787,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
and writes TEMP bytes. */
/* Insert (diff (len (old), len (new)) ch. */
temp = ne - nfd;
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
else
col_temp = temp;
@@ -1837,7 +1838,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
_rl_last_c_pos == 0 &&
lendiff > prompt_visible_length &&
current_invis_chars > 0) == 0) &&
(((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
(((mb_cur_max > 1 && rl_byte_oriented == 0) &&
current_line == 0 && wrap_offset &&
((nfd - new) <= prompt_last_invisible) &&
(col_lendiff < prompt_visible_length)) == 0) &&
@@ -1845,12 +1846,12 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
{
open_some_spaces (col_lendiff);
_rl_output_some_chars (nfd, bytes_to_insert);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
_rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
else
_rl_last_c_pos += bytes_to_insert;
}
else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
else if ((mb_cur_max == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
{
/* At the end of a line the characters do not have to
be "inserted". They can just be placed on the screen. */
@@ -1865,7 +1866,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
/* If nfd begins before the last invisible character in the
prompt, adjust _rl_last_c_pos to account for wrap_offset
and set cpos_adjusted to let the caller know. */
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
{
_rl_last_c_pos -= wrap_offset;
cpos_adjusted = 1;
@@ -1878,7 +1879,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
/* If nfd begins before the last invisible character in the
prompt, adjust _rl_last_c_pos to account for wrap_offset
and set cpos_adjusted to let the caller know. */
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
{
_rl_last_c_pos -= wrap_offset;
cpos_adjusted = 1;
@@ -1898,7 +1899,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
crude attempt to compute how far into the new line buffer we are.
It doesn't work well in the face of multibyte characters and needs
to be rethought. XXX */
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
current_line == prompt_last_screen_line && wrap_offset &&
displaying_prompt_first_line &&
wrap_offset != prompt_invis_chars_first_line &&
@@ -1942,7 +1943,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
in a multibyte locale to account for the wrap offset and
set cpos_adjusted accordingly. */
_rl_output_some_chars (nfd, bytes_to_insert);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
_rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
if (current_line == 0 && wrap_offset &&
@@ -1977,7 +1978,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
set cpos_adjusted accordingly. */
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += col_temp; /* XXX */
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
if (current_line == 0 && wrap_offset &&
displaying_prompt_first_line &&
@@ -1991,7 +1992,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
}
clear_rest_of_line:
lendiff = (oe - old) - (ne - new);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
else
col_lendiff = lendiff;
@@ -2001,7 +2002,7 @@ clear_rest_of_line:
space_to_eol will insert too many spaces. XXX - maybe we should
adjust col_lendiff based on the difference between _rl_last_c_pos
and _rl_screenwidth */
if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
if (col_lendiff && ((mb_cur_max == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
{
if (_rl_term_autowrap && current_line < inv_botlin)
space_to_eol (col_lendiff);
@@ -2161,6 +2162,7 @@ _rl_move_cursor_relative (new, data)
int cpos, dpos; /* current and desired cursor positions */
int adjust;
int in_invisline;
int mb_cur_max = MB_CUR_MAX;
woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
cpos = _rl_last_c_pos;
@@ -2174,7 +2176,7 @@ _rl_move_cursor_relative (new, data)
this case, NEW's display position is not obvious and must be
calculated. We need to account for invisible characters in this line,
as long as we are past them and they are counted by _rl_col_width. */
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
adjust = 1;
/* Try to short-circuit common cases and eliminate a bunch of multibyte
@@ -2242,7 +2244,7 @@ _rl_move_cursor_relative (new, data)
of moving backwards. */
/* i == current physical cursor position. */
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
i = _rl_last_c_pos;
else
#endif
@@ -2277,7 +2279,7 @@ _rl_move_cursor_relative (new, data)
in the buffer and we have to go back to the beginning of the screen
line. In this case, we can use the terminal sequence to move forward
if it's available. */
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
if (mb_cur_max > 1 && rl_byte_oriented == 0)
{
if (_rl_term_forward_char)
{
+91 -2
View File
@@ -27,7 +27,7 @@ changevar: expect <three four five>
argv[1] = <three four five>
expect <three four five>
argv[1] = <three four five>
./nameref.tests: line 93: bar: readonly variable
./nameref.tests: line 93: foo: readonly variable
./nameref.tests: line 94: foo: readonly variable
one
one
@@ -111,6 +111,7 @@ ref -> two, value: 2
ref -> three, value: 3
final state: ref -> three, value: 3
./nameref6.sub: line 2: typeset: x: nameref variable self references not allowed
./nameref6.sub: line 5: typeset: x[3]: reference variable cannot be an array
./nameref6.sub: line 12: typeset: x: reference variable cannot be an array
the -- 1
42 -- 0
@@ -120,10 +121,19 @@ y -- 0
y -- 0
bar
unset
./nameref8.sub: line 3: typeset: warning: v: circular name reference
./nameref8.sub: line 3: warning: v: circular name reference
./nameref8.sub: line 5: warning: v: circular name reference
inside
inside: two
outside:
./nameref8.sub: line 29: typeset: warning: x: circular name reference
./nameref8.sub: line 29: warning: x: circular name reference
./nameref8.sub: line 31: warning: x: circular name reference
foo
./nameref8.sub: line 38: typeset: warning: v: circular name reference
./nameref8.sub: line 38: warning: v: circular name reference
./nameref8.sub: line 38: warning: v: circular name reference
local
./nameref8.sub: line 47: typeset: v: nameref variable self references not allowed
./nameref8.sub: line 54: warning: x: circular name reference
@@ -214,7 +224,7 @@ declare -r RO_PID
./nameref11.sub: line 39: RO: cannot unset: readonly variable
declare -r RO="x"
./nameref11.sub: line 39: declare: RO_PID: not found
./nameref11.sub: line 41: ref_PID: readonly variable
./nameref11.sub: line 41: RO2: readonly variable
declare -r RO2="a"
./nameref12.sub: line 6: declare: `/': invalid variable name for name reference
./nameref12.sub: line 9: declare: `%': invalid variable name for name reference
@@ -280,3 +290,82 @@ after
declare -n ref="var"
./nameref14.sub: line 32: typeset: var: not found
declare -n ref="var"
./nameref15.sub: line 1: local: warning: a: circular name reference
./nameref15.sub: line 1: `a[0]': not a valid identifier
declare -a a=([0]="0")
./nameref15.sub: line 1: local: warning: a: circular name reference
./nameref15.sub: line 1: warning: a: circular name reference
./nameref15.sub: line 1: warning: a: circular name reference
declare -a a=([0]="X")
declare -a b=([0]="X")
./nameref15.sub: line 1: local: warning: a: circular name reference
./nameref15.sub: line 1: `a[0]': not a valid identifier
declare -a b=([0]="0")
./nameref15.sub: line 19: typeset: warning: ref: circular name reference
./nameref15.sub: line 19: warning: ref: circular name reference
./nameref15.sub: line 20: warning: ref: circular name reference
./nameref15.sub: line 21: warning: ref: circular name reference
inside
outside X
./nameref15.sub: line 29: typeset: ref: nameref variable self references not allowed
./nameref15.sub: line 31: ref: nameref variable self references not allowed
./nameref15.sub: line 32: typeset: ref: not found
declare -- ref="4"
4
declare -n foo="var[@]"
declare -n ref="var[@]"
./nameref15.sub: line 47: var[@]: bad array subscript
declare -n bar="var[@]"
./nameref15.sub: line 52: var[@]: bad array subscript
declare -n r1="y"
declare -n r2="x"
./nameref16.sub: line 12: typeset: x: not found
./nameref16.sub: line 12: typeset: y: not found
declare -n r1="y"
declare -n r2="x"
./nameref16.sub: line 21: typeset: x: not found
./nameref16.sub: line 21: typeset: y: not found
declare -n r1="y"
declare -n r2="x"
./nameref16.sub: line 33: typeset: x: not found
./nameref16.sub: line 33: typeset: y: not found
declare -n r1="y"
declare -n r2="x"
declare -- x="one"
declare -- y="two"
./nameref17.sub: line 8: declare: bar: not found
./nameref17.sub: line 9: unset: foo0: cannot unset: readonly variable
declare -nr foo0="bar"
declare -nr foo0="bar"
declare -- bar
./nameref17.sub: line 14: declare: foo0: readonly variable
./nameref17.sub: line 15: declare: foo0: readonly variable
declare -nr foo1
./nameref17.sub: line 24: typeset: foo1: readonly variable
declare -nr foo1
declare -n foo2="bar"
declare -r bar
./nameref17.sub: line 35: bar: readonly variable
./nameref17.sub: line 36: typeset: bar: readonly variable
declare -n foo2="bar"
declare -r bar
declare -- bar3="three"
./nameref17.sub: line 46: unset: foo3: cannot unset: readonly variable
./nameref17.sub: line 49: declare: bar3: readonly variable
declare -nr foo3="bar3"
declare -r bar3="three"
./nameref17.sub: line 51: declare: foo3: readonly variable
declare -nr foo4="bar4"
declare -- bar4="four"
./nameref17.sub: line 63: typeset: foo4: readonly variable
declare -nr foo4="bar4"
declare -nr foo4="bar4"
declare -- bar4="four"
./nameref17.sub: line 79: typeset: foo4: readonly variable
declare -nr foo4="bar4"
declare -nr foo4="bar4"
declare -- bar4="four"
declare -nr foo5
declare -r foo5
declare -nr foo5
declare -r foo5
+3
View File
@@ -129,3 +129,6 @@ ${THIS_SH} ./nameref11.sub
${THIS_SH} ./nameref12.sub
${THIS_SH} ./nameref13.sub
${THIS_SH} ./nameref14.sub
${THIS_SH} ./nameref15.sub
${THIS_SH} ./nameref16.sub
${THIS_SH} ./nameref17.sub
+52
View File
@@ -0,0 +1,52 @@
f() { local -n a=$1; a=X; }
a=(0); f 'a[0]'
while [[ -v a ]]; do declare -p a; unset a; done
a=(0); f 'a'
while [[ -v a ]]; do declare -p a; unset a; done
b=(0); f 'b[0]'
while [[ -v a ]]; do typeset -p a; unset a; done
typeset -p b
b=(0); f 'a[0]'
while [[ -v a ]]; do typeset -p a; unset a; done
typeset -p b
add_X_echo()
{
typeset -n ref=$1
ref+=X
echo inside $ref
}
ref=
add_X_echo ref
echo outside "$ref"
unset ref
typeset -n ref=ref
typeset -n ref=re ref+=f
typeset -p ref
ref=4
typeset -p ref
export ref
printenv ref
unset ref ; unset -n ref
unset foo; unset -n foo
typeset -n foo=var[@]
typeset -p foo
typeset -n ref=var ref+=[@]
typeset -p ref
ref=42
typeset -n bar
bar=var[@]
typeset -p bar
bar=7
+44
View File
@@ -0,0 +1,44 @@
# post-bash-4.3 changes for more ksh93 compatibility when following nameref
# chains and using typeset/declare -n to operate on nameref variables rather
# than the variables they reference
# don't follow nameref chain when using declare -n and at the global scope
unset -n r1 r2
typeset -n r1=r2
typeset -n r2=x
typeset -n r1=y
typeset -p r1 r2 x y
# same behavior when in a shell function
foo()
{
typeset -n r1=r2
typeset -n r2=x
typeset -n r1=y
typeset -p r1 r2 x y
}
unset -n r1 r2
foo
unset -f foo
# same behavior when namerefs aren't chained
unset -n r1 r2
typeset -n r1=z
typeset -n r2=x
typeset -n r1=y
typeset -p r1 r2 x y
# same behavior when referenced variables have values
unset -n r1 r2
x=one
y=two
typeset -n r1=r2
typeset -n r2=x
typeset -n r1=y
typeset -p r1 r2 x y
+103
View File
@@ -0,0 +1,103 @@
# test behavior of readonly namerefs and namerefs referencing readonly variables
# readonly nameref variable referencing read-write global variable
bar=one
declare -rn foo0=bar
unset foo0 # unsets bar
declare -p bar
unset -n foo0 # cannot unset
declare -p foo0
declare +r foo0 # modifies bar
declare -p foo0 bar
declare +r -n foo0 # error
declare +n foo0 # error
unset bar
# readonly nameref variable without a value
typeset -n foo1
typeset -r foo1
typeset -p foo1
typeset foo1=bar # error
typeset +r foo1 # no-op, follows nameref chain to nothing
typeset -p foo1
# nameref pointing to read-only global variable
foo2=bar
typeset -n foo2
typeset -r foo2 # changes bar
typeset -p foo2 bar
foo2=bar # error?
typeset +r foo2 # attempts to change bar, error
typeset -p foo2 bar # nameref unchanged
# read-only nameref pointing to read-only global variable
bar3=three
declare -rn foo3=bar3
unset foo3 # unsets bar3
bar3=three
declare -p bar3
unset -n foo3 # cannot unset
readonly bar3
declare +r foo3 # error attempting to reference bar3
declare -p foo3 bar3
declare +r -n foo3 # error
# readonly nameref pointing to read-write local -- can we remove nameref attr?
func()
{
typeset bar4=four
# readonly nameref
typeset -n -r foo4=bar4
typeset -p foo4 bar4
typeset +n foo4
typeset -p foo4
}
func
unset -f func
# readonly nameref pointing to read-write global -- can we remove nameref attr?
bar4=four
foo4=bar4
# readonly nameref
typeset -n foo4
typeset -r -n foo4
typeset -p foo4 bar4
typeset +n foo4
typeset -p foo4
bar4=four
: ${foo4=bar4}
typeset -p foo4 bar4
# readonly local nameref without a value -- can we remove nameref attribute?
func()
{
declare -r -n foo5
declare -p foo5
declare +n foo5
declare -p foo5
}
func
unset -f func
# readonly global nameref without a value -- can we remove nameref attribute?
declare -n foo5
declare -r -n foo5
declare -p foo5
declare +n foo5
declare -p foo5
+19 -4
View File
@@ -283,6 +283,8 @@ static int variable_in_context __P((SHELL_VAR *));
static int visible_array_vars __P((SHELL_VAR *));
#endif
static SHELL_VAR *find_variable_internal __P((const char *, int));
static SHELL_VAR *find_nameref_at_context __P((SHELL_VAR *, VAR_CONTEXT *));
static SHELL_VAR *find_variable_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **));
static SHELL_VAR *find_variable_last_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **));
@@ -2767,7 +2769,7 @@ assign_value:
if ((readonly_p (entry) && (aflags & ASS_FORCE) == 0) || noassign_p (entry))
{
if (readonly_p (entry))
err_readonly (name);
err_readonly (name_cell (entry));
return (entry);
}
@@ -2875,7 +2877,7 @@ bind_variable (name, value, flags)
#if 0
return (bind_variable_value (v, value, flags|ASS_NAMEREF));
#else
return (bind_variable_internal (v->name, value, nvc->table, 0, flags));
v = 0; /* backwards compat */
#endif
}
else
@@ -2887,7 +2889,7 @@ bind_variable (name, value, flags)
#if 0
return (bind_variable_value (v, value, flags|ASS_NAMEREF));
#else
return (bind_variable_internal (v->name, value, nvc->table, 0, flags));
v = 0; /* backwards compat */
#endif
}
else
@@ -2947,7 +2949,20 @@ bind_variable_value (var, value, aflags)
else
{
t = make_variable_value (var, value, aflags);
if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || valid_nameref_value (t, 0) == 0))
if (STREQ (name_cell (var), t))
{
if (variable_context)
internal_warning (_("%s: circular name reference"), name_cell (var));
else
{
internal_error (_("%s: nameref variable self references not allowed"), name_cell (var));
free (t);
if (invis)
VSETATTR (var, att_invisible); /* XXX */
return ((SHELL_VAR *)NULL);
}
}
if ((aflags & ASS_NAMEREF) && (valid_nameref_value (t, 0) == 0))
{
free (t);
if (invis)
+1 -1
View File
@@ -255,7 +255,7 @@ extern SHELL_VAR *find_global_variable_last_nameref __P((const char *, int));
extern SHELL_VAR *find_variable_nameref __P((SHELL_VAR *));
extern SHELL_VAR *find_variable_nameref_for_create __P((const char *, int));
extern SHELL_VAR *find_variable_nameref_for_assignment __P((const char *, int));
extern SHELL_VAR *find_variable_internal __P((const char *, int));
/*extern SHELL_VAR *find_variable_internal __P((const char *, int));*/
extern SHELL_VAR *find_variable_tempenv __P((const char *));
extern SHELL_VAR *find_variable_notempenv __P((const char *));
extern SHELL_VAR *find_global_variable __P((const char *));