public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/libbash:master commit in: src/, src/builtins/tests/, src/core/, bashast/, test/, src/core/tests/, utils/, ...
@ 2011-06-03 14:42 Petteri Räty
  0 siblings, 0 replies; only message in thread
From: Petteri Räty @ 2011-06-03 14:42 UTC (permalink / raw
  To: gentoo-commits

commit:     5454166103257b3f19b829dbc2c824ad67acf344
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Thu Jun  2 11:27:04 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Fri Jun  3 13:31:00 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=54541661

Core: make error handling POSIX compliant

For a non-interactive shell, an error condition encountered by a special
built-in or other type of utility shall cause the shell to write a
diagnostic message to standard error and exit.

---
 bashast/libbashWalker.g             |    2 +-
 src/builtins/shopt_builtin.cpp      |   38 ++++++--------------
 src/builtins/shopt_builtin.h        |    2 +-
 src/builtins/source_builtin.cpp     |    7 ----
 src/builtins/tests/shopt_tests.cpp  |   40 +++++++++++++--------
 src/builtins/tests/source_tests.cpp |    6 ++--
 src/core/bash_ast.cpp               |   21 +++--------
 src/core/bash_ast.h                 |    6 ---
 src/core/interpreter.cpp            |    2 +-
 src/core/tests/bash_ast_test.cpp    |   10 ++----
 src/libbash.cpp                     |   12 +------
 test/api_test.cpp                   |   17 ++++-----
 utils/ast_printer.cpp               |   66 +++++++++++++++++------------------
 utils/variable_printer.cpp          |   10 +++++-
 14 files changed, 99 insertions(+), 140 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index bbf442c..3bb0f40 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -494,8 +494,8 @@ execute_command[const std::string& name, std::vector<std::string>& libbash_args]
 		}
 		else
 		{
-			std::cerr << name << " is not supported yet" << std::endl;
 			walker->set_status(1);
+			throw interpreter_exception(name + " is not supported yet");
 		}
 	}
 	(BANG { walker->set_status(!walker->get_status()); })?;

diff --git a/src/builtins/shopt_builtin.cpp b/src/builtins/shopt_builtin.cpp
index e9e239a..45e564c 100644
--- a/src/builtins/shopt_builtin.cpp
+++ b/src/builtins/shopt_builtin.cpp
@@ -27,49 +27,33 @@
 #include "core/interpreter_exception.h"
 #include "cppbash_builtin.h"
 
-int shopt_builtin::set_opt(const std::vector<std::string>& bash_args, bool value)
+void shopt_builtin::set_opt(const std::vector<std::string>& bash_args, bool value)
 {
-  int result = 0;
   for(auto iter = bash_args.begin() + 1; iter != bash_args.end(); ++iter)
-  {
-    try
-    {
       _walker.set_option(*iter, value);
-    }
-    catch(interpreter_exception& e)
-    {
-      std::cerr << *iter << " is not a valid bash option" << std::endl;
-      result = 1;
-    }
-  }
-  return result;
 }
 
 int shopt_builtin::exec(const std::vector<std::string>& bash_args)
 {
   if(bash_args.empty())
-  {
-    *_err_stream << "Arguments required for shopt" << std::endl;
-    return 1;
-  }
+    throw interpreter_exception("Arguments required for shopt");
   else if(bash_args[0].size() != 2)
-  {
-    *_err_stream << "Multiple arguments are not supported" << std::endl;
-    return 1;
-  }
+    throw interpreter_exception("Multiple arguments are not supported");
 
   switch(bash_args[0][1])
   {
     case 'u':
-      return set_opt(bash_args, false);
+      set_opt(bash_args, false);
+      break;
     case 's':
-      return set_opt(bash_args, true);
+      set_opt(bash_args, true);
+      break;
     case 'q':
     case 'o':
-      *_err_stream << "shopt " << bash_args[0] << " is not supported yet" << std::endl;
-      return 1;
+      throw interpreter_exception("shopt " + bash_args[0] + " is not supported yet");
     default:
-      *_err_stream << "Unrecognized option for shopt: " << bash_args[0] << std::endl;
-      return 1;
+      throw interpreter_exception("Unrecognized option for shopt: " + bash_args[0]);
   }
+
+  return 0;
 }

diff --git a/src/builtins/shopt_builtin.h b/src/builtins/shopt_builtin.h
index d274dc3..905e4ba 100644
--- a/src/builtins/shopt_builtin.h
+++ b/src/builtins/shopt_builtin.h
@@ -27,7 +27,7 @@
 
 class shopt_builtin : public virtual cppbash_builtin
 {
-  int set_opt(const std::vector<std::string>& bash_args, bool value);
+  void set_opt(const std::vector<std::string>& bash_args, bool value);
 public:
   BUILTIN_CONSTRUCTOR(shopt)
   virtual int exec(const std::vector<std::string>& );

diff --git a/src/builtins/source_builtin.cpp b/src/builtins/source_builtin.cpp
index 4103576..6d43463 100644
--- a/src/builtins/source_builtin.cpp
+++ b/src/builtins/source_builtin.cpp
@@ -46,14 +46,7 @@ int source_builtin::exec(const std::vector<std::string>& bash_args)
 
   auto& stored_ast = ast_cache[path];
   if(!stored_ast)
-  {
     stored_ast.reset(new bash_ast(path));
-    if(stored_ast->get_error_count())
-    {
-      std::cerr << path << " could not be parsed properly" << std::endl;
-      return 1;
-    }
-  }
 
   const std::string& original_path = _walker.resolve<std::string>("0");
   try

diff --git a/src/builtins/tests/shopt_tests.cpp b/src/builtins/tests/shopt_tests.cpp
index e8cd013..8d53434 100644
--- a/src/builtins/tests/shopt_tests.cpp
+++ b/src/builtins/tests/shopt_tests.cpp
@@ -26,11 +26,27 @@
 #include "core/interpreter.h"
 #include "cppbash_builtin.h"
 
-TEST(shopt_builtin_test, disable_extglob)
+static void test_shopt_builtin(const std::string& expected, const std::vector<std::string>& args)
 {
+  std::stringstream output;
   interpreter walker;
-  EXPECT_EQ(1, cppbash_builtin::exec("shopt", {"-u", "not exist"}, std::cout, std::cerr, std::cin, walker));
+  try
+  {
+    cppbash_builtin::exec("shopt", args, std::cout, output, std::cin, walker);
+    FAIL();
+  }
+  catch(interpreter_exception& e)
+  {
+    EXPECT_STREQ(expected.c_str(), e.what());
+  }
+}
+
 
+TEST(shopt_builtin_test, disable_extglob)
+{
+  test_shopt_builtin("not exist is not a valid bash option", {"-u", "not exist"});
+
+  interpreter walker;
   walker.set_option("autocd", true);
   EXPECT_EQ(0, cppbash_builtin::exec("shopt", {"-u", "autocd", "cdspell"}, std::cout, std::cerr, std::cin, walker));
   EXPECT_FALSE(walker.get_option("autocd"));
@@ -39,26 +55,18 @@ TEST(shopt_builtin_test, disable_extglob)
 
 TEST(shopt_builtin_test, enable_extglob)
 {
-  interpreter walker;
-  EXPECT_EQ(1, cppbash_builtin::exec("shopt", {"-s", "not exist"}, std::cout, std::cerr, std::cin, walker));
+  test_shopt_builtin("not exist is not a valid bash option", {"-s", "not exist"});
 
+  interpreter walker;
   EXPECT_EQ(0, cppbash_builtin::exec("shopt", {"-s", "autocd", "cdspell"}, std::cout, std::cerr, std::cin, walker));
   EXPECT_TRUE(walker.get_option("autocd"));
   EXPECT_TRUE(walker.get_option("cdspell"));
 }
 
-static void test_shopt_builtin(const std::string& expected, const std::vector<std::string>& args, int status)
-{
-  std::stringstream output;
-  interpreter walker;
-  EXPECT_EQ(status, cppbash_builtin::exec("shopt", args, std::cout, output, std::cin, walker));
-  EXPECT_STREQ(expected.c_str(), output.str().c_str());
-}
-
 TEST(shopt_builtin_test, invalid_argument)
 {
-  test_shopt_builtin("Arguments required for shopt\n", {}, 1);
-  test_shopt_builtin("Multiple arguments are not supported\n", {"-so"}, 1);
-  test_shopt_builtin("shopt -q is not supported yet\n", {"-q"}, 1);
-  test_shopt_builtin("Unrecognized option for shopt: -d\n", {"-d"}, 1);
+  test_shopt_builtin("Arguments required for shopt", {});
+  test_shopt_builtin("Multiple arguments are not supported", {"-so"});
+  test_shopt_builtin("shopt -q is not supported yet", {"-q"});
+  test_shopt_builtin("Unrecognized option for shopt: -d", {"-d"});
 }

diff --git a/src/builtins/tests/source_tests.cpp b/src/builtins/tests/source_tests.cpp
index b051de3..e1fecee 100644
--- a/src/builtins/tests/source_tests.cpp
+++ b/src/builtins/tests/source_tests.cpp
@@ -84,11 +84,11 @@ TEST(source_builtin_test, invalid)
                                      std::cin,
                                      walker),
                interpreter_exception);
-  int status = cppbash_builtin::exec("source",
+  EXPECT_THROW(cppbash_builtin::exec("source",
                                      {get_src_dir() + "/scripts/illegal_script.sh"},
                                      std::cout,
                                      std::cerr,
                                      std::cin,
-                                     walker);
-  EXPECT_NE(status, 0);
+                                     walker),
+               interpreter_exception);
 }

diff --git a/src/core/bash_ast.cpp b/src/core/bash_ast.cpp
index 8eafb3e..8f06311 100644
--- a/src/core/bash_ast.cpp
+++ b/src/core/bash_ast.cpp
@@ -78,31 +78,20 @@ void bash_ast::init_parser(const std::string& script, const std::string& script_
 
   lexer = libbashLexerNew(input);
   if ( lexer == NULL )
-  {
-    std::cerr << "Unable to create the lexer due to malloc() failure" << std::endl;
-    error_count = 1;
-    return;
-  }
+    throw interpreter_exception("Unable to create the lexer due to malloc() failure");
 
   token_stream = antlr3CommonTokenStreamSourceNew(
       ANTLR3_SIZE_HINT, lexer->pLexer->rec->state->tokSource);
   if (token_stream == NULL)
-  {
-    std::cerr << "Out of memory trying to allocate token stream" << std::endl;
-    error_count = 1;
-    return;
-  }
+    throw interpreter_exception("Out of memory trying to allocate token stream");
 
   parser = libbashParserNew(token_stream);
   if (parser == NULL)
-  {
-    std::cerr << "Out of memory trying to allocate parser" << std::endl;
-    error_count = 1;
-    return;
-  }
+    throw interpreter_exception("Out of memory trying to allocate parser");
 
   ast = parse(parser);
-  error_count = parser->pParser->rec->getNumberOfSyntaxErrors(parser->pParser->rec);
+  if(parser->pParser->rec->getNumberOfSyntaxErrors(parser->pParser->rec))
+    throw interpreter_exception("Something wrong happened while parsing");
   nodes = antlr3CommonTreeNodeStreamNewTree(ast, ANTLR3_SIZE_HINT);
 }
 

diff --git a/src/core/bash_ast.h b/src/core/bash_ast.h
index dab71f5..d5d7f83 100644
--- a/src/core/bash_ast.h
+++ b/src/core/bash_ast.h
@@ -51,7 +51,6 @@ class bash_ast: public boost::noncopyable
   libbashParser_Ctx_struct* parser;
   pANTLR3_BASE_TREE ast;
   pANTLR3_COMMON_TREE_NODE_STREAM nodes;
-  unsigned error_count;
   std::function<pANTLR3_BASE_TREE(libbashParser_Ctx_struct*)> parse;
 
   void init_parser(const std::string& script, const std::string& script_path);
@@ -65,11 +64,6 @@ public:
 
   ~bash_ast();
 
-  unsigned get_error_count() const
-  {
-    return error_count;
-  }
-
   static void walker_start(plibbashWalker tree_parser);
 
   static int walker_arithmetics(plibbashWalker tree_parser);

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index 378c3d2..b0d32c0 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -414,7 +414,7 @@ void interpreter::set_option(const std::string& name, bool value)
 {
   auto iter = bash_options.find(name);
   if(iter == bash_options.end())
-    throw interpreter_exception("Invalid bash option");
+    throw interpreter_exception(name + " is not a valid bash option");
 
   iter->second = value;
 }

diff --git a/src/core/tests/bash_ast_test.cpp b/src/core/tests/bash_ast_test.cpp
index d335d80..0b94d67 100644
--- a/src/core/tests/bash_ast_test.cpp
+++ b/src/core/tests/bash_ast_test.cpp
@@ -33,17 +33,13 @@
 
 TEST(bash_ast, parse_illegal_script)
 {
-  bash_ast ast(get_src_dir() + std::string("/scripts/illegal_script.sh"));
-  EXPECT_NE(0, ast.get_error_count());
+  EXPECT_THROW(bash_ast ast(get_src_dir() + std::string("/scripts/illegal_script.sh")), interpreter_exception);
 }
 
 TEST(bash_ast, parse_legal_script)
 {
-  bash_ast ast(get_src_dir() + std::string("/scripts/source_true.sh"));
-  EXPECT_EQ(0, ast.get_error_count());
-
-  bash_ast ast2(get_src_dir() + std::string("/scripts/source_false.sh"));
-  EXPECT_EQ(0, ast2.get_error_count());
+  bash_ast(get_src_dir() + std::string("/scripts/source_true.sh"));
+  bash_ast(get_src_dir() + std::string("/scripts/source_false.sh"));
 }
 
 TEST(bash_ast, parse_arithmetics)

diff --git a/src/libbash.cpp b/src/libbash.cpp
index d636f59..98f20b6 100644
--- a/src/libbash.cpp
+++ b/src/libbash.cpp
@@ -37,8 +37,6 @@ namespace internal
                 std::unordered_map<std::string, std::vector<std::string>>& variables,
                 std::vector<std::string>& functions)
   {
-    int result = 0;
-
     // Initialize bash environment
     for(auto iter = variables.begin(); iter != variables.end(); ++iter)
       walker.define(iter->first, (iter->second)[0]);
@@ -47,14 +45,12 @@ namespace internal
 
     bash_ast ast(path);
     ast.interpret_with(walker);
-    result += boost::numeric_cast<int>(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;
+    return walker.get_status();
   }
 }
 
@@ -78,12 +74,6 @@ namespace libbash
     // Preloading
     bash_ast preload_ast(preload_path);
     preload_ast.interpret_with(walker);
-    int result = boost::numeric_cast<int>(preload_ast.get_error_count());
-    if(result)
-    {
-      std::cerr << "Error occured while preloading" << std::endl;
-      return result;
-    }
 
     return internal::interpret(walker, target_path, variables, functions);
   }

diff --git a/test/api_test.cpp b/test/api_test.cpp
index 7744ebf..38972fe 100644
--- a/test/api_test.cpp
+++ b/test/api_test.cpp
@@ -40,10 +40,8 @@ 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);
+  EXPECT_THROW(libbash::interpret(get_src_dir() + "/scripts/illegal_script.sh", variables, functions),
+               interpreter_exception);
 }
 
 TEST(libbashapi, legal_script)
@@ -78,9 +76,10 @@ TEST(libbashapi, preload)
                               variables,
                               functions);
   EXPECT_NE(0, result);
-  result = libbash::interpret(get_src_dir() + std::string("/scripts/source_true.sh"),
-                              get_src_dir() + std::string("/scripts/illegal_script.sh"),
-                              variables,
-                              functions);
-  EXPECT_NE(0, result);
+
+  EXPECT_THROW(libbash::interpret(get_src_dir() + std::string("/scripts/source_true.sh"),
+                                  get_src_dir() + std::string("/scripts/illegal_script.sh"),
+                                  variables,
+                                  functions),
+               interpreter_exception);
 }

diff --git a/utils/ast_printer.cpp b/utils/ast_printer.cpp
index b7dcfc1..e55df78 100644
--- a/utils/ast_printer.cpp
+++ b/utils/ast_printer.cpp
@@ -34,6 +34,7 @@
 #include <boost/fusion/include/adapt_struct.hpp>
 
 #include "core/bash_ast.h"
+#include "core/interpreter_exception.h"
 #include "libbashParser.h"
 
 namespace po = boost::program_options;
@@ -48,19 +49,17 @@ BOOST_FUSION_ADAPT_STRUCT(
     (ANTLR3_INT32, first)
 )
 
-static int print_ast(std::istream& input, bool silent, bool dot)
+static void print_ast(std::istream& input, bool silent, bool dot)
 {
   bash_ast ast(input);
 
   if(silent)
-    return ast.get_error_count();
+    return;
 
   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,
@@ -85,58 +84,49 @@ 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 int print_token(std::istream& input,
+static void print_token(std::istream& input,
                        const std::string& token_path,
                        bool silent)
 {
   if(silent)
-    return 0;
+    return;
 
   bash_ast ast(input);
   std::unordered_map<ANTLR3_INT32, std::string> token_map;
 
   if(build_token_map(token_map, token_path))
-  {
     std::cout << ast.get_tokens(std::bind(&token_mapper,
                                           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 int print_files(const std::vector<std::string>& files,
+static void print_files(const std::vector<std::string>& files,
                         bool print_name,
-                        std::function<int(std::istream&)> printer)
+                        std::function<void(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());
-    result += printer(input);
+    printer(input);
   }
-
-  return result;
 }
 
-static inline int print_expression(const std::string& expr,
-                                    std::function<int(std::istream&)> printer)
+static inline void print_expression(const std::string& expr,
+                                    std::function<void(std::istream&)> printer)
 {
   std::istringstream input(expr);
-  return printer(input);
+  printer(input);
 }
 
-static inline int print_cin(std::function<int(std::istream&)> printer)
+static inline void print_cin(std::function<void(std::istream&)> printer)
 {
-  return printer(std::cin);
+  printer(std::cin);
 }
 
 int main(int argc, char** argv)
@@ -168,7 +158,7 @@ int main(int argc, char** argv)
     return EXIT_FAILURE;
   }
 
-  std::function<int(std::istream&)> printer;
+  std::function<void(std::istream&)> printer;
   if(vm.count("token"))
     printer = std::bind(&print_token,
                         std::placeholders::_1,
@@ -180,15 +170,23 @@ int main(int argc, char** argv)
                         vm.count("silent"),
                         vm.count("dot"));
 
-  int result;
-  if(vm.count("files"))
-    result = print_files(vm["files"].as<std::vector<std::string>>(),
-                         vm.count("name"),
-                         printer);
-  else if(vm.count("expr"))
-    result = print_expression(vm["expr"].as<std::string>(), printer);
-  else
-    result = print_cin(printer);
+  try
+  {
+    if(vm.count("files"))
+      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);
+    else
+      print_cin(printer);
+  }
+  catch(interpreter_exception& e)
+  {
+    if(!vm.count("silent"))
+      std::cerr << e.what() << std::endl;
+    return EXIT_FAILURE;
+  }
 
-  return result;
+  return EXIT_SUCCESS;
 }

diff --git a/utils/variable_printer.cpp b/utils/variable_printer.cpp
index 001e75e..252ee9b 100644
--- a/utils/variable_printer.cpp
+++ b/utils/variable_printer.cpp
@@ -46,7 +46,15 @@ int main(int argc, char** argv)
 
   std::unordered_map<std::string, std::vector<std::string>> variables;
   std::vector<std::string> functions;
-  libbash::interpret(argv[1], variables, functions);
+  try
+  {
+    libbash::interpret(argv[1], variables, functions);
+  }
+  catch(interpreter_exception& e)
+  {
+    std::cerr << e.what() << std::endl;
+    return EXIT_FAILURE;
+  }
 
   std::map<std::string, std::vector<std::string>> sorted(variables.begin(), variables.end());
   // Currently we don't need internal variables



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2011-06-03 14:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-03 14:42 [gentoo-commits] proj/libbash:master commit in: src/, src/builtins/tests/, src/core/, bashast/, test/, src/core/tests/, utils/, 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