aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMu Qiao <qiaomuf@gentoo.org>2011-06-22 21:25:48 +0800
committerMu Qiao <qiaomuf@gentoo.org>2011-06-26 22:06:37 +0800
commitccec9a99b7f370c2b4d4ae872d97385848fb1845 (patch)
tree8c9b5ee7f7b46ebfbdbee2212e97dacb41e7192d /src
parentBuild: relax antlr timeout limit (diff)
downloadlibbash-ccec9a99b7f370c2b4d4ae872d97385848fb1845.tar.gz
libbash-ccec9a99b7f370c2b4d4ae872d97385848fb1845.tar.bz2
libbash-ccec9a99b7f370c2b4d4ae872d97385848fb1845.zip
Walker: make arithmetic expansion follow POSIX
POSIX requires signed long integer for arithmetic expansion. $? is implemented in the interpreter class now because POSIX doesn't require the type of $? to be long. It would cause conversion in many places if we used long for $?.
Diffstat (limited to 'src')
-rw-r--r--src/builtins/inherit_builtin.cpp6
-rw-r--r--src/core/bash_ast.cpp2
-rw-r--r--src/core/bash_ast.h2
-rw-r--r--src/core/interpreter.cpp4
-rw-r--r--src/core/interpreter.h17
-rw-r--r--src/core/symbols.hpp30
-rw-r--r--src/core/tests/interpreter_test.cpp16
-rw-r--r--src/core/tests/symbols_test.cpp14
8 files changed, 47 insertions, 44 deletions
diff --git a/src/builtins/inherit_builtin.cpp b/src/builtins/inherit_builtin.cpp
index 54ba4ac..1490e5b 100644
--- a/src/builtins/inherit_builtin.cpp
+++ b/src/builtins/inherit_builtin.cpp
@@ -58,7 +58,7 @@ inline bool inherit_builtin::hasq(const std::string& value, const std::string& n
// We do not support any QA warning
int inherit_builtin::exec(const std::vector<std::string>& bash_args)
{
- _walker.set_value("ECLASS_DEPTH", _walker.resolve<int>("ECLASS_DEPTH") + 1);
+ _walker.set_value("ECLASS_DEPTH", _walker.resolve<long>("ECLASS_DEPTH") + 1);
// find eclass directory
std::string eclassdir;
@@ -114,8 +114,8 @@ int inherit_builtin::exec(const std::vector<std::string>& bash_args)
_walker.set_value("INHERITED", _walker.resolve<std::string>("INHERITED") + " " + *iter);
}
- _walker.set_value("ECLASS_DEPTH", _walker.resolve<int>("ECLASS_DEPTH") - 1);
- if(_walker.resolve<int>("ECLASS_DEPTH") > 0)
+ _walker.set_value("ECLASS_DEPTH", _walker.resolve<long>("ECLASS_DEPTH") - 1);
+ if(_walker.resolve<long>("ECLASS_DEPTH") > 0)
{
_walker.set_value("ECLASS", PECLASS);
}
diff --git a/src/core/bash_ast.cpp b/src/core/bash_ast.cpp
index 45cec7c..56aef8c 100644
--- a/src/core/bash_ast.cpp
+++ b/src/core/bash_ast.cpp
@@ -176,7 +176,7 @@ void bash_ast::walker_start(plibbashWalker tree_parser)
tree_parser->start(tree_parser);
}
-int bash_ast::walker_arithmetics(plibbashWalker tree_parser)
+long bash_ast::walker_arithmetics(plibbashWalker tree_parser)
{
return tree_parser->arithmetics(tree_parser);
}
diff --git a/src/core/bash_ast.h b/src/core/bash_ast.h
index ae6bb0f..f79608d 100644
--- a/src/core/bash_ast.h
+++ b/src/core/bash_ast.h
@@ -75,7 +75,7 @@ public:
static void walker_start(plibbashWalker tree_parser);
- static int walker_arithmetics(plibbashWalker tree_parser);
+ static long walker_arithmetics(plibbashWalker tree_parser);
static void call_function(plibbashWalker tree_parser,
ANTLR3_MARKER index);
diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index 267183a..ed9f626 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -118,7 +118,7 @@ interpreter::interpreter(): _out(&std::cout), _err(&std::cerr), _in(&std::cin),
{'P', false},
{'T', false},
}
- )
+ ), status(0)
{
define("IFS", " \t\n");
// We do not support the options set by the shell itself (such as the -i option)
@@ -430,7 +430,7 @@ void interpreter::set_additional_option(const std::string& name, bool value)
iter->second = value;
}
-int interpreter::eval_arithmetic(const std::string& expression)
+long interpreter::eval_arithmetic(const std::string& expression)
{
bash_ast ast(std::stringstream(expression), &bash_ast::parser_arithmetics);
return ast.interpret_with(*this, &bash_ast::walker_arithmetics);
diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index d44ede4..b0cfda5 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -73,6 +73,10 @@ class interpreter: public boost::noncopyable
// as bash implementation.
std::map<char, bool> options;
+ /// \var private::status
+ /// \brief the return status of the last command
+ int status;
+
/// \brief calculate the correct offset when offset < 0 and check whether
/// the real offset is in legal range
/// \param[in,out] a value/result argument referring to offset
@@ -180,7 +184,7 @@ public:
_out = &std::cout;
}
- /// \brief resolve string/int variable, local scope will be
+ /// \brief resolve string/long variable, local scope will be
/// checked first, then global scope
/// \param variable name
/// \param array index, use index=0 if it's not an array
@@ -245,17 +249,16 @@ public:
/// \brief set the return status of the last command
/// \param the value of the return status
- void set_status(int status)
+ void set_status(int s)
{
- set_value("?", status);
+ status = s;
}
/// \brief get the return status of the last command
/// \param the value of the return status
- template <typename T=int>
- T get_status(void) const
+ int get_status(void) const
{
- return resolve<T>("?");
+ return status;
}
/// \brief unset a variable
@@ -483,7 +486,7 @@ public:
/// \brief evaluate arithmetic expression and return the result
/// \param the arithmetic expression
/// \return the evaluated result
- int eval_arithmetic(const std::string& expression);
+ long eval_arithmetic(const std::string& expression);
/// \brief perform expansion like ${var//foo/bar}
/// \param the value to be expanded
diff --git a/src/core/symbols.hpp b/src/core/symbols.hpp
index a5e2e1d..8c6dec7 100644
--- a/src/core/symbols.hpp
+++ b/src/core/symbols.hpp
@@ -46,33 +46,33 @@ class converter: public boost::static_visitor<T>
///
/// \class converter
-/// \brief specialized converter for int
+/// \brief specialized converter for long
///
template<>
-class converter<int>: public boost::static_visitor<int>
+class converter<long>: public boost::static_visitor<long>
{
public:
- /// \brief converter for int value
+ /// \brief converter for long value
/// \param the value to be converted
- /// \return the converted int
- int operator() (const int value) const
+ /// \return the converted long
+ long operator() (const long value) const
{
return value;
}
/// \brief converter for string value
/// \param the value to be converted
- /// \return the converted int
- int operator() (const std::string& value) const
+ /// \return the converted long
+ long operator() (const std::string& value) const
{
- int result = 0;
+ long result = 0;
try
{
- result = boost::lexical_cast<int>(value);
+ result = boost::lexical_cast<long>(value);
}
catch(boost::bad_lexical_cast& e)
{
- std::cerr << "can't cast " << value << " to int" << std::endl;
+ std::cerr << "can't cast " << value << " to long" << std::endl;
}
return result;
}
@@ -87,10 +87,10 @@ class converter<std::string>:
public boost::static_visitor<std::string>
{
public:
- /// \brief converter for int value
+ /// \brief converter for long value
/// \param the value to be converted
/// \return the converted string
- std::string operator() (const int value) const
+ std::string operator() (const long value) const
{
return boost::lexical_cast<std::string>(value);
}
@@ -115,17 +115,17 @@ class variable
std::string name;
/// \var private::value
- /// \brief actual value of the variable. We put string in front of int
+ /// \brief actual value of the variable. We put string in front of long
/// because we want "" as default string value; Otherwise we
/// will get "0".
- std::map<unsigned, boost::variant<std::string, int>> value;
+ std::map<unsigned, boost::variant<std::string, long>> value;
/// \var private::readonly
/// \brief whether the variable is readonly
bool readonly;
public:
- typedef std::map<unsigned, boost::variant<std::string, int>>::size_type size_type;
+ typedef std::map<unsigned, boost::variant<std::string, long>>::size_type size_type;
/// \brief retrieve variable name
/// \return const string value of variable name
diff --git a/src/core/tests/interpreter_test.cpp b/src/core/tests/interpreter_test.cpp
index c449e3c..d20697b 100644
--- a/src/core/tests/interpreter_test.cpp
+++ b/src/core/tests/interpreter_test.cpp
@@ -31,9 +31,9 @@ TEST(interpreter, define_resolve_int)
{
interpreter walker;
walker.define("aint", 4);
- EXPECT_EQ(4, walker.resolve<int>("aint"));
- EXPECT_EQ(0, walker.resolve<int>("undefined"));
- EXPECT_EQ(0, walker.resolve<int>(""));
+ EXPECT_EQ(4, walker.resolve<long>("aint"));
+ EXPECT_EQ(0, walker.resolve<long>("undefined"));
+ EXPECT_EQ(0, walker.resolve<long>(""));
}
TEST(interpreter, define_resolve_string)
@@ -57,7 +57,7 @@ TEST(interpreter, define_resolve_array)
walker.define("partial", 10, false, 8);
EXPECT_EQ(1, walker.get_array_length("partial"));
- EXPECT_EQ(10, walker.resolve<int>("partial", 8));
+ EXPECT_EQ(10, walker.resolve<long>("partial", 8));
EXPECT_EQ(0, walker.get_array_length("not exist"));
}
@@ -91,14 +91,14 @@ TEST(interpreter, set_int_value)
interpreter walker;
walker.define("aint", 4);
EXPECT_EQ(10, walker.set_value("aint", 10));
- EXPECT_EQ(10, walker.resolve<int>("aint"));
+ EXPECT_EQ(10, walker.resolve<long>("aint"));
EXPECT_EQ(10, walker.set_value("undefined", 10));
- EXPECT_EQ(10, walker.resolve<int>("undefined"));
+ EXPECT_EQ(10, walker.resolve<long>("undefined"));
walker.define("aint_ro", 4, true);
EXPECT_THROW(walker.set_value("aint_ro", 10),
libbash::readonly_exception);
- EXPECT_EQ(4, walker.resolve<int>("aint_ro"));
+ EXPECT_EQ(4, walker.resolve<long>("aint_ro"));
}
TEST(interpreter, set_string_value)
@@ -138,7 +138,7 @@ TEST(interpreter, get_array_values)
std::map<unsigned, std::string> values = {{0, "1"}, {1, "2"}, {2, "3"}};
walker.define("array", values);
- std::vector<int> array_values;
+ std::vector<long> array_values;
EXPECT_TRUE(walker.resolve_array("array", array_values));
EXPECT_EQ(1, array_values[0]);
EXPECT_EQ(2, array_values[1]);
diff --git a/src/core/tests/symbols_test.cpp b/src/core/tests/symbols_test.cpp
index 1410a05..e5b4649 100644
--- a/src/core/tests/symbols_test.cpp
+++ b/src/core/tests/symbols_test.cpp
@@ -32,14 +32,14 @@ TEST(symbol_test, int_variable)
// readonly integer
variable ro_integer("integer", 10, true);
EXPECT_STREQ("integer", ro_integer.get_name().c_str());
- EXPECT_EQ(10, ro_integer.get_value<int>());
+ EXPECT_EQ(10, ro_integer.get_value<long>());
EXPECT_THROW(ro_integer.set_value(100), libbash::interpreter_exception);
- EXPECT_EQ(10, ro_integer.get_value<int>());
+ EXPECT_EQ(10, ro_integer.get_value<long>());
// normal only integer
variable normal_integer("integer", 10);
normal_integer.set_value(100);
- EXPECT_EQ(100, normal_integer.get_value<int>());
+ EXPECT_EQ(100, normal_integer.get_value<long>());
// get string value of an integer
EXPECT_STREQ("100", normal_integer.get_value<string>().c_str());
@@ -61,9 +61,9 @@ TEST(symbol_test, string_variable)
// string contains integer value
variable int_string("string", "123");
- EXPECT_EQ(123, int_string.get_value<int>());
+ EXPECT_EQ(123, int_string.get_value<long>());
int_string.set_value("abc");
- EXPECT_EQ(0, int_string.get_value<int>());
+ EXPECT_EQ(0, int_string.get_value<long>());
}
TEST(symbol_test, array_variable)
@@ -92,7 +92,7 @@ TEST(symbol_test, array_variable)
EXPECT_STREQ("5", normal_array.get_value<string>(4).c_str());
// get integer value
- EXPECT_EQ(3, normal_array.get_value<int>(2));
+ EXPECT_EQ(3, normal_array.get_value<long>(2));
}
TEST(symbol_test, get_all_values)
@@ -114,7 +114,7 @@ TEST(symbol_test, get_all_values)
EXPECT_STREQ("1", string_values[0].c_str());
variable an_int("foo", 10);
- vector<int> int_values;
+ vector<long> int_values;
an_int.get_all_values(int_values);
EXPECT_EQ(1, int_values.size());
EXPECT_EQ(10, int_values[0]);