diff options
author | Mu Qiao <qiaomuf@gentoo.org> | 2011-05-15 14:08:10 +0800 |
---|---|---|
committer | Mu Qiao <qiaomuf@gentoo.org> | 2011-05-15 18:40:51 +0800 |
commit | d869ca70e03de7a07d041900592e8b3af2b2a562 (patch) | |
tree | 405197fdaca2775ae911569d037579bd7a530874 | |
parent | Build: parallel support for code coverage (diff) | |
download | libbash-d869ca70e03de7a07d041900592e8b3af2b2a562.tar.gz libbash-d869ca70e03de7a07d041900592e8b3af2b2a562.tar.bz2 libbash-d869ca70e03de7a07d041900592e8b3af2b2a562.zip |
Walker: fix a bug in command stack handling
All commands, built-ins and functions should have their own local
scope(or command environment). Take "foo=abc bar" for example, the
variable foo need to be stored in local scope. We only cared about
the local scope for functions, which caused the example crash. Now
it's fixed by creating local scopes in the walker grammar.
-rw-r--r-- | bashast/libbashWalker.g | 18 | ||||
-rw-r--r-- | scripts/command_execution.bash | 1 | ||||
-rw-r--r-- | scripts/command_execution.bash.result | 1 | ||||
-rw-r--r-- | src/core/interpreter.cpp | 6 | ||||
-rw-r--r-- | src/core/interpreter.h | 20 |
5 files changed, 35 insertions, 11 deletions
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g index 5b22e7a..bd87ee8 100644 --- a/bashast/libbashWalker.g +++ b/bashast/libbashWalker.g @@ -439,13 +439,19 @@ simple_command @declarations { std::vector<std::string> libbash_args; } - :^(COMMAND string_expr (argument[libbash_args])* var_def[true]*) { - if(walker->has_function($string_expr.libbash_value)) + :^(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] +@declarations { + interpreter::local_scope current_scope(*walker); +} + :var_def[true]* { + if(walker->has_function(name)) { ANTLR3_MARKER command_index = INDEX(); try { - walker->set_status(walker->call($string_expr.libbash_value, + walker->set_status(walker->call(name, libbash_args, ctx, compound_command)); @@ -455,13 +461,13 @@ simple_command SEEK(command_index); } } - else if(cppbash_builtin::is_builtin($string_expr.libbash_value)) + else if(cppbash_builtin::is_builtin(name)) { - walker->set_status(walker->execute_builtin($string_expr.libbash_value, libbash_args)); + walker->set_status(walker->execute_builtin(name, libbash_args)); } else { - std::cerr << $string_expr.libbash_value << " is not supported yet" << std::endl; + std::cerr << name << " is not supported yet" << std::endl; walker->set_status(1); } }; diff --git a/scripts/command_execution.bash b/scripts/command_execution.bash index 3664356..821d061 100644 --- a/scripts/command_execution.bash +++ b/scripts/command_execution.bash @@ -13,3 +13,4 @@ false && echo "wrong" false || echo "right" true || echo "wrong" echo "end" +FOO="abc" echo "command environment" diff --git a/scripts/command_execution.bash.result b/scripts/command_execution.bash.result index d9f3021..8bd7226 100644 --- a/scripts/command_execution.bash.result +++ b/scripts/command_execution.bash.result @@ -3,5 +3,6 @@ hello world right right end +command environment FOO001=hello FOO002=Hello World diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp index 1102138..2214613 100644 --- a/src/core/interpreter.cpp +++ b/src/core/interpreter.cpp @@ -206,8 +206,7 @@ int interpreter::call(const std::string& name, return -1; func_index = iter->second; - // Prepare function stack and arguments - local_members.push_back(scope()); + // Prepare arguments define_function_arguments(local_members.back(), arguments); auto INPUT = ctx->pTreeParser->ctnstream; @@ -221,9 +220,6 @@ int interpreter::call(const std::string& name, // Reset to the previous index ISTREAM->seek(ISTREAM, curr); - // Clear function stack - local_members.pop_back(); - return 0; } diff --git a/src/core/interpreter.h b/src/core/interpreter.h index d71885a..c46afe1 100644 --- a/src/core/interpreter.h +++ b/src/core/interpreter.h @@ -87,6 +87,26 @@ class interpreter public: + /// + /// \class local_scope + /// \brief RAII concept for local scope management + /// + class local_scope + { + interpreter& walker; + + public: + local_scope(interpreter& w): walker(w) + { + walker.local_members.push_back(scope()); + } + + ~local_scope() + { + walker.local_members.pop_back(); + } + }; + interpreter(): out(&std::cout), err(&std::cerr), in(&std::cin) { define("IFS", " \t\n"); |