public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [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