mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 15:43:18 +02:00
commit bash-20210215 snapshot
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)"
|
||||
"
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user