* [gentoo-commits] proj/libbash:master commit in: src/, scripts/, /, src/core/, test/, src/core/tests/, utils/, src/builtins/
@ 2011-05-13 11:06 Petteri Räty
0 siblings, 0 replies; only message in thread
From: Petteri Räty @ 2011-05-13 11:06 UTC (permalink / raw
To: gentoo-commits
commit: fbbffbf9fe8d4a56535335e6e45db20f6e4ae3a2
Author: Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Fri May 13 09:07:07 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Fri May 13 11:08:35 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=fbbffbf9
Core&Utility: return non zero exit status on failure
The public API, ast_printer and bash_ast are refactored to return
non zero exit status on failure.
---
Makefile.am | 2 +
scripts/illegal_script.sh | 1 +
src/builtins/source_builtin.cpp | 5 ++-
src/core/bash_ast.cpp | 26 ++++++++--
src/core/bash_ast.h | 5 ++
.../core/tests/bash_ast_test.cpp | 30 ++++++++---
src/libbash.cpp | 12 +++-
src/libbash.h | 7 ++-
test/api_test.cpp | 28 ++++++++++-
test/ast_printer_test.sh | 12 +++++
utils/ast_printer.cpp | 52 ++++++++++++--------
11 files changed, 137 insertions(+), 43 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 3d26460..f117196 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -99,6 +99,7 @@ check_PROGRAMS = cppunittests
cppunittests_SOURCES = test/run_tests.cpp \
src/core/tests/symbols_test.cpp \
src/core/tests/interpreter_test.cpp \
+ src/core/tests/bash_ast_test.cpp \
src/builtins/tests/echo_tests.cpp \
src/builtins/tests/boolean_tests.cpp \
src/builtins/tests/source_tests.cpp \
@@ -208,6 +209,7 @@ EXTRA_DIST = bashast/bashast.g \
scripts/source_false.sh \
scripts/source_true.sh \
scripts/source_return.sh \
+ scripts/illegal_script.sh \
utils/meta_gen.sh \
scripts/foo.eclass \
$(BASH_TESTS) \
diff --git a/scripts/illegal_script.sh b/scripts/illegal_script.sh
new file mode 100644
index 0000000..9a33383
--- /dev/null
+++ b/scripts/illegal_script.sh
@@ -0,0 +1 @@
+case
diff --git a/src/builtins/source_builtin.cpp b/src/builtins/source_builtin.cpp
index 277eb94..383b716 100644
--- a/src/builtins/source_builtin.cpp
+++ b/src/builtins/source_builtin.cpp
@@ -25,6 +25,7 @@
#include "builtins/source_builtin.h"
#include <fstream>
+#include <iostream>
#include <string>
#include <unordered_map>
@@ -52,8 +53,10 @@ int source_builtin::exec(const std::vector<std::string>& bash_args)
throw interpreter_exception(path + " can't be read");
stored_ast.reset(new bash_ast(input));
+ if(stored_ast->get_error_count())
+ std::cerr << path << " could not be parsed properly" << std::endl;
}
-
+
try
{
stored_ast->interpret_with(_walker);
diff --git a/src/core/bash_ast.cpp b/src/core/bash_ast.cpp
index 3010774..0bf8938 100644
--- a/src/core/bash_ast.cpp
+++ b/src/core/bash_ast.cpp
@@ -27,11 +27,12 @@
#include <sstream>
#include "core/interpreter_exception.h"
+#include "core/interpreter.h"
#include "libbashLexer.h"
#include "libbashParser.h"
#include "libbashWalker.h"
-bash_ast::bash_ast(std::istream& source)
+bash_ast::bash_ast(std::istream& source): error_count(0)
{
std::stringstream stream;
stream << source.rdbuf();
@@ -41,6 +42,10 @@ bash_ast::bash_ast(std::istream& source)
reinterpret_cast<pANTLR3_UINT8>(const_cast<char*>(script.c_str())),
script.size(),
NULL);
+
+ if(input == NULL)
+ throw interpreter_exception("Unable to open file " + script + " due to malloc() failure");
+
init_parser();
}
@@ -57,18 +62,31 @@ void bash_ast::init_parser()
{
lxr = libbashLexerNew(input);
if ( lxr == NULL )
- throw interpreter_exception("Unable to create the lexer due to malloc() failure");
+ {
+ std::cerr << "Unable to create the lexer due to malloc() failure" << std::endl;
+ error_count = 1;
+ return;
+ }
tstream = antlr3CommonTokenStreamSourceNew(
ANTLR3_SIZE_HINT, lxr->pLexer->rec->state->tokSource);
if (tstream == NULL)
- throw interpreter_exception("Out of memory trying to allocate token stream");
+ {
+ std::cerr << "Out of memory trying to allocate token stream" << std::endl;
+ error_count = 1;
+ return;
+ }
psr = libbashParserNew(tstream);
if (psr == NULL)
- throw interpreter_exception("Out of memory trying to allocate parser");
+ {
+ std::cerr << "Out of memory trying to allocate parser" << std::endl;
+ error_count = 1;
+ return;
+ }
langAST.reset(new libbashParser_start_return(psr->start(psr)));
+ error_count = psr->pParser->rec->getNumberOfSyntaxErrors(psr->pParser->rec);
nodes = antlr3CommonTreeNodeStreamNewTree(langAST->tree, ANTLR3_SIZE_HINT);
}
diff --git a/src/core/bash_ast.h b/src/core/bash_ast.h
index d7ae27c..e587d81 100644
--- a/src/core/bash_ast.h
+++ b/src/core/bash_ast.h
@@ -48,12 +48,17 @@ class bash_ast
libbashParser_Ctx_struct* psr;
std::unique_ptr<libbashParser_start_return_struct> langAST;
pANTLR3_COMMON_TREE_NODE_STREAM nodes;
+ int error_count;
void init_parser();
public:
explicit bash_ast(std::istream& source);
~bash_ast();
+ int get_error_count() const
+ {
+ return error_count;
+ }
///
/// \brief interpret the script with a given interpreter
/// \param the interpreter object
diff --git a/test/api_test.cpp b/src/core/tests/bash_ast_test.cpp
similarity index 54%
copy from test/api_test.cpp
copy to src/core/tests/bash_ast_test.cpp
index 813c3b0..9c4421c 100644
--- a/test/api_test.cpp
+++ b/src/core/tests/bash_ast_test.cpp
@@ -17,21 +17,33 @@
along with libbash. If not, see <http://www.gnu.org/licenses/>.
*/
///
-/// \file api_test.cpp
+/// \file bash_ast_test.cpp
/// \author Mu Qiao
-/// \brief series of unit tests for the public interface
+/// \brief series of unit tests for interpreter.
///
+#include <fstream>
+#include <string>
+
#include <gtest/gtest.h>
-#include "libbash.h"
+#include "core/bash_ast.h"
+#include "test.h"
-using namespace std;
+TEST(bash_ast, parse_illegal_script)
+{
+ std::ifstream input(get_src_dir() + std::string("/scripts/illegal_script.sh"));
+ bash_ast ast(input);
+ EXPECT_NE(0, ast.get_error_count());
+}
-TEST(libbashapi, bad_path)
+TEST(bash_ast, parse_legal_script)
{
- std::unordered_map<std::string, std::vector<std::string>> variables;
- std::vector<std::string> functions;
- EXPECT_THROW(libbash::interpret("not exist", variables, functions),
- interpreter_exception);
+ std::ifstream input(get_src_dir() + std::string("/scripts/source_true.sh"));
+ bash_ast ast(input);
+ EXPECT_EQ(0, ast.get_error_count());
+
+ std::ifstream input2(get_src_dir() + std::string("/scripts/source_false.sh"));
+ bash_ast ast2(input2);
+ EXPECT_EQ(0, ast2.get_error_count());
}
diff --git a/src/libbash.cpp b/src/libbash.cpp
index f04064d..bd354b3 100644
--- a/src/libbash.cpp
+++ b/src/libbash.cpp
@@ -31,10 +31,12 @@
namespace libbash
{
- void interpret(const std::string& path,
- std::unordered_map<std::string, std::vector<std::string>>& variables,
- std::vector<std::string>& functions)
+ int interpret(const std::string& path,
+ std::unordered_map<std::string, std::vector<std::string>>& variables,
+ std::vector<std::string>& functions)
{
+ int result;
+
std::ifstream input(path.c_str());
if(!input)
throw interpreter_exception("Unable to create fstream for script: " + path);
@@ -46,9 +48,13 @@ namespace libbash
bash_ast ast(input);
ast.interpret_with(walker);
+ result = ast.get_error_count();
for(auto iter = walker.begin(); iter != walker.end(); ++iter)
iter->second->get_all_values<std::string>(variables[iter->first]);
walker.get_all_function_names(functions);
+
+ result += walker.get_status();
+ return result;
}
}
diff --git a/src/libbash.h b/src/libbash.h
index 3f903e9..261d207 100644
--- a/src/libbash.h
+++ b/src/libbash.h
@@ -41,9 +41,10 @@ namespace libbash
/// \param the path of target script
/// \param[in, out] we use the map to initialize bash environment and store the result
/// \param[out] store the names of the functions defined in the script
- void LIBBASH_API interpret(const std::string& path,
- std::unordered_map<std::string, std::vector<std::string>>& variables,
- std::vector<std::string>& functions);
+ /// \return the return status of the script
+ int LIBBASH_API interpret(const std::string& path,
+ std::unordered_map<std::string, std::vector<std::string>>& variables,
+ std::vector<std::string>& functions);
}
#endif
diff --git a/test/api_test.cpp b/test/api_test.cpp
index 813c3b0..8746a0a 100644
--- a/test/api_test.cpp
+++ b/test/api_test.cpp
@@ -25,8 +25,7 @@
#include <gtest/gtest.h>
#include "libbash.h"
-
-using namespace std;
+#include "test.h"
TEST(libbashapi, bad_path)
{
@@ -35,3 +34,28 @@ TEST(libbashapi, bad_path)
EXPECT_THROW(libbash::interpret("not exist", variables, functions),
interpreter_exception);
}
+
+TEST(libbashapi, illegal_script)
+{
+ std::unordered_map<std::string, std::vector<std::string>> variables;
+ std::vector<std::string> functions;
+ int result = libbash::interpret(get_src_dir() + "/scripts/illegal_script.sh",
+ variables,
+ functions);
+ EXPECT_NE(0, result);
+}
+
+TEST(libbashapi, legal_script)
+{
+ std::unordered_map<std::string, std::vector<std::string>> variables;
+ std::vector<std::string> functions;
+ int result = libbash::interpret(get_src_dir() + std::string("/scripts/source_true.sh"),
+ variables,
+ functions);
+ EXPECT_EQ(0, result);
+
+ result = libbash::interpret(get_src_dir() + std::string("/scripts/source_false.sh"),
+ variables,
+ functions);
+ EXPECT_NE(0, result);
+}
diff --git a/test/ast_printer_test.sh b/test/ast_printer_test.sh
index 6549921..e0c930f 100755
--- a/test/ast_printer_test.sh
+++ b/test/ast_printer_test.sh
@@ -10,4 +10,16 @@ error+=$?
| diff -u $srcdir/bashast/features_script/features.sh.tokens -
error+=$?
+./ast_printer -f $srcdir/bashast/features_script/illegal_script.sh 2 > /dev/null
+if [[ $? == 0 ]]
+then
+ error+=1
+fi
+
+./ast_printer -e "case" 2 > /dev/null
+if [[ $? == 0 ]]
+then
+ error+=1
+fi
+
exit $error
diff --git a/utils/ast_printer.cpp b/utils/ast_printer.cpp
index dae4233..b7dcfc1 100644
--- a/utils/ast_printer.cpp
+++ b/utils/ast_printer.cpp
@@ -48,17 +48,19 @@ BOOST_FUSION_ADAPT_STRUCT(
(ANTLR3_INT32, first)
)
-static void print_ast(std::istream& input, bool silent, bool dot)
+static int print_ast(std::istream& input, bool silent, bool dot)
{
bash_ast ast(input);
if(silent)
- return;
+ return ast.get_error_count();
if(dot)
std::cout << ast.get_dot_graph() << std::endl;
else
std::cout << ast.get_string_tree() << std::endl;
+
+ return ast.get_error_count();
}
static inline std::string token_mapper(std::unordered_map<ANTLR3_INT32, std::string> token_map,
@@ -83,12 +85,12 @@ static bool build_token_map(std::unordered_map<ANTLR3_INT32, std::string>& token
return qi::parse(first, last, line % qi::eol >> qi::eol, token_map) && first == last;
}
-static inline void print_token(std::istream& input,
- const std::string& token_path,
- bool silent)
+static int print_token(std::istream& input,
+ const std::string& token_path,
+ bool silent)
{
if(silent)
- return;
+ return 0;
bash_ast ast(input);
std::unordered_map<ANTLR3_INT32, std::string> token_map;
@@ -99,37 +101,42 @@ static inline void print_token(std::istream& input,
token_map,
std::placeholders::_1))
<< std::endl;
+ return ast.get_error_count();
}
else
{
std::cerr << "Building token map failed" << std::endl;
+ return ast.get_error_count() + 1;
}
}
-static void print_files(const std::vector<std::string>& files,
+static int print_files(const std::vector<std::string>& files,
bool print_name,
- std::function<void(std::istream&)> printer)
+ std::function<int(std::istream&)> printer)
{
+ int result = 0;
for(auto iter = files.begin(); iter != files.end(); ++iter)
{
if(print_name)
std::cout << "Interpreting " << *iter << std::endl;
std::ifstream input(iter->c_str());
- printer(input);
+ result += printer(input);
}
+
+ return result;
}
-static inline void print_expression(const std::string& expr,
- std::function<void(std::istream&)> printer)
+static inline int print_expression(const std::string& expr,
+ std::function<int(std::istream&)> printer)
{
std::istringstream input(expr);
- printer(input);
+ return printer(input);
}
-static inline void print_cin(std::function<void(std::istream&)> printer)
+static inline int print_cin(std::function<int(std::istream&)> printer)
{
- printer(std::cin);
+ return printer(std::cin);
}
int main(int argc, char** argv)
@@ -158,10 +165,10 @@ int main(int argc, char** argv)
if(vm.count("help"))
{
std::cout << desc << std::endl;
- return 1;
+ return EXIT_FAILURE;
}
- std::function<void(std::istream&)> printer;
+ std::function<int(std::istream&)> printer;
if(vm.count("token"))
printer = std::bind(&print_token,
std::placeholders::_1,
@@ -173,12 +180,15 @@ int main(int argc, char** argv)
vm.count("silent"),
vm.count("dot"));
+ int result;
if(vm.count("files"))
- print_files(vm["files"].as<std::vector<std::string>>(),
- vm.count("name"),
- printer);
+ result = print_files(vm["files"].as<std::vector<std::string>>(),
+ vm.count("name"),
+ printer);
else if(vm.count("expr"))
- print_expression(vm["expr"].as<std::string>(), printer);
+ result = print_expression(vm["expr"].as<std::string>(), printer);
else
- print_cin(printer);
+ result = print_cin(printer);
+
+ return result;
}
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2011-05-13 11:06 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-13 11:06 [gentoo-commits] proj/libbash:master commit in: src/, scripts/, /, src/core/, test/, src/core/tests/, utils/, src/builtins/ Petteri Räty
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox