aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMu Qiao <qiaomuf@gentoo.org>2011-07-27 16:55:46 +0800
committerMu Qiao <qiaomuf@gentoo.org>2011-08-02 15:52:18 +0800
commit9042ed3ac8b75202e71e5de49376e0b1c68e847f (patch)
tree611e5275680a3dd5f61e920d546b72631c6ebc52
parentParser: improve exported variable handling (diff)
downloadlibbash-9042ed3ac8b75202e71e5de49376e0b1c68e847f.tar.gz
libbash-9042ed3ac8b75202e71e5de49376e0b1c68e847f.tar.bz2
libbash-9042ed3ac8b75202e71e5de49376e0b1c68e847f.zip
Parser: support empty command with redirection
Now only '>' is supported because there would be a lot of conflicts if we want to fully support this. Also the operator other than '>' doesn't make sense.
-rw-r--r--bashast/bashast.g34
-rw-r--r--bashast/libbashWalker.g6
-rw-r--r--scripts/command_execution.bash1
-rwxr-xr-xtest/verify_error_output_test.sh2
4 files changed, 31 insertions, 12 deletions
diff --git a/bashast/bashast.g b/bashast/bashast.g
index 55a499d..dc0ff1b 100644
--- a/bashast/bashast.g
+++ b/bashast/bashast.g
@@ -226,6 +226,9 @@ tokens{
||token == LESS_THAN
||token == GREATER_THAN
||token == RSHIFT
+ ||token == AMP_LESS_THAN
+ ||token == AMP_GREATER_THAN
+ ||token == AMP_RSHIFT
// for end of command
||token == SEMIC
||token == EOL
@@ -325,7 +328,7 @@ here_document_operator
here_document_begin
: (
- token=~(EOL|BLANK|LESS_THAN|HERE_STRING_OP|AMP|GREATER_THAN|RSHIFT)
+ token=~(EOL|BLANK|LESS_THAN|HERE_STRING_OP|GREATER_THAN|RSHIFT|AMP_LESS_THAN|AMP_GREATER_THAN|AMP_RSHIFT)
{
if(LA(-1) != DQUOTE && LA(-1) != ESC)
{
@@ -347,13 +350,13 @@ redirection_operator
: BLANK! DIGIT redirection_operator
| BLANK?
(
- AMP LESS_THAN -> OP["&<"]
+ AMP_LESS_THAN -> OP["&<"]
| GREATER_THAN AMP -> OP[">&"]
| LESS_THAN AMP -> OP["<&"]
| LESS_THAN GREATER_THAN -> OP["<>"]
| RSHIFT -> OP[">>"]
- | AMP GREATER_THAN -> OP["&>"]
- | AMP RSHIFT -> OP ["&>>"]
+ | AMP_GREATER_THAN -> OP["&>"]
+ | AMP_RSHIFT -> OP ["&>>"]
| LESS_THAN -> LESS_THAN
| GREATER_THAN -> GREATER_THAN
);
@@ -376,21 +379,29 @@ command_atom
| -> ^(VARIABLE_DEFINITIONS variable_definitions)
)
| (EXPORT) => EXPORT BLANK export_item -> ^(STRING EXPORT) ^(STRING ^(DOUBLE_QUOTED_STRING export_item))
- | string_expr_no_reserved_word
+ | command_name
(
(BLANK? parens) => BLANK? parens wspace? compound_command
- -> ^(FUNCTION["function"] string_expr_no_reserved_word compound_command)
+ -> ^(FUNCTION["function"] command_name compound_command)
| (
{LA(1) == BLANK &&
(
!is_special_token(LA(2))
// redirection
- &&(LA(2) != DIGIT || (LA(3) != AMP && LA(3) != LESS_THAN
- && LA(3) != GREATER_THAN && LA(3) != RSHIFT))
+ &&(LA(2) != DIGIT || (LA(3) != AMP_LESS_THAN &&
+ LA(3) != AMP_GREATER_THAN &&
+ LA(3) != AMP_RSHIFT &&
+ LA(3) != GREATER_THAN &&
+ LA(3) != LESS_THAN &&
+ LA(3) != RSHIFT))
)}? => BLANK bash_command_arguments
- )* -> string_expr_no_reserved_word bash_command_arguments*
+ )* -> command_name bash_command_arguments*
);
+command_name
+ : string_expr_no_reserved_word
+ | {LA(1) == GREATER_THAN}? => redirection_atom -> ^(STRING NAME) redirection_atom;
+
variable_definitions
: (
variable_definition_atom ((BLANK name (LSQUARE|EQUALS|PLUS EQUALS)) => BLANK! variable_definition_atom)*
@@ -765,7 +776,7 @@ pattern_char
: LETTER|DIGIT|OTHER|QMARK|COLON|AT|SEMIC|POUND|SLASH
|BANG|TIMES|COMMA|PIPE|AMP|MINUS|PLUS|PCT|LSQUARE|RSQUARE
|RPAREN|LPAREN|RBRACE|LBRACE|DOLLAR|TICK|DOT|LESS_THAN
- |GREATER_THAN|SQUOTE|DQUOTE;
+ |GREATER_THAN|SQUOTE|DQUOTE|AMP_LESS_THAN|AMP_GREATER_THAN|AMP_RSHIFT;
variable_reference
: DOLLAR LBRACE parameter_expansion RBRACE -> ^(VAR_REF parameter_expansion)
@@ -1041,6 +1052,9 @@ LESS_THAN : '<';
GREATER_THAN : '>';
LSHIFT : '<<';
RSHIFT : '>>';
+AMP_LESS_THAN : '&<';
+AMP_GREATER_THAN : '&>';
+AMP_RSHIFT : '&>>';
SEMIC : ';';
DOUBLE_SEMIC : ';;';
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index d1bbe93..7deb461 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -579,7 +579,7 @@ simple_command
}
:string_expr (argument[libbash_args])* execute_command[$string_expr.libbash_value, libbash_args];
-execute_command[const std::string& name, std::vector<std::string>& libbash_args]
+execute_command[std::string& name, std::vector<std::string>& libbash_args]
@declarations {
interpreter::local_scope current_scope(*walker);
std::unique_ptr<std::ostream> out;
@@ -588,6 +588,10 @@ execute_command[const std::string& name, std::vector<std::string>& libbash_args]
bool redirection = false;
}
:var_def[true]* (redirect[out, err, in]{ redirection = true; })* {
+ // Empty command, still need to run bash redirection
+ if(name.empty())
+ name = ":";
+
if(walker->has_function(name))
{
if(redirection)
diff --git a/scripts/command_execution.bash b/scripts/command_execution.bash
index 05e2177..132d72d 100644
--- a/scripts/command_execution.bash
+++ b/scripts/command_execution.bash
@@ -74,3 +74,4 @@ o Hello\
world
echo \`\(\)\$\>\<\`
export SRC_URI="${SRC_URI} http://www.oracle.com/technology/products/berkeley-db/db/update/${MY_PV}/patch.${MY_PV}.${i}"
+> /dev/null
diff --git a/test/verify_error_output_test.sh b/test/verify_error_output_test.sh
index 48e972b..cbf6cf2 100755
--- a/test/verify_error_output_test.sh
+++ b/test/verify_error_output_test.sh
@@ -2,4 +2,4 @@
illegal="${srcdir}/scripts/illegal_script.sh"
output=$(./variable_printer "$illegal" 2>&1)
-[[ $output == "${illegal}(1) : error 10 : Missing token, at offset 3"* ]]
+[[ $output == "${illegal}(1) : error 1 : Unexpected token, at offset 3"* ]]