diff options
author | André Aparício <aparicio99@gmail.com> | 2012-05-28 03:17:41 +0100 |
---|---|---|
committer | André Aparício <aparicio99@gmail.com> | 2012-07-03 02:16:19 +0100 |
commit | ddfcd534ecd1d7415041b431006e087c717dea4c (patch) | |
tree | 9f1bf95e72d8cf9bac131b54d98de96c439da8a2 | |
parent | Builtin: implement read builtin (diff) | |
download | libbash-ddfcd534ecd1d7415041b431006e087c717dea4c.tar.gz libbash-ddfcd534ecd1d7415041b431006e087c717dea4c.tar.bz2 libbash-ddfcd534ecd1d7415041b431006e087c717dea4c.zip |
Builtin: Implement set builtin
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | bashast/libbashWalker.g | 2 | ||||
-rw-r--r-- | scripts/function_def.bash | 15 | ||||
-rw-r--r-- | src/builtins/set_builtin.cpp | 79 | ||||
-rw-r--r-- | src/builtins/set_builtin.h | 46 | ||||
-rw-r--r-- | src/builtins/tests/set_tests.cpp | 43 | ||||
-rw-r--r-- | src/core/interpreter.cpp | 15 | ||||
-rw-r--r-- | src/core/interpreter.h | 3 | ||||
-rw-r--r-- | src/cppbash_builtin.cpp | 2 |
9 files changed, 207 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index ca61091..cc57503 100644 --- a/Makefile.am +++ b/Makefile.am @@ -106,6 +106,7 @@ cppunittests_SOURCES = test/run_tests.cpp \ src/builtins/tests/shopt_tests.cpp \ src/builtins/tests/return_tests.cpp \ src/builtins/tests/read_tests.cpp \ + src/builtins/tests/set_tests.cpp \ src/builtins/tests/printf_tests.cpp \ test/test.h \ test/test.cpp \ @@ -239,6 +240,8 @@ libbash_la_SOURCES = include/common.h \ src/builtins/unset_builtin.cpp \ src/builtins/read_builtin.h \ src/builtins/read_builtin.cpp \ + src/builtins/set_builtin.h \ + src/builtins/set_builtin.cpp \ src/builtins/builtin_exceptions.h \ $(GENERATED_PARSER_C) \ $(GENERATED_PARSER_H) \ diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g index fb1ca55..9157574 100644 --- a/bashast/libbashWalker.g +++ b/bashast/libbashWalker.g @@ -649,7 +649,7 @@ execute_command[std::string& name, std::vector<std::string>& libbash_args] bool redirection = false; } @init { - if(name != "local") + if(name != "local" && name != "set") current_scope.reset(new interpreter::local_scope(*walker)); } :var_def[true]* (redirect[out, err, in]{ redirection = true; })* { diff --git a/scripts/function_def.bash b/scripts/function_def.bash index b425221..53cc6da 100644 --- a/scripts/function_def.bash +++ b/scripts/function_def.bash @@ -76,6 +76,21 @@ func_positional_args() { func_positional_args 1 2 3 IFS=" \t\n" +nested_func_override_positional_args() { + echo $@ + set -- 40 50 60 + echo $@ +} +func_override_positional_args() { + echo $@ + nested_func_override_positional_args 4 5 6 + set -- 10 20 30 + echo $@ +} +set -- foo bar +func_override_positional_args 1 2 3 +echo $@ + if true; then function_in_compound_statement() { echo "function_in_compound_statement" diff --git a/src/builtins/set_builtin.cpp b/src/builtins/set_builtin.cpp new file mode 100644 index 0000000..fca0f82 --- /dev/null +++ b/src/builtins/set_builtin.cpp @@ -0,0 +1,79 @@ +/* + Please use git log for copyright holder and year information + + This file is part of libbash. + + libbash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + libbash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libbash. If not, see <http://www.gnu.org/licenses/>. +*/ +/// +/// \file set_builtin.cpp +/// \brief class that implements the set builtin +/// +#include "builtins/set_builtin.h" + +#include "core/interpreter.h" +#include "exceptions.h" + +int set_builtin::exec(const std::vector<std::string>& bash_args) +{ + if(bash_args.empty()) + { + throw libbash::unsupported_exception("set: variables printing are not supported"); + return 1; + } + + if(bash_args[0][0] != '-' && bash_args[0][0] != '+') + { + throw libbash::illegal_argument_exception("set: invalid option"); + return 1; + } + + switch(bash_args[0][1]) + { + case '-': + if(bash_args[0][0] != '-') { + throw libbash::unsupported_exception("set: invalid option"); + return 1; + } + else + { + _walker.define_positional_arguments(bash_args.begin() + 1, bash_args.end()); + return 0; + } + case 'a': + case 'b': + case 'e': + case 'f': + case 'h': + case 'k': + case 'm': + case 'n': + case 'p': + case 't': + case 'u': + case 'v': + case 'x': + case 'B': + case 'C': + case 'E': + case 'H': + case 'P': + case 'T': + throw libbash::unsupported_exception("set " + bash_args[0] + " is not supported yet"); + return 1; + default: + throw libbash::illegal_argument_exception("set: unrecognized option: " + bash_args[0]); + return 1; + } +} diff --git a/src/builtins/set_builtin.h b/src/builtins/set_builtin.h new file mode 100644 index 0000000..ad27243 --- /dev/null +++ b/src/builtins/set_builtin.h @@ -0,0 +1,46 @@ +/* + Please use git log for copyright holder and year information + + This file is part of libbash. + + libbash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + libbash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libbash. If not, see <http://www.gnu.org/licenses/>. +*/ +/// +/// \file set_builtin.h +/// \brief class that implements the set builtin +/// + +#ifndef LIBBASH_BUILTINS_SET_BUILTIN_H_ +#define LIBBASH_BUILTINS_SET_BUILTIN_H_ + +#include "cppbash_builtin.h" + +/// +/// \class set_builtin +/// \brief the set builtin for bash +/// +class set_builtin: public virtual cppbash_builtin +{ +public: + BUILTIN_CONSTRUCTOR(set) + + /// + /// \brief runs the set builtin on the supplied arguments + /// \param bash_args the arguments to the set builtin + /// \return exit status of set + /// + virtual int exec(const std::vector<std::string>& bash_args); +}; + +#endif diff --git a/src/builtins/tests/set_tests.cpp b/src/builtins/tests/set_tests.cpp new file mode 100644 index 0000000..c4807c9 --- /dev/null +++ b/src/builtins/tests/set_tests.cpp @@ -0,0 +1,43 @@ +/* + Please use git log for copyright holder and year information + + This file is part of libbash. + + libbash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + libbash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libbash. If not, see <http://www.gnu.org/licenses/>. +*/ +/// +/// \file set_tests.cpp +/// \brief series of unit tests for set builtin +/// +#include <boost/lexical_cast.hpp> +#include <gtest/gtest.h> + +#include "core/interpreter.h" +#include "cppbash_builtin.h" +#include "exceptions.h" + +TEST(set_builtin_test, positional) +{ + interpreter walker; + + EXPECT_EQ(0, cppbash_builtin::exec("set", {"--", "1", "2", "3"}, std::cout, std::cerr, std::cin, walker)); + EXPECT_EQ(3, walker.get_array_length("*")); + EXPECT_STREQ("1", walker.resolve<std::string>("*", 1).c_str()); + EXPECT_STREQ("2", walker.resolve<std::string>("*", 2).c_str()); + EXPECT_STREQ("3", walker.resolve<std::string>("*", 3).c_str()); + + EXPECT_EQ(0, cppbash_builtin::exec("set", {"--"}, std::cout, std::cerr, std::cin, walker)); + EXPECT_EQ(0, walker.get_array_length("*")); + EXPECT_STREQ("", walker.resolve<std::string>("*", 1).c_str()); +} diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp index b048353..405023d 100644 --- a/src/core/interpreter.cpp +++ b/src/core/interpreter.cpp @@ -312,6 +312,21 @@ void interpreter::define_function_arguments(scope& current_stack, current_stack["*"].reset(new variable("*", positional_args)); } +void interpreter::define_positional_arguments(const std::vector<std::string>::const_iterator begin, + const std::vector<std::string>::const_iterator end) +{ + std::map<unsigned, std::string> positional_args; + std::vector<std::string>::const_iterator iter = begin; + + for(auto i = 1u; iter != end ; ++i, ++iter) + positional_args[i] = *iter; + + if(local_members.size() < 1) + define("*", positional_args); + else + define_local("*", positional_args); +} + namespace { bool check_function_name(const std::string& name) diff --git a/src/core/interpreter.h b/src/core/interpreter.h index fbb9d48..dd72377 100644 --- a/src/core/interpreter.h +++ b/src/core/interpreter.h @@ -521,6 +521,9 @@ public: /// \return zero unless n is greater than $# or less than zero, non-zero otherwise. int shift(int shift_number); + void define_positional_arguments(const std::vector<std::string>::const_iterator begin, + const std::vector<std::string>::const_iterator end); + /// \brief perform expansion like ${var//foo/bar} /// \param value the value to be expanded /// \param pattern the pattern used to match the value diff --git a/src/cppbash_builtin.cpp b/src/cppbash_builtin.cpp index c93b94a..e4a7c29 100644 --- a/src/cppbash_builtin.cpp +++ b/src/cppbash_builtin.cpp @@ -45,6 +45,7 @@ #include "builtins/source_builtin.h" #include "builtins/unset_builtin.h" #include "builtins/read_builtin.h" +#include "builtins/set_builtin.h" namespace qi = boost::spirit::qi; namespace karma = boost::spirit::karma; @@ -75,6 +76,7 @@ cppbash_builtin::builtins_type& cppbash_builtin::builtins() { {"let", boost::factory<let_builtin*>()}, {"unset", boost::factory<unset_builtin*>()}, {"read", boost::factory<read_builtin*>()}, + {"set", boost::factory<set_builtin*>()}, }); return *p; } |