public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Petteri Räty" <betelgeuse@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/libbash:master commit in: /, src/core/, src/core/tests/
Date: Fri, 27 May 2011 23:03:24 +0000 (UTC)	[thread overview]
Message-ID: <a6e8bcfd05d72ca16ea786aa78106111b7a4d15e.betelgeuse@gentoo> (raw)

commit:     a6e8bcfd05d72ca16ea786aa78106111b7a4d15e
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Thu May 26 10:42:50 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Fri May 27 08:45:41 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=a6e8bcfd

Core: adjust interpreter to support unset

We didn't not handle local variables and the interface was not
helpful. Now the implementation is adjusted to support unset
built-in. As we don't support read only functions, unsetting
functions will always return true.

---
 Makefile.am                         |    1 +
 src/core/interpreter.cpp            |   60 ++++++++++++++++++++++++++--------
 src/core/interpreter.h              |    4 ++
 src/core/tests/interpreter_test.cpp |   59 +++++++++++++++++++++++++++++-----
 src/core/unset_exception.h          |   44 +++++++++++++++++++++++++
 5 files changed, 145 insertions(+), 23 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 86c2583..3b72d46 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -193,6 +193,7 @@ libcppbash_la_SOURCES = src/common.h \
 						$(GENERATED_PARSER_C) \
 						$(GENERATED_PARSER_H) \
 						src/core/interpreter_exception.h \
+						src/core/unset_exception.h \
 						src/core/interpreter.cpp \
 						src/core/interpreter.h \
 						src/core/symbols.hpp \

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index 2337e87..41bc7b5 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -22,8 +22,6 @@
 /// \brief implementations for bash interpreter (visitor pattern).
 ///
 
-#include "core/interpreter.h"
-
 #include <cctype>
 
 #include <functional>
@@ -37,8 +35,11 @@
 #include <boost/range/adaptor/map.hpp>
 #include <boost/range/algorithm/copy.hpp>
 
+#include "core/unset_exception.h"
 #include "libbashWalker.h"
 
+#include "core/interpreter.h"
+
 interpreter::interpreter(): out(&std::cout), err(&std::cerr), in(&std::cin), bash_options(
     {
       {"autocd", false},
@@ -341,25 +342,56 @@ void interpreter::get_all_function_names(std::vector<std::string>& function_name
   boost::copy(functions | boost::adaptors::map_keys, back_inserter(function_names));
 }
 
+namespace
+{
+  void check_unset_positional(const std::string& name)
+  {
+    // Unsetting positional parameters is not allowed
+    if(isdigit(name[0]))
+      throw unset_exception("unset: not a valid identifier");
+  }
+}
+
 void interpreter::unset(const std::string& name)
 {
-  auto iter = members.find(name);
-  if(iter == members.end())
-    return;
-  else if(iter->second->is_readonly())
-    throw interpreter_exception("Can't unset readonly variable " + name);
-  else
-    members.erase(name);
+  check_unset_positional(name);
+
+  auto unsetter = [&](scope& frame) -> bool {
+    auto iter_local = frame.find(name);
+    if(iter_local != frame.end())
+    {
+      if(iter_local->second->is_readonly())
+        throw unset_exception("unset a readonly variable");
+      frame.erase(iter_local);
+      return true;
+    }
+    return false;
+  };
+
+  if(std::none_of(local_members.rbegin(), local_members.rend(), unsetter))
+    unsetter(members);
+}
+
+// We need to return false when unsetting readonly functions in future
+void interpreter::unset_function(const std::string& name)
+{
+  auto function = functions.find(name);
+  if(function != functions.end())
+    functions.erase(name);
 }
 
 void interpreter::unset(const std::string& name,
                         const unsigned index)
 {
-  auto iter = members.find(name);
-  if(iter == members.end())
-    return;
-  else
-    iter->second->unset_value(index);
+  check_unset_positional(name);
+
+  auto var = resolve_variable(name);
+  if(var)
+  {
+    if(var->is_readonly())
+      throw unset_exception("unset a readonly variable");
+    var->unset_value(index);
+  }
 }
 
 bool interpreter::get_option(const std::string& name) const

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index f35b8ff..3420ee4 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -502,6 +502,10 @@ public:
   /// \param the name of the variable
   void unset(const std::string& name);
 
+  /// \brief unset a function
+  /// \param the name of the function
+  void unset_function(const std::string& name);
+
   /// \brief unset a array member
   /// \param the name of the array
   /// \param the index of the member

diff --git a/src/core/tests/interpreter_test.cpp b/src/core/tests/interpreter_test.cpp
index ab24449..d64866f 100644
--- a/src/core/tests/interpreter_test.cpp
+++ b/src/core/tests/interpreter_test.cpp
@@ -25,6 +25,7 @@
 #include <gtest/gtest.h>
 
 #include "core/interpreter.h"
+#include "core/unset_exception.h"
 
 using namespace std;
 
@@ -143,31 +144,71 @@ TEST(interpreter, get_array_values)
   EXPECT_FALSE(walker.resolve_array("undefined", array_values));
 }
 
-TEST(interpreter, unset_values)
+TEST(interpreter, unset_arrays)
 {
   interpreter walker;
   std::map<int, std::string> values = {{0, "1"}, {1, "2"}, {2, "3"}};
   walker.define("array", values);
   walker.define("ro_array", values, true);
-  walker.define("var", "123");
-  walker.define("ro_var", "123", true);
-
+  interpreter::local_scope temp_scope(walker);
+  values[0] = "local";
+  walker.define_local("array", values);
+  walker.define_local("ro_local_array", values, true);
+
+  // unset arrays
+  EXPECT_STREQ("local", walker.resolve<string>("array", 0).c_str());
+  // unset local
+  walker.unset("array", 0);
+  EXPECT_STREQ("", walker.resolve<string>("array", 0).c_str());
+  // unset local
+  walker.unset("array");
+  // resolve to global
+  EXPECT_STREQ("1", walker.resolve<string>("array", 0).c_str());
   EXPECT_STREQ("2", walker.resolve<string>("array", 1).c_str());
-  walker.unset("array", 1);
-  EXPECT_STREQ("", walker.resolve<string>("array", 1).c_str());
+  EXPECT_STREQ("3", walker.resolve<string>("array", 2).c_str());
+  // unset global
   walker.unset("array");
   EXPECT_STREQ("", walker.resolve<string>("array", 0).c_str());
   EXPECT_STREQ("", walker.resolve<string>("array", 1).c_str());
   EXPECT_STREQ("", walker.resolve<string>("array", 2).c_str());
+  walker.unset("array");
+
+  EXPECT_THROW(walker.unset("ro_array", 1), unset_exception);
+  EXPECT_THROW(walker.unset("ro_local_array", 1), unset_exception);
+  EXPECT_THROW(walker.unset("ro_array"), unset_exception);
+  EXPECT_THROW(walker.unset("ro_local_array"), unset_exception);
+
+  EXPECT_THROW(walker.unset("1", 1), interpreter_exception);
+}
 
-  EXPECT_THROW(walker.unset("ro_array", 1), interpreter_exception);
-  EXPECT_THROW(walker.unset("ro_array"), interpreter_exception);
+TEST(interpreter, unset_variables)
+{
+  interpreter walker;
+  walker.define("var", "123");
+  walker.define("ro_var", "123", true);
+  interpreter::local_scope temp_scope(walker);
+  walker.define_local("var", 456);
+  walker.define_local("ro_local_var", 456, true);
 
+  EXPECT_STREQ("456", walker.resolve<string>("var").c_str());
+  walker.unset("var");
   EXPECT_STREQ("123", walker.resolve<string>("var").c_str());
   walker.unset("var");
   EXPECT_STREQ("", walker.resolve<string>("var").c_str());
+  walker.unset("var");
+
+  EXPECT_THROW(walker.unset("ro_var"), unset_exception);
+  EXPECT_THROW(walker.unset("ro_local_var"), unset_exception);
+  EXPECT_THROW(walker.unset("1"), interpreter_exception);
+}
 
-  EXPECT_THROW(walker.unset("ro_var"), interpreter_exception);
+TEST(interpreter, unset_functions)
+{
+  interpreter walker;
+  walker.define_function("foo", 0);
+  EXPECT_TRUE(walker.has_function("foo"));
+  walker.unset_function("foo");
+  EXPECT_FALSE(walker.has_function("foo"));
 }
 
 TEST(interperter, substring_expansion_exception)

diff --git a/src/core/unset_exception.h b/src/core/unset_exception.h
new file mode 100644
index 0000000..7ee6c03
--- /dev/null
+++ b/src/core/unset_exception.h
@@ -0,0 +1,44 @@
+/*
+   Please use git log for copyright holder and year information
+
+   This file is part of libbash.
+
+   libbash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 2 of the License, or
+   (at your option) any later version.
+
+   libbash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with libbash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+///
+/// \file unset_exception.h
+/// \author Mu Qiao
+/// \brief implementation for unset_exception
+///
+
+#ifndef LIBBASH_CORE_UNSET_EXCEPTION_H_
+#define LIBBASH_CORE_UNSET_EXCEPTION_H_
+
+#include <stdexcept>
+#include <string>
+
+#include "interpreter_exception.h"
+
+///
+/// \class unset_exception
+/// \brief exception for unsetting variables
+///
+class unset_exception: public interpreter_exception
+{
+public:
+  explicit unset_exception(const std::string& err_msg):
+    interpreter_exception(err_msg){}
+};
+
+#endif



             reply	other threads:[~2011-05-27 23:03 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-27 23:03 Petteri Räty [this message]
  -- strict thread matches above, loose matches on Subject: below --
2011-03-25  9:24 [gentoo-commits] proj/libbash:master commit in: /, src/core/, src/core/tests/ Petteri Räty

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a6e8bcfd05d72ca16ea786aa78106111b7a4d15e.betelgeuse@gentoo \
    --to=betelgeuse@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox