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
next 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