aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMu Qiao <qiaomuf@gentoo.org>2011-05-15 14:08:10 +0800
committerMu Qiao <qiaomuf@gentoo.org>2011-05-15 18:40:51 +0800
commitd869ca70e03de7a07d041900592e8b3af2b2a562 (patch)
tree405197fdaca2775ae911569d037579bd7a530874
parentBuild: parallel support for code coverage (diff)
downloadlibbash-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.g18
-rw-r--r--scripts/command_execution.bash1
-rw-r--r--scripts/command_execution.bash.result1
-rw-r--r--src/core/interpreter.cpp6
-rw-r--r--src/core/interpreter.h20
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");