diff options
-rw-r--r-- | src/builtins/declare_builtin.cpp | 13 | ||||
-rw-r--r-- | src/builtins/tests/declare_tests.cpp | 23 | ||||
-rw-r--r-- | src/core/interpreter.h | 8 |
3 files changed, 39 insertions, 5 deletions
diff --git a/src/builtins/declare_builtin.cpp b/src/builtins/declare_builtin.cpp index 81877b5..34a78cd 100644 --- a/src/builtins/declare_builtin.cpp +++ b/src/builtins/declare_builtin.cpp @@ -41,6 +41,8 @@ int declare_builtin::exec(const std::vector<std::string>& bash_args) } int result = 0; + bool jump_option = false; + bool option_global = false; std::vector<std::string> tokens; boost::split(tokens, bash_args[0], boost::is_any_of(" ")); @@ -50,6 +52,7 @@ int declare_builtin::exec(const std::vector<std::string>& bash_args) if(tokens[0].size() > 2) throw libbash::unsupported_exception("declare: " + tokens[0] + " is not supported yet"); + jump_option = true; switch(tokens[0][1]) { case 'F': @@ -100,6 +103,10 @@ int declare_builtin::exec(const std::vector<std::string>& bash_args) return result; case 'a': case 'i': + break; + case 'g': + option_global = true; + break; case 'A': case 'f': case 'l': @@ -119,7 +126,11 @@ int declare_builtin::exec(const std::vector<std::string>& bash_args) for(auto iter = bash_args.begin(); iter != bash_args.end(); ++iter) script << *iter + " "; - bash_ast ast(script, std::bind(&bash_ast::parser_builtin_variable_definitions, std::placeholders::_1, false)); + if(jump_option) + script.ignore(static_cast<std::streamsize>(tokens[0].size())); + + bool local = _walker.is_local_scope() && !option_global; + bash_ast ast(script, std::bind(&bash_ast::parser_builtin_variable_definitions, std::placeholders::_1, local)); ast.interpret_with(_walker); return result; diff --git a/src/builtins/tests/declare_tests.cpp b/src/builtins/tests/declare_tests.cpp index eec5e41..1b83f7d 100644 --- a/src/builtins/tests/declare_tests.cpp +++ b/src/builtins/tests/declare_tests.cpp @@ -119,22 +119,37 @@ TEST(declare_built_test, _p) EXPECT_EQ("-bash: declare: bar: not found\n-bash: declare: test: not found\n", test_output2.str()); } +TEST(declare_built_test, _a) +{ + interpreter walker; + EXPECT_EQ(0, cppbash_builtin::exec("declare", {"-a", "foo"}, std::cout, cerr, cin, walker)); + walker.set_value("foo", "bar", 3); + EXPECT_STREQ("bar", walker.resolve<std::string>("foo", 3).c_str()); +} + +TEST(declare_built_test, _g) +{ + stringstream expression("function func() { declare -g var1=foo; declare var2=bar; }; func;"); + interpreter walker; + bash_ast ast(expression); + ast.interpret_with(walker); + + EXPECT_STREQ("foo", walker.resolve<std::string>("var1").c_str()); + EXPECT_STREQ("", walker.resolve<std::string>("var2").c_str()); +} + #define TEST_DECLARE(name, expected, ...) \ TEST(declare_builtin_test, name) { test_declare<libbash::unsupported_exception>(expected, {__VA_ARGS__}); } -TEST_DECLARE(_a, "declare -a is not supported yet", "-a", "world") TEST_DECLARE(_A, "declare -A is not supported yet", "-A", "world") TEST_DECLARE(_f, "declare -f is not supported yet", "-f", "world") -TEST_DECLARE(_i, "declare -i is not supported yet", "-i", "world") TEST_DECLARE(_l, "declare -l is not supported yet", "-l", "world") TEST_DECLARE(_r, "declare -r is not supported yet", "-r", "world") TEST_DECLARE(_t, "declare -t is not supported yet", "-t", "world") TEST_DECLARE(_u, "declare -u is not supported yet", "-u", "world") TEST_DECLARE(_x, "declare -x is not supported yet", "-x", "world") -TEST_DECLARE(pa, "declare +a is not supported yet", "+a", "world") TEST_DECLARE(pA, "declare +A is not supported yet", "+A", "world") TEST_DECLARE(pf, "declare +f is not supported yet", "+f", "world") -TEST_DECLARE(pi, "declare +i is not supported yet", "+i", "world") TEST_DECLARE(pl, "declare +l is not supported yet", "+l", "world") TEST_DECLARE(pr, "declare +r is not supported yet", "+r", "world") TEST_DECLARE(pt, "declare +t is not supported yet", "+t", "world") diff --git a/src/core/interpreter.h b/src/core/interpreter.h index 3f77f5d..2f6854b 100644 --- a/src/core/interpreter.h +++ b/src/core/interpreter.h @@ -176,6 +176,14 @@ public: return members.end(); } + /// + /// \brief checks whether the current scope is local or global + /// \return whether current scope is local + bool is_local_scope() const + { + return local_members.size() > 0; + } + /// \brief set current output stream /// \param stream the pointer to the output stream void set_output_stream(std::ostream* stream) |