mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
check for delimiter_depth being 0 before popping off the stack (reset_parser resets it); make EOFs while reading here-doc delimiters sticky; when reading arith command, push back a character after the first closing paren that isn't a second close paren to fix backslash issue
This commit is contained in:
@@ -11151,3 +11151,38 @@ builtins/read.def
|
||||
only push the delimiter back if we read that character ourselves
|
||||
(i > 1).
|
||||
Report from Greg Wooledge <greg@wooledge.org>
|
||||
|
||||
4/23
|
||||
----
|
||||
parse.y
|
||||
- pop_delimiter: only decrement delimiter_depth if it's > 0, since
|
||||
reset_parser() may have set it to 0 after the matching call to
|
||||
push_delimiter
|
||||
Report from Grisha Levit <grishalevit@gmail.com> based on a report
|
||||
from Александр Ушаков <aushakov@astralinux.ru>
|
||||
|
||||
4/25
|
||||
----
|
||||
parse.y
|
||||
- read_a_line: if the shell is interactive, and not reading from a
|
||||
string, check whether a previous call to shell_getc has set
|
||||
EOF_Reached and return EOF in this case, after resetting the
|
||||
current token to '\n'. This makes EOFs that are not the first
|
||||
character on the line `sticky' instead of just token delimiters.
|
||||
From https://savannah.gnu.org/bugs/?67045
|
||||
- history_delimiting_chars: if it looks like we just finished a
|
||||
subshell, and the line we're adding begins with an operator that
|
||||
can't follow a semicolon, return a newline
|
||||
From https://savannah.gnu.org/patch/?10517
|
||||
|
||||
4/28
|
||||
----
|
||||
parse.y
|
||||
- parse_arith_command: if the character after the first right paren
|
||||
isn't a right paren, making the construct a nested subshell, push
|
||||
that character back and return the subshell command as the current
|
||||
token string, which we push onto the pushed string list. Reading
|
||||
one character more can cause synchronization problems with backslash
|
||||
newline, among other things.
|
||||
From https://savannah.gnu.org/patch/?10517
|
||||
|
||||
|
||||
@@ -2214,7 +2214,15 @@ read_a_line (int remove_quoted_newline)
|
||||
QUIT;
|
||||
|
||||
/* If we're reading the here-document from an alias, use shell_getc */
|
||||
c = heredoc_string ? shell_getc (0) : yy_getc ();
|
||||
if (interactive && EOF_Reached && heredoc_string == 0)
|
||||
{
|
||||
c = EOF;
|
||||
EOF_Reached = 0;
|
||||
if (current_token == yacc_EOF)
|
||||
current_token = '\n'; /* reset state */
|
||||
}
|
||||
else
|
||||
c = heredoc_string ? shell_getc (0) : yy_getc ();
|
||||
|
||||
/* Ignore null bytes in input. */
|
||||
if (c == 0)
|
||||
@@ -2451,7 +2459,10 @@ static struct dstack temp_dstack = { (char *)NULL, 0, 0 };
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define pop_delimiter(ds) ds.delimiter_depth--
|
||||
/* The parsing or expansion code may have called reset_parser() between the
|
||||
time push_delimiter was called and this call to pop_delimiter, which resets
|
||||
delimiter_depth to 0, so we check. */
|
||||
#define pop_delimiter(ds) do { if (ds.delimiter_depth > 0) ds.delimiter_depth--; } while (0)
|
||||
|
||||
/* Return the next shell input character. This always reads characters
|
||||
from shell_input_line; when that line is exhausted, it is time to
|
||||
@@ -4983,11 +4994,12 @@ parse_arith_cmd (char **ep, int adddq)
|
||||
}
|
||||
else /* nested subshell */
|
||||
{
|
||||
shell_ungetc (c);
|
||||
|
||||
tokstr[0] = '(';
|
||||
strncpy (tokstr + 1, ttok, ttoklen - 1);
|
||||
tokstr[ttoklen] = ')';
|
||||
tokstr[ttoklen+1] = c;
|
||||
tokstr[ttoklen+2] = '\0';
|
||||
tokstr[ttoklen+1] = '\0';
|
||||
}
|
||||
|
||||
*ep = tokstr;
|
||||
@@ -5990,6 +6002,10 @@ static const int no_semi_successors[] = {
|
||||
0
|
||||
};
|
||||
|
||||
static const int no_semi_predecessors[] = {
|
||||
'&', '|', ';', 0
|
||||
};
|
||||
|
||||
/* If we are not within a delimited expression, try to be smart
|
||||
about which separators can be semi-colons and which must be
|
||||
newlines. Returns the string that should be added into the
|
||||
@@ -5999,6 +6015,7 @@ char *
|
||||
history_delimiting_chars (const char *line)
|
||||
{
|
||||
static int last_was_heredoc = 0; /* was the last entry the start of a here document? */
|
||||
const char *lp;
|
||||
register int i;
|
||||
|
||||
if ((parser_state & PST_HEREDOC) == 0)
|
||||
@@ -6045,6 +6062,9 @@ history_delimiting_chars (const char *line)
|
||||
if (parser_state & PST_COMPASSIGN)
|
||||
return (" ");
|
||||
|
||||
for (lp = line; *lp && shellblank(*lp); lp++)
|
||||
;
|
||||
|
||||
/* First, handle some special cases. */
|
||||
/*(*/
|
||||
/* If we just read `()', assume it's a function definition, and don't
|
||||
@@ -6061,7 +6081,15 @@ history_delimiting_chars (const char *line)
|
||||
else if (parser_state & PST_CASESTMT) /* case statement pattern */
|
||||
return " ";
|
||||
else
|
||||
return "; "; /* (...) subshell */
|
||||
{
|
||||
/* (...) subshell. Make sure this line doesn't start with an
|
||||
operator that cannot be preceded by a semicolon. If it can't
|
||||
(basically the command terminators), return a newline. */
|
||||
for (i = 0; no_semi_predecessors[i]; i++)
|
||||
if (*lp == no_semi_predecessors[i])
|
||||
return "\n";
|
||||
return "; ";
|
||||
}
|
||||
}
|
||||
else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
|
||||
return " "; /* function def using `function name' without `()' */
|
||||
|
||||
@@ -52,11 +52,6 @@ a = abc
|
||||
<$'spring\375'>
|
||||
<summer>
|
||||
<automn>
|
||||
<winter>
|
||||
<$'spring\375'>
|
||||
<$'\277summer'>
|
||||
<$'\277'>
|
||||
<automn>
|
||||
timeout 1: ok
|
||||
unset or null 1
|
||||
timeout 2: ok
|
||||
|
||||
+11
-9
@@ -44,14 +44,16 @@ printf '%b\0' winter spring 'summer\0200apple\0200banana\0200cherry' automn |
|
||||
printf '%b\200' winter 'spring\0375' summer automn |
|
||||
while IFS= read -rd $'\200' season; do LC_ALL=C printf "<%q>\n" "$season"; done
|
||||
|
||||
: ${TMPDIR:=/tmp}
|
||||
INFILE=$TMPDIR/read-in-$$
|
||||
printf '%b\243' winter 'spring\0375' '\0277summer' '\0277' automn > $INFILE
|
||||
# this test is encoding-dependent, and varies from system to system
|
||||
#: ${TMPDIR:=/tmp}
|
||||
#INFILE=$TMPDIR/read-in-$$
|
||||
#printf '%b\243' winter 'spring\0375' '\0277summer' '\0277' automn > $INFILE
|
||||
#
|
||||
#LANG=zh_HK.big5hkscs
|
||||
#while IFS= read -rd $'\243' season; do
|
||||
# LC_ALL=C printf "<%q>\n" "$season"
|
||||
#done < $INFILE
|
||||
#
|
||||
#rm -f $INFILE
|
||||
|
||||
LANG=zh_HK.big5hkscs
|
||||
while IFS= read -rd $'\243' season; do
|
||||
LC_ALL=C printf "<%q>\n" "$season"
|
||||
done < $INFILE
|
||||
|
||||
rm -f $INFILE
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user