mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-08-03 16:59:22 +02:00
commit bash-20090305 snapshot
This commit is contained in:
+94
-51
@@ -2670,6 +2670,7 @@ reset_parser ()
|
||||
FREE (word_desc_to_read);
|
||||
word_desc_to_read = (WORD_DESC *)NULL;
|
||||
|
||||
current_token = '\n'; /* XXX */
|
||||
last_read_token = '\n';
|
||||
token_to_read = '\n';
|
||||
}
|
||||
@@ -2917,19 +2918,21 @@ tokword:
|
||||
#define P_DQUOTE 0x04
|
||||
#define P_COMMAND 0x08 /* parsing a command, so look for comments */
|
||||
#define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */
|
||||
#define P_ARRAY 0x20 /* parsing a [...] array assignment */
|
||||
#define P_ARRAYSUB 0x20 /* parsing a [...] array subscript for assignment */
|
||||
|
||||
/* Lexical state while parsing a grouping construct or $(...). */
|
||||
#define LEX_WASDOL 0x001
|
||||
#define LEX_CKCOMMENT 0x002
|
||||
#define LEX_INCOMMENT 0x004
|
||||
#define LEX_PASSNEXT 0x008
|
||||
#define LEX_RESWDOK 0x010
|
||||
#define LEX_CKCASE 0x020
|
||||
#define LEX_INCASE 0x040
|
||||
#define LEX_INHEREDOC 0x080
|
||||
#define LEX_HEREDELIM 0x100 /* reading here-doc delimiter */
|
||||
#define LEX_STRIPDOC 0x200 /* <<- strip tabs from here doc delim */
|
||||
#define LEX_WASDOL 0x0001
|
||||
#define LEX_CKCOMMENT 0x0002
|
||||
#define LEX_INCOMMENT 0x0004
|
||||
#define LEX_PASSNEXT 0x0008
|
||||
#define LEX_RESWDOK 0x0010
|
||||
#define LEX_CKCASE 0x0020
|
||||
#define LEX_INCASE 0x0040
|
||||
#define LEX_INHEREDOC 0x0080
|
||||
#define LEX_HEREDELIM 0x0100 /* reading here-doc delimiter */
|
||||
#define LEX_STRIPDOC 0x0200 /* <<- strip tabs from here doc delim */
|
||||
#define LEX_WASQUOTED 0x0400
|
||||
#define LEX_INWORD 0x0800
|
||||
|
||||
#define COMSUB_META(ch) ((ch) == ';' || (ch) == '&' || (ch) == '|')
|
||||
|
||||
@@ -2952,6 +2955,11 @@ tokword:
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Not exactly right yet, should handle shell metacharacters, too. If
|
||||
any changes are made to this test, make analogous changes to subst.c:
|
||||
extract_delimited_string(). */
|
||||
#define COMMENT_BEGIN(x) ((x) == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
|
||||
|
||||
static char matched_pair_error;
|
||||
|
||||
static char *
|
||||
@@ -2965,7 +2973,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
char *ret, *nestret, *ttrans;
|
||||
int retind, retsize, rflags;
|
||||
|
||||
/* itrace("parse_matched_pair: open = %c close = %c flags = %d", open, close, flags); */
|
||||
/*itrace("parse_matched_pair: open = %c close = %c flags = %d", open, close, flags); */
|
||||
count = 1;
|
||||
tflags = 0;
|
||||
|
||||
@@ -3009,10 +3017,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Not exactly right yet, should handle shell metacharacters, too. If
|
||||
any changes are made to this test, make analogous changes to subst.c:
|
||||
extract_delimited_string(). */
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && COMMENT_BEGIN (ch))
|
||||
tflags |= LEX_INCOMMENT;
|
||||
|
||||
if (tflags & LEX_PASSNEXT) /* last char was backslash */
|
||||
@@ -3132,6 +3137,8 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
APPEND_NESTRET ();
|
||||
FREE (nestret);
|
||||
}
|
||||
else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
|
||||
goto parse_dollar_word;
|
||||
}
|
||||
/* Parse an old-style command substitution within double quotes as a
|
||||
single word. */
|
||||
@@ -3148,6 +3155,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
else if MBTEST(open != '`' && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
|
||||
/* check for $(), $[], or ${} inside quoted string. */
|
||||
{
|
||||
parse_dollar_word:
|
||||
if (open == ch) /* undo previous increment */
|
||||
count--;
|
||||
if (ch == '(') /* ) */
|
||||
@@ -3182,14 +3190,14 @@ parse_comsub (qc, open, close, lenp, flags)
|
||||
int open, close;
|
||||
int *lenp, flags;
|
||||
{
|
||||
int count, ch, peekc, tflags, lex_rwlen, lex_firstind;
|
||||
int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
|
||||
int nestlen, ttranslen, start_lineno;
|
||||
char *ret, *nestret, *ttrans, *heredelim;
|
||||
int retind, retsize, rflags, hdlen;
|
||||
|
||||
/*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/
|
||||
count = 1;
|
||||
tflags = LEX_RESWDOK;
|
||||
tflags = LEX_RESWDOK|LEX_INWORD;
|
||||
|
||||
if ((flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0)
|
||||
tflags |= LEX_CKCASE;
|
||||
@@ -3203,7 +3211,7 @@ parse_comsub (qc, open, close, lenp, flags)
|
||||
retind = 0;
|
||||
|
||||
start_lineno = line_number;
|
||||
lex_rwlen = 0;
|
||||
lex_rwlen = lex_wlen = 0;
|
||||
|
||||
heredelim = 0;
|
||||
lex_firstind = -1;
|
||||
@@ -3270,6 +3278,46 @@ eof_error:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tflags & LEX_PASSNEXT) /* last char was backslash */
|
||||
{
|
||||
/*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
|
||||
tflags &= ~LEX_PASSNEXT;
|
||||
if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
|
||||
{
|
||||
if (retind > 0)
|
||||
retind--; /* swallow previously-added backslash */
|
||||
continue;
|
||||
}
|
||||
|
||||
RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
|
||||
if MBTEST(ch == CTLESC || ch == CTLNUL)
|
||||
ret[retind++] = CTLESC;
|
||||
ret[retind++] = ch;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If this is a shell break character, we are not in a word. If not,
|
||||
we either start or continue a word. */
|
||||
if MBTEST(shellbreak (ch))
|
||||
{
|
||||
tflags &= ~LEX_INWORD;
|
||||
/*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tflags & LEX_INWORD)
|
||||
{
|
||||
lex_wlen++;
|
||||
/*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
/*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
|
||||
tflags |= LEX_INWORD;
|
||||
lex_wlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip whitespace */
|
||||
if MBTEST(shellblank (ch) && lex_rwlen == 0)
|
||||
{
|
||||
@@ -3319,7 +3367,7 @@ eof_error:
|
||||
{
|
||||
RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
|
||||
ret[retind++] = peekc;
|
||||
/*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch); */
|
||||
/*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/
|
||||
tflags |= LEX_RESWDOK;
|
||||
lex_rwlen = 0;
|
||||
continue;
|
||||
@@ -3327,8 +3375,8 @@ eof_error:
|
||||
else if (ch == '\n' || COMSUB_META(ch))
|
||||
{
|
||||
shell_ungetc (peekc);
|
||||
tflags |= LEX_RESWDOK;
|
||||
/*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/
|
||||
tflags |= LEX_RESWDOK;
|
||||
lex_rwlen = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -3367,14 +3415,17 @@ eof_error:
|
||||
}
|
||||
tflags &= ~LEX_RESWDOK;
|
||||
}
|
||||
else if (shellbreak (ch) == 0)
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && ((lex_rwlen == 0 && ch == '#') || COMMENT_BEGIN(ch)))
|
||||
; /* don't turn off LEX_RESWDOK if we're starting a comment */
|
||||
else if MBTEST(shellbreak (ch) == 0)
|
||||
{
|
||||
tflags &= ~LEX_RESWDOK;
|
||||
/*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
|
||||
}
|
||||
}
|
||||
|
||||
if MBTEST((tflags & LEX_INCOMMENT) == 0 && (tflags & LEX_CKCASE) && ch == '<')
|
||||
/* Might be the start of a here-doc delimiter */
|
||||
if MBTEST((tflags & (LEX_PASSNEXT|LEX_INCOMMENT)) == 0 && (tflags & LEX_CKCASE) && ch == '<')
|
||||
{
|
||||
/* Add this character. */
|
||||
RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
|
||||
@@ -3397,36 +3448,27 @@ eof_error:
|
||||
}
|
||||
else
|
||||
shell_ungetc (peekc);
|
||||
tflags |= LEX_HEREDELIM;
|
||||
lex_firstind = -1;
|
||||
if (peekc != '<')
|
||||
{
|
||||
tflags |= LEX_HEREDELIM;
|
||||
lex_firstind = -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
ch = peekc; /* fall through and continue XXX - this skips comments if peekc == '#' */
|
||||
ch = peekc; /* fall through and continue XXX */
|
||||
}
|
||||
/* Not exactly right yet, should handle shell metacharacters, too. If
|
||||
any changes are made to this test, make analogous changes to subst.c:
|
||||
extract_delimited_string(). */
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
|
||||
#if 0
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0) || COMMENT_BEGIN(ch)))
|
||||
#else
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
|
||||
#endif
|
||||
{
|
||||
/*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
|
||||
tflags |= LEX_INCOMMENT;
|
||||
}
|
||||
|
||||
if (tflags & LEX_PASSNEXT) /* last char was backslash */
|
||||
{
|
||||
tflags &= ~LEX_PASSNEXT;
|
||||
if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
|
||||
{
|
||||
if (retind > 0)
|
||||
retind--; /* swallow previously-added backslash */
|
||||
continue;
|
||||
}
|
||||
|
||||
RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
|
||||
if MBTEST(ch == CTLESC || ch == CTLNUL)
|
||||
ret[retind++] = CTLESC;
|
||||
ret[retind++] = ch;
|
||||
continue;
|
||||
}
|
||||
else if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
|
||||
if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
|
||||
{
|
||||
RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
|
||||
ret[retind++] = CTLESC;
|
||||
@@ -4251,7 +4293,7 @@ read_token_word (character)
|
||||
((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
|
||||
(token_index == 0 && (parser_state&PST_COMPASSIGN))))
|
||||
{
|
||||
ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
|
||||
ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
|
||||
if (ttok == &matched_pair_error)
|
||||
return -1; /* Bail immediately. */
|
||||
RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
|
||||
@@ -4452,6 +4494,7 @@ reserved_word_acceptable (toksym)
|
||||
case '}': /* XXX */
|
||||
case AND_AND:
|
||||
case BANG:
|
||||
case BAR_AND:
|
||||
case DO:
|
||||
case DONE:
|
||||
case ELIF:
|
||||
@@ -5186,7 +5229,7 @@ report_syntax_error (message)
|
||||
parser_error (line_number, "%s", message);
|
||||
if (interactive && EOF_Reached)
|
||||
EOF_Reached = 0;
|
||||
last_command_exit_value = EX_USAGE;
|
||||
last_command_exit_value = EX_BADUSAGE;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5201,7 +5244,7 @@ report_syntax_error (message)
|
||||
if (interactive == 0)
|
||||
print_offending_line ();
|
||||
|
||||
last_command_exit_value = EX_USAGE;
|
||||
last_command_exit_value = EX_BADUSAGE;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5232,7 +5275,7 @@ report_syntax_error (message)
|
||||
EOF_Reached = 0;
|
||||
}
|
||||
|
||||
last_command_exit_value = EX_USAGE;
|
||||
last_command_exit_value = EX_BADUSAGE;
|
||||
}
|
||||
|
||||
/* ??? Needed function. ??? We have to be able to discard the constructs
|
||||
|
||||
Reference in New Issue
Block a user