aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Aparício <aparicio99@gmail.com>2012-06-19 17:46:40 +0100
committerMu Qiao <qiaomuf@gentoo.org>2012-07-20 09:20:22 +0800
commitf9501f5d7ad82d273cab44cd96114d644fb5772d (patch)
tree8a0639ad40b65f460cdb7409ea94ffc52d7fd67b
parentReplace boost::scoped_ptr with std::unique_ptr (diff)
downloadlibbash-f9501f5d7ad82d273cab44cd96114d644fb5772d.tar.gz
libbash-f9501f5d7ad82d273cab44cd96114d644fb5772d.tar.bz2
libbash-f9501f5d7ad82d273cab44cd96114d644fb5772d.zip
Builtin: Support variable declarations in declare
-rw-r--r--bashast/bashast.g5
-rw-r--r--bashast/libbashWalker.g5
-rw-r--r--scripts/command_execution.bash3
-rw-r--r--scripts/var_def.bash7
-rw-r--r--src/builtins/declare_builtin.cpp144
-rw-r--r--src/builtins/tests/declare_tests.cpp35
6 files changed, 123 insertions, 76 deletions
diff --git a/bashast/bashast.g b/bashast/bashast.g
index e2702d0..2d425ce 100644
--- a/bashast/bashast.g
+++ b/bashast/bashast.g
@@ -398,6 +398,8 @@ command_atom
-> ^(STRING EXPORT) ^(STRING builtin_variable_definition_item)
| (LOCAL) => LOCAL BLANK builtin_variable_definition_item
-> ^(STRING LOCAL) ^(STRING builtin_variable_definition_item)
+ | (DECLARE) => DECLARE BLANK builtin_variable_definition_item
+ -> ^(STRING DECLARE) ^(STRING builtin_variable_definition_item)
| command_name
(
(BLANK? parens) => BLANK? parens wspace? compound_command
@@ -782,7 +784,7 @@ string_part
ns_string_part
: num|name|escaped_character
|OTHER|EQUALS|PCT|PCTPCT|PLUS|MINUS|DOT|DOTDOT|COLON
- |TILDE|LSQUARE|RSQUARE|CARET|POUND|COMMA|EXPORT|LOCAL|AT
+ |TILDE|LSQUARE|RSQUARE|CARET|POUND|COMMA|EXPORT|LOCAL|DECLARE|AT
// Escaped characters
|ESC_RPAREN|ESC_LPAREN|ESC_DOLLAR|ESC_GT|ESC_LT|ESC_TICK|ESC_DQUOTE
// The following is for filename expansion
@@ -1151,6 +1153,7 @@ QMARK : '?';
LOCAL : 'local';
EXPORT : 'export';
+DECLARE : 'declare';
LOGICAND : '&&';
LOGICOR : '||';
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 648dd53..42a8917 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -637,7 +637,8 @@ simple_command
std::vector<std::string> libbash_args;
bool split;
}
- :string_expr{ split = ($string_expr.libbash_value != "local" && $string_expr.libbash_value != "export"); }
+ :string_expr{ split = ($string_expr.libbash_value != "local" && $string_expr.libbash_value != "export"
+ && $string_expr.libbash_value != "declare"); }
(argument[libbash_args, split])* execute_command[$string_expr.libbash_value, libbash_args];
execute_command[std::string& name, std::vector<std::string>& libbash_args]
@@ -649,7 +650,7 @@ execute_command[std::string& name, std::vector<std::string>& libbash_args]
bool redirection = false;
}
@init {
- if(name != "local" && name != "set")
+ if(name != "local" && name != "set" && name != "declare")
current_scope.reset(new interpreter::local_scope(*walker));
}
:var_def[true]* (redirect[out, err, in]{ redirection = true; })* {
diff --git a/scripts/command_execution.bash b/scripts/command_execution.bash
index 4c04908..901a9bb 100644
--- a/scripts/command_execution.bash
+++ b/scripts/command_execution.bash
@@ -93,3 +93,6 @@ echo "${!#// /_}"
echo "${!1// /_}"
echo "${!variable// /$'\n'}"
eval abc+=\( \"\$@\" \)
+declare MOZILLA_FIVE_HOME="/usr/share/${PN}"
+declare foo=23 empty bar=42
+echo $MOZILLA_FIVE_HOME $foo $lol $bar
diff --git a/scripts/var_def.bash b/scripts/var_def.bash
index 96747c0..b0224f1 100644
--- a/scripts/var_def.bash
+++ b/scripts/var_def.bash
@@ -17,6 +17,8 @@ IUSE=""
echo $IUSE
RDEPEND="dev-db/sqlite:3"
echo $RDEPEND
+declare RDEPEND
+echo $RDEPEND
DEPEND="${RDEPEND}
echo $DEPEND
dev-util/pkgconfig"
@@ -26,6 +28,7 @@ PATCH=("1.patch" 2.patch)
echo ${PATCH[@]}
ARRAY01=(1 2 3 [5]=4 5)
echo ${ARRAY01[@]}
+declare ARRAY02
ARRAY02=(1 2 3)
echo ${ARRAY02[@]}
ARRAY02[2]=4
@@ -96,3 +99,7 @@ echo ${ARRAY12[@]}
ARRAY13=()
ARRAY13+=(4 5 6)
echo ${ARRAY13[@]}
+declare num=42
+echo $num
+unset num
+echo $num
diff --git a/src/builtins/declare_builtin.cpp b/src/builtins/declare_builtin.cpp
index db955c4..81877b5 100644
--- a/src/builtins/declare_builtin.cpp
+++ b/src/builtins/declare_builtin.cpp
@@ -25,6 +25,10 @@
#include <algorithm>
#include <iostream>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
+
+#include "core/bash_ast.h"
#include "core/interpreter.h"
#include "exceptions.h"
@@ -35,80 +39,88 @@ int declare_builtin::exec(const std::vector<std::string>& bash_args)
throw libbash::illegal_argument_exception("declare: arguments required");
return 1;
}
- else if(bash_args[0].size() != 2)
- {
- throw libbash::unsupported_exception("declare: multiple arguments are not supported");
- return 1;
- }
-
- if(bash_args[0][0] != '-' && bash_args[0][0] != '+')
- {
- throw libbash::illegal_argument_exception("declare: invalid option");
- return 1;
- }
int result = 0;
- switch(bash_args[0][1])
+
+ std::vector<std::string> tokens;
+ boost::split(tokens, bash_args[0], boost::is_any_of(" "));
+
+ if(tokens[0][0] == '-' || tokens[0][0] == '+')
{
- case 'F':
- if(bash_args[0][0] == '+')
- return 0;
- if(bash_args.size() > 1)
- {
- for(auto iter = bash_args.begin() + 1; iter != bash_args.end(); ++iter)
- {
- if(_walker.has_function(*iter))
- *_out_stream << *iter << std::endl;
- else
- result = 1;
- }
- }
- else
- {
- std::vector<std::string> functions;
-
- _walker.get_all_function_names(functions);
- sort(functions.begin(), functions.end());
-
- for(auto iter = functions.begin(); iter != functions.end(); ++iter)
- *_out_stream << "declare -f " << *iter << std::endl;
- }
- return result;
- case 'p':
- if(bash_args.size() > 1)
- {
- for(auto iter = bash_args.begin() + 1; iter != bash_args.end(); ++iter)
+ if(tokens[0].size() > 2)
+ throw libbash::unsupported_exception("declare: " + tokens[0] + " is not supported yet");
+
+ switch(tokens[0][1])
+ {
+ case 'F':
+ if(tokens[0][0] == '+')
+ return 0;
+ if(tokens.size() > 1)
{
- // We do not print the type of the variable for now
- if(!_walker.is_unset(*iter))
+ for(auto iter = tokens.begin() + 1; iter != tokens.end(); ++iter)
{
- *_out_stream << "declare -- " << *iter << "=\"" << _walker.resolve<std::string>(*iter) << "\"" << std::endl;
+ if(_walker.has_function(*iter))
+ *_out_stream << *iter << std::endl;
+ else
+ result = 1;
}
- else
+ }
+ else
+ {
+ std::vector<std::string> functions;
+
+ _walker.get_all_function_names(functions);
+ sort(functions.begin(), functions.end());
+
+ for(auto iter = functions.begin(); iter != functions.end(); ++iter)
+ *_out_stream << "declare -f " << *iter << std::endl;
+ }
+ return result;
+ case 'p':
+ if(tokens.size() > 1)
+ {
+ for(auto iter = tokens.begin() + 1; iter != tokens.end(); ++iter)
{
- *_out_stream << "-bash: declare: " << *iter << ": not found" << std::endl;
- result = 1;
+ // We do not print the type of the variable for now
+ if(!_walker.is_unset(*iter))
+ {
+ *_out_stream << "declare -- " << *iter << "=\"" << _walker.resolve<std::string>(*iter) << "\"" << std::endl;
+ }
+ else
+ {
+ *_out_stream << "-bash: declare: " << *iter << ": not found" << std::endl;
+ result = 1;
+ }
}
}
- }
- else
- {
- throw libbash::unsupported_exception("We do not support declare -p without arguments for now");
- }
- return result;
- case 'a':
- case 'A':
- case 'f':
- case 'i':
- case 'l':
- case 'r':
- case 't':
- case 'u':
- case 'x':
- throw libbash::unsupported_exception("declare " + bash_args[0] + " is not supported yet");
- return 1;
- default:
- throw libbash::illegal_argument_exception("declare: unrecognized option: " + bash_args[0]);
- return 1;
+ else
+ {
+ throw libbash::unsupported_exception("We do not support declare -p without arguments for now");
+ }
+ return result;
+ case 'a':
+ case 'i':
+ case 'A':
+ case 'f':
+ case 'l':
+ case 'r':
+ case 't':
+ case 'u':
+ case 'x':
+ throw libbash::unsupported_exception("declare " + tokens[0] + " is not supported yet");
+ return 1;
+ default:
+ throw libbash::illegal_argument_exception("declare: unrecognized option: " + tokens[0]);
+ return 1;
+ }
}
+
+ std::stringstream script;
+ 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));
+ ast.interpret_with(_walker);
+
+ return result;
}
diff --git a/src/builtins/tests/declare_tests.cpp b/src/builtins/tests/declare_tests.cpp
index 19347ac..eec5e41 100644
--- a/src/builtins/tests/declare_tests.cpp
+++ b/src/builtins/tests/declare_tests.cpp
@@ -55,11 +55,32 @@ namespace
TEST(declare_builtin_test, invalid_arguments)
{
test_declare<libbash::illegal_argument_exception>("declare: arguments required", {});
- test_declare<libbash::unsupported_exception>("declare: multiple arguments are not supported", {"-ap"});
- test_declare<libbash::illegal_argument_exception>("declare: invalid option", {"_a"});
+ test_declare<libbash::unsupported_exception>("declare: -ap is not supported yet", {"-ap"});
test_declare<libbash::illegal_argument_exception>("declare: unrecognized option: -L", {"-L"});
}
+TEST(declare_built_test, declarations)
+{
+ interpreter walker;
+
+ EXPECT_EQ(0, cppbash_builtin::exec("declare", {"var"}, cout, cerr, cin, walker));
+
+ EXPECT_EQ(0, cppbash_builtin::exec("declare", {"foo1=bar"}, cout, cerr, cin, walker));
+ EXPECT_STREQ("bar", walker.resolve<std::string>("foo1").c_str());
+
+ walker.define("foo2", "bar");
+ EXPECT_EQ(0, cppbash_builtin::exec("declare", {"foo2"}, cout, cerr, cin, walker));
+ EXPECT_STREQ("bar", walker.resolve<std::string>("foo2").c_str());
+
+ EXPECT_EQ(0, cppbash_builtin::exec("declare", {"var1=foo var2 var3=bar"}, cout, cerr, cin, walker));
+ EXPECT_STREQ("foo", walker.resolve<std::string>("var1").c_str());
+ EXPECT_STREQ("", walker.resolve<std::string>("var2").c_str());
+ EXPECT_STREQ("bar", walker.resolve<std::string>("var3").c_str());
+
+ EXPECT_EQ(0, cppbash_builtin::exec("declare", {"var=\"foo bar\""}, cout, cerr, cin, walker));
+ EXPECT_STREQ("foo bar", walker.resolve<std::string>("var").c_str());
+}
+
TEST(declare_builtin_test, _F)
{
stringstream expression("function foo() { :; }; function bar() { :; }");
@@ -68,15 +89,15 @@ TEST(declare_builtin_test, _F)
ast.interpret_with(walker);
stringstream test_output1;
- EXPECT_EQ(0, cppbash_builtin::exec("declare", {"-F", "foo"}, test_output1, cerr, cin, walker));
+ EXPECT_EQ(0, cppbash_builtin::exec("declare", {"-F foo"}, test_output1, cerr, cin, walker));
EXPECT_EQ("foo\n", test_output1.str());
stringstream test_output2;
- EXPECT_EQ(1, cppbash_builtin::exec("declare", {"-F", "foo", "bar", "test"}, test_output2, cerr, cin, walker));
+ EXPECT_EQ(1, cppbash_builtin::exec("declare", {"-F foo bar test"}, test_output2, cerr, cin, walker));
EXPECT_EQ("foo\nbar\n", test_output2.str());
stringstream test_output3;
- EXPECT_EQ(0, cppbash_builtin::exec("declare", {"+F", "foo", "bar", "test"}, test_output3, cerr, cin, walker));
+ EXPECT_EQ(0, cppbash_builtin::exec("declare", {"+F foo bar test"}, test_output3, cerr, cin, walker));
EXPECT_EQ("", test_output3.str());
stringstream test_output4;
@@ -90,11 +111,11 @@ TEST(declare_built_test, _p)
walker.define("foo", "bar");
stringstream test_output1;
- EXPECT_EQ(0, cppbash_builtin::exec("declare", {"-p", "foo"}, test_output1, cerr, cin, walker));
+ EXPECT_EQ(0, cppbash_builtin::exec("declare", {"-p foo"}, test_output1, cerr, cin, walker));
EXPECT_EQ("declare -- foo=\"bar\"\n", test_output1.str());
stringstream test_output2;
- EXPECT_EQ(1, cppbash_builtin::exec("declare", {"-p", "bar", "test"}, test_output2, cerr, cin, walker));
+ EXPECT_EQ(1, cppbash_builtin::exec("declare", {"-p bar test"}, test_output2, cerr, cin, walker));
EXPECT_EQ("-bash: declare: bar: not found\n-bash: declare: test: not found\n", test_output2.str());
}