commit bash-20210215 snapshot

This commit is contained in:
Chet Ramey
2021-02-17 15:31:03 -05:00
parent a6c3a43f43
commit a7309caba4
13 changed files with 1769 additions and 1352 deletions
+30
View File
@@ -9604,3 +9604,33 @@ lib/readline/text.c
bashline.c
- posix_edit_macros: handle rl_read_key() returning <= 0
2/15
----
parse.y
- read_comsub: make sure to turn on the LEX_RESWDOK flag if we are in
a case statement and read a `)', since we can get a valid `esac'.
Fixes bug reported by Oguz <oguzismailuysal@gmail.com>
- read_comsub: if we're in a case statement, recognize `}' as a
reserved word and set the LEX_RESWDOK flag for the next word, since
we can get an esac (or another reserved word) after it
2/16
----
parse.y
- reserved_word_acceptable: add ARITH_CMD and COND_END to the list of
tokens that can precede a reserved word, so you can use reserved
words after ((...)) and [[...]].
Reported by Koichi Murase <myoga.murase@gmail.com>
2/17
----
parse.y
- parse_comsub: use new LEX_CASEWD flag to track when we are reading
the WORD in `case WORD in' and turn on the LEX_RESWDOK flag when
that word ends. This allows $(case x in esac), which no one uses.
- parse_comsub: use LEX_PATLIST flag to track when we are reading a
case pattern list so `|' doesn't turn on the LES_RESWDOK flag
- parse_comsub: case_level: simple counter to count the number of esacs
we need to see before we're no longer in a case statement; analog of
esacs_needed_count from the lexer
+1
View File
@@ -988,6 +988,7 @@ tests/comsub-posix.right f
tests/comsub-posix1.sub f
tests/comsub-posix2.sub f
tests/comsub-posix3.sub f
tests/comsub-posix5.sub f
tests/cond.tests f
tests/cond.right f
tests/cond-regexp1.sub f
+106 -16
View File
@@ -1,6 +1,6 @@
/* parse.y - Yacc grammar for bash. */
/* Copyright (C) 1989-2020 Free Software Foundation, Inc.
/* Copyright (C) 1989-2021 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -3517,6 +3517,9 @@ tokword:
#define LEX_QUOTEDDOC 0x0400 /* here doc with quoted delim */
#define LEX_INWORD 0x0800
#define LEX_GTLT 0x1000
#define LEX_CKESAC 0x2000 /* check esac after in -- for later */
#define LEX_CASEWD 0x4000 /* word after case */
#define LEX_PATLIST 0x8000 /* case statement pattern list */
#define COMSUB_META(ch) ((ch) == ';' || (ch) == '&' || (ch) == '|')
@@ -3861,11 +3864,26 @@ dump_tflags (flags)
f &= ~LEX_CKCASE;
fprintf (stderr, "LEX_CKCASE%s", f ? "|" : "");
}
if (f & LEX_CKESAC)
{
f &= ~LEX_CKESAC;
fprintf (stderr, "LEX_CKESAC%s", f ? "|" : "");
}
if (f & LEX_INCASE)
{
f &= ~LEX_INCASE;
fprintf (stderr, "LEX_INCASE%s", f ? "|" : "");
}
if (f & LEX_CASEWD)
{
f &= ~LEX_CASEWD;
fprintf (stderr, "LEX_CASEWD%s", f ? "|" : "");
}
if (f & LEX_PATLIST)
{
f &= ~LEX_PATLIST;
fprintf (stderr, "LEX_PATLIST%s", f ? "|" : "");
}
if (f & LEX_INHEREDOC)
{
f &= ~LEX_INHEREDOC;
@@ -3906,7 +3924,7 @@ parse_comsub (qc, open, close, lenp, flags)
int *lenp, flags;
{
int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
int nestlen, ttranslen, start_lineno, orig_histexp;
int nestlen, ttranslen, start_lineno, orig_histexp, case_level;
char *ret, *nestret, *ttrans, *heredelim;
int retind, retsize, rflags, hdlen;
@@ -3932,7 +3950,7 @@ parse_comsub (qc, open, close, lenp, flags)
/* RFLAGS is the set of flags we want to pass to recursive calls. */
rflags = (flags & P_DQUOTE);
ret = (char *)xmalloc (retsize = 64);
ret = (char *)xmalloc (retsize = 128);
retind = 0;
start_lineno = line_number;
@@ -3941,6 +3959,8 @@ parse_comsub (qc, open, close, lenp, flags)
heredelim = 0;
lex_firstind = -1;
case_level = 0;
while (count)
{
comsub_readchar:
@@ -4092,6 +4112,13 @@ eof_error:
we either start or continue a word. */
if MBTEST(shellbreak (ch))
{
if (tflags & LEX_CASEWD) /* word in case WORD in */
{
/*itrace("parse_comsub:%d: lex_inword -> 0 lex_casewd -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
tflags &= ~LEX_CASEWD;
tflags |= LEX_RESWDOK; /* allow "in" next */
lex_rwlen = 0;
}
tflags &= ~LEX_INWORD;
/*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
}
@@ -4183,6 +4210,13 @@ eof_error:
/*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/
tflags |= LEX_RESWDOK;
lex_rwlen = 0;
if ((tflags & LEX_INCASE) && ch == ';')
tflags |= LEX_PATLIST;
continue;
}
else if ((tflags & LEX_PATLIST) && ch == '|')
{
shell_ungetc (peekc);
continue;
}
else if (ch == '\n' || COMSUB_META(ch))
@@ -4193,6 +4227,16 @@ eof_error:
lex_rwlen = 0;
continue;
}
/* If we read a right paren, we can get esac here, so make a note. ( */
else if MBTEST((tflags & LEX_INCASE) && ch == ')')
{
shell_ungetc (peekc);
/*itrace("parse_comsub:%d: found `)' while in case statement, turning on LEX_RESWDOK", line_number);*/
tflags |= LEX_RESWDOK;
lex_rwlen = 0;
tflags &= ~LEX_PATLIST;
continue;
}
else if (ch == EOF)
goto eof_error;
else
@@ -4203,10 +4247,23 @@ eof_error:
}
}
/* If we're checking for esac and it looks like we might have one, try
to read one. */
/* XXX - check LEX_PATLIST here? */
else if ((tflags & LEX_INCASE) && (tflags & LEX_CKESAC))
{
if MBTEST(ch == 'e' && (tflags & LEX_RESWDOK) == 0)
{
tflags |= LEX_RESWDOK;
lex_rwlen = 0;
}
tflags &= ~LEX_CKESAC;
}
/* If we can read a reserved word, try to read one. */
if (tflags & LEX_RESWDOK)
{
if MBTEST(islower ((unsigned char)ch))
if MBTEST(islower ((unsigned char)ch) || ch == '{' || ch == '}')
{
/* Add this character. */
RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
@@ -4218,14 +4275,17 @@ eof_error:
{
if (STREQN (ret + retind - 4, "case", 4))
{
tflags |= LEX_INCASE;
tflags |= LEX_INCASE|LEX_CASEWD;
case_level++;
tflags &= ~LEX_RESWDOK;
/*itrace("parse_comsub:%d: found `case', lex_incase -> 1 lex_reswdok -> 0", line_number);*/
}
else if (STREQN (ret + retind - 4, "esac", 4))
{
tflags &= ~LEX_INCASE;
/*itrace("parse_comsub:%d: found `esac', lex_incase -> 0 lex_reswdok -> 1", line_number);*/
case_level--;
if (case_level == 0)
tflags &= ~(LEX_INCASE|LEX_PATLIST);
/*itrace("parse_comsub:%d: found `esac', lex_incase -> 0 lex_reswdok -> 1 case_level = %d", line_number, case_level);*/
tflags |= LEX_RESWDOK;
lex_rwlen = 0;
}
@@ -4263,6 +4323,43 @@ eof_error:
/*itrace("parse_comsub:%d: lex_incase == 0 found `%c', found \"do\"", line_number, ch);*/
lex_rwlen = 0;
}
/* { */
else if MBTEST((tflags & LEX_INCASE) &&
(isblank((unsigned char)ch) || ch == '\n') &&
lex_rwlen == 1 &&
ret[retind - 1] == '}')
{ /* { */
/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', found \"}\"", line_number, ch);*/
lex_rwlen = 0;
}
else if MBTEST((tflags & LEX_INCASE) &&
(isblank((unsigned char)ch) || ch == '\n') &&
lex_rwlen == 2 &&
STREQN (ret + retind - 2, "fi", 2))
{
/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', found \"fi\"", line_number, ch);*/
lex_rwlen = 0;
}
else if MBTEST((tflags & LEX_INCASE) &&
(isblank((unsigned char)ch) || ch == '\n') &&
lex_rwlen == 2 &&
STREQN (ret + retind - 2, "in", 2))
{
/* This works because we turn on the RESWDOK flag after reading
WORD in `case WORD in'. */
/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', found \"in\"", line_number, ch);*/
tflags &= ~LEX_RESWDOK;
tflags |= LEX_CKESAC|LEX_PATLIST;
}
/* If we are in a case statement and we read a right paren, we leave
LEX_RESWDOK alone but set rwlen to 0 so we can potentially read
another reserved word. ( */
else if MBTEST((tflags & LEX_INCASE) && ch == ')')
{
tflags |= LEX_RESWDOK;
tflags &= ~LEX_PATLIST;
lex_rwlen = 0;
}
else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
/* If we can read a reserved word and we're in case, we're at the
point where we can read a new pattern list or an esac. We
@@ -4278,15 +4375,6 @@ eof_error:
tflags &= ~LEX_RESWDOK;
/*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
}
#if 0
/* If we find a space or tab but have read something and it's not
`do', turn off the reserved-word-ok flag */
else if MBTEST(isblank ((unsigned char)ch) && lex_rwlen > 0)
{
tflags &= ~LEX_RESWDOK;
/*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
}
#endif
}
/* Might be the start of a here-doc delimiter */
@@ -5473,8 +5561,10 @@ reserved_word_acceptable (toksym)
case '{':
case '}': /* XXX */
case AND_AND:
case ARITH_CMD:
case BANG:
case BAR_AND:
case COND_END:
case DO:
case DONE:
case ELIF:
BIN
View File
Binary file not shown.
+1538 -1332
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -96,6 +96,10 @@ do
if [ -n "$mode" ]; then
chmod $mode $newdir/$fname
elif [ "$type" = "f" ]; then
chmod $filmode $newdir/$fname
elif [ "$type" = "d" ]; then
chmod $dirmode $newdir/$fname
fi
done < $MANIFEST
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+2 -2
View File
@@ -259,5 +259,5 @@ efg
42
42
42
./arith.tests: line 327: 'foo' : syntax error: operand expected (error token is "'foo' ")
./arith.tests: line 331: b[c]d: syntax error in expression (error token is "d")
./arith.tests: line 330: 'foo' : syntax error: operand expected (error token is "'foo' ")
./arith.tests: line 333: b[c]d: syntax error in expression (error token is "d")
+3 -1
View File
@@ -322,10 +322,12 @@ printf "%u\n" $n
echo $(( 16#$(printf "%x\n" $n) ))
echo $(( 16#$(printf "%X\n" $n) ))
# allow reserved words after an arithmetic command just because
if ((expr)) then ((expr)) fi
# these are errors
foo=1
echo $(( 'foo' ))
# causes longjmp botches through bash-2.05b
a[b[c]d]=e
+10
View File
@@ -74,5 +74,15 @@ swap32_posix ()
));
done
}
./comsub-posix5.sub: command substitution: line 38: syntax error near unexpected token `done'
./comsub-posix5.sub: command substitution: line 38: `case x in x) ;; x) done esac)'
./comsub-posix5.sub: command substitution: line 39: syntax error near unexpected token `done'
./comsub-posix5.sub: command substitution: line 39: `case x in x) ;; x) done ;; esac)'
./comsub-posix5.sub: command substitution: line 40: syntax error near unexpected token `esac'
./comsub-posix5.sub: command substitution: line 40: `case x in x) (esac) esac)'
bash: -c: line 1: syntax error near unexpected token `;;'
bash: -c: line 1: `: $(case x in esac|in) foo;; esac)'
bash: -c: line 1: unexpected EOF while looking for matching `)'
bash: -c: line 2: syntax error: unexpected end of file
yes
ab cde
+3
View File
@@ -231,6 +231,9 @@ ${THIS_SH} ./comsub-posix2.sub
${THIS_SH} ./comsub-posix3.sub
#${THIS_SH} ./comsub-posix4.sub
${THIS_SH} ./comsub-posix5.sub
# produced a parse error through bash-4.0-beta2
: $(echo foo)"
"
+68
View File
@@ -0,0 +1,68 @@
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
: ${THIS_SH:=./bash}
# problems with recognzing `esac' after a right paren in a command substitution
: $(case x in x) esac)
: $(case x in x) ;; x) esac)
# non-reserved word beginning with e
: $(case x in x) ;; x) echo ;; esac)
# reserved word beginning with e
: $(case x in x) ;; x) eval esac ;; esac)
: $(case x in x ) esac)
: $(case x in x ) ;; x) esac)
: $(case x in (x) esac)
: $(case x in (x) ;; (x) esac)
: $(case x in (x) ;; x) esac)
: $(case x in (x) (echo a) esac)
: $(case x in (x) (echo esac) esac)
: $(case x in x) (echo esac) esac)
# these errors should be caught sooner
: $(case x in x) ;; x) done esac)
: $(case x in x) ;; x) done ;; esac)
: $(case x in x) (esac) esac)
# these are not errors
: $(case x in x) ;; x) eval done ;; esac)
# these are just ridiculous
: $(case x in (x) a() { echo a; } esac)
: $(case x in (x) if :; then echo a; fi esac)
: $(case x in (x) { echo a; } esac)
: $(case x in (x) while false; do echo a; done esac)
: $(case x in (x) case y in (y) echo a;; esac esac)
: $(case x in (x) case y in (y) echo a;; esac ;; (y) foo ;; esac)
: $(case x in x) a() { echo a; } esac)
: $(case x in x) if :; then echo a; fi esac)
: $(case x in x) { echo a; } esac)
: $(case x in x) while false; do echo a; done esac)
: $(case x in x) case y in (y) echo a;; esac esac)
: $(case x in x) case y in (y) echo a;; esac ;; y) foo ;; esac)
: $(case x in x) case y in y) echo a;; esac ;; y) foo ;; esac)
: $(case ni in esac)
: $(case in in esac)
: $(case x in in|esac) foo;; esac)
# this is an error
${THIS_SH} -c ': $(case x in esac|in) foo;; esac)' bash
${THIS_SH} -c ': $(case x in x) ;; x) done)' bash
+3
View File
@@ -207,6 +207,9 @@ del=$'\177'
[[ "" == "$foo" ]] && echo ok 4
[[ "$del" == "${foo,,}" ]] || echo ok 5
# allow reserved words after a conditional command just because
if [[ str ]] then [[ str ]] fi
${THIS_SH} ./cond-regexp1.sub
${THIS_SH} ./cond-regexp2.sub