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: scripts/, src/core/, bashast/, src/core/tests/
Date: Thu, 14 Apr 2011 04:50:14 +0000 (UTC)	[thread overview]
Message-ID: <60fe984fb2c868848a8fb71fe2272a24a78d350a.betelgeuse@gentoo> (raw)

commit:     60fe984fb2c868848a8fb71fe2272a24a78d350a
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Tue Apr 12 13:44:06 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Wed Apr 13 02:46:03 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=60fe984f

Implement array element reference for variable expansion

---
 bashast/libbashWalker.g             |   21 +++++++++++------
 scripts/var_expansion.ebuild        |   13 +++++++++++
 scripts/var_expansion.ebuild.result |   14 ++++++++++++
 src/core/interpreter.h              |   41 ++++++++++++++++++++++++----------
 src/core/symbols.hpp                |   23 +++++++++----------
 src/core/tests/interpreter_test.cpp |   13 ++++++++--
 6 files changed, 90 insertions(+), 35 deletions(-)

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 45034c2..ddeffa0 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -116,23 +116,28 @@ var_name returns[std::string libbash_value, unsigned index]
 
 var_expansion returns[std::string libbash_value]:
 	^(USE_DEFAULT var_name libbash_word=word) {
-		libbash_value = walker->do_default_expansion($var_name.libbash_value, libbash_word);
+		libbash_value = walker->do_default_expansion($var_name.libbash_value, libbash_word, $var_name.index);
 	}
 	|^(ASSIGN_DEFAULT var_name libbash_word=word) {
-		libbash_value = walker->do_assign_expansion($var_name.libbash_value, libbash_word);
+		libbash_value = walker->do_assign_expansion($var_name.libbash_value, libbash_word, $var_name.index);
 	}
 	|^(USE_ALTERNATE var_name libbash_word=word) {
-		libbash_value = walker->do_alternate_expansion($var_name.libbash_value, libbash_word);
+		libbash_value = walker->do_alternate_expansion($var_name.libbash_value, libbash_word, $var_name.index);
 	}
 	|(^(OFFSET var_name arithmetics arithmetics)) => ^(OFFSET var_name offset=arithmetics length=arithmetics) {
-		libbash_value = walker->do_substring_expansion($var_name.libbash_value, offset, length);
+		libbash_value = walker->do_substring_expansion($var_name.libbash_value, offset, length, $var_name.index);
 	}
 	|^(OFFSET var_name offset=arithmetics) {
-		libbash_value = walker->do_substring_expansion($var_name.libbash_value, offset);
-	}
-	|^(POUND var_name) {
-		libbash_value = boost::lexical_cast<std::string>(walker->get_length($var_name.libbash_value));
-	};
+		libbash_value = walker->do_substring_expansion($var_name.libbash_value, offset, $var_name.index);
+	}
+	|^(POUND(
+		var_name {
+			libbash_value = boost::lexical_cast<std::string>(walker->get_length($var_name.libbash_value, $var_name.index));
+		}
+		|^(libbash_name=name_base ARRAY_SIZE) {
+			libbash_value = boost::lexical_cast<std::string>(walker->get_array_length(libbash_name));
+		}
+	));
 
 word returns[std::string libbash_value]:
 	|(num) => libbash_string=num { $libbash_value = libbash_string; }

diff --git a/scripts/var_expansion.ebuild b/scripts/var_expansion.ebuild
index 0045b5e..96b6bf2 100644
--- a/scripts/var_expansion.ebuild
+++ b/scripts/var_expansion.ebuild
@@ -1,3 +1,4 @@
+ARRAY=(hi hello 1 2 3)
 EAPI="3"
 EAPI4="$(($EAPI+1))"
 FOO001="${EAPI:-hello}"
@@ -24,3 +25,15 @@ FOO022=${FOO009: -2:100}
 FOO023=${NOT_EXIST:0:2}
 FOO024=${#FOO009}
 FOO025=${#NOT_EXIST}
+FOO026="${ARRAY[0]:-hello}"
+FOO028="${ARRAY[5]:-hello}"
+FOO029="${ARRAY2[0]:=hello}"
+FOO030="${ARRAY2[0]:=hi}"
+FOO031="${ARRAY2[0]:+hi}"
+FOO032="${ARRAY2[1]:+hi}"
+FOO033="${ARRAY[1]:1}"
+FOO034="${ARRAY[1]:1:3}"
+FOO035="${#ARRAY[0]}"
+FOO036="${#ARRAY[@]}"
+FOO037="${#ARRAY[*]}"
+FOO038="${#ARRAY}"

diff --git a/scripts/var_expansion.ebuild.result b/scripts/var_expansion.ebuild.result
index e7b767a..8bea3b8 100644
--- a/scripts/var_expansion.ebuild.result
+++ b/scripts/var_expansion.ebuild.result
@@ -1,3 +1,5 @@
+ARRAY=hi hello 1 2 3
+ARRAY2=hello
 EAPI=3
 EAPI4=4
 FOO001=3
@@ -25,3 +27,15 @@ FOO022=lo
 FOO023=
 FOO024=5
 FOO025=0
+FOO026=hi
+FOO028=hello
+FOO029=hello
+FOO030=hello
+FOO031=hi
+FOO032=
+FOO033=ello
+FOO034=ell
+FOO035=2
+FOO036=5
+FOO037=5
+FOO038=2

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 5c75bf0..9166379 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -392,11 +392,11 @@ public:
   ///        if the variable is undefined
   /// \param variable name
   /// \return whether the value of the variable is null
-  bool is_unset_or_null(const std::string& name)
+  bool is_unset_or_null(const std::string& name, const unsigned index)
   {
     std::shared_ptr<variable> value = members.resolve(name);
     if(value)
-      return value->is_null();
+      return value->is_null(index);
     else
       return true;
   }
@@ -449,9 +449,11 @@ public:
   /// \param the value of the word
   /// \return the expansion result
   const std::string do_default_expansion(const std::string& name,
-                                         const std::string& value)
+                                         const std::string& value,
+                                         const unsigned index)
   {
-    return (is_unset_or_null(name)? value : resolve<std::string>(name));
+    return (is_unset_or_null(name, index)?
+        value : resolve<std::string>(name, index));
   }
 
   /// \brief perform ${parameter:=word} expansion
@@ -459,9 +461,11 @@ public:
   /// \param the value of the word
   /// \return the expansion result
   const std::string do_assign_expansion(const std::string& name,
-                                        const std::string& value)
+                                        const std::string& value,
+                                        const unsigned index)
   {
-    return (is_unset_or_null(name)? set_value(name, value) : resolve<std::string>(name));
+    return (is_unset_or_null(name, index)?
+        set_value(name, value, index) : resolve<std::string>(name, index));
   }
 
   /// \brief perform ${parameter:+word} expansion
@@ -469,18 +473,20 @@ public:
   /// \param the value of the word
   /// \return the expansion result
   const std::string do_alternate_expansion(const std::string& name,
-                                           const std::string& value)
+                                           const std::string& value,
+                                           const unsigned index)
   {
-    return (is_unset_or_null(name)? "" : value);
+    return (is_unset_or_null(name, index)? "" : value);
   }
 
   /// \brief perform substring expansion
   /// \param the offset of the substring
   /// \return the expansion result
   const std::string do_substring_expansion(const std::string& name,
-                                           int offset)
+                                           int offset,
+                                           const unsigned index)
   {
-    std::string value = resolve<std::string>(name);
+    std::string value = resolve<std::string>(name, index);
     if(!get_real_offset(offset, value))
       return "";
     return value.substr(offset);
@@ -492,11 +498,12 @@ public:
   /// \return the expansion result
   const std::string do_substring_expansion(const std::string& name,
                                            int offset,
-                                           int length)
+                                           int length,
+                                           const unsigned index)
   {
     if(length < 0)
       throw interpreter_exception("length of substring expression should be greater or equal to zero");
-    std::string value = resolve<std::string>(name);
+    std::string value = resolve<std::string>(name, index);
     if(!get_real_offset(offset, value))
       return "";
     return value.substr(offset, length);
@@ -513,5 +520,15 @@ public:
     return value->get_length(index);
   }
 
+  /// \brief get the length of an array
+  /// \param the name of the array
+  /// \return the length of the array
+  unsigned get_array_length(const std::string& name)
+  {
+    std::shared_ptr<variable> value = members.resolve(name);
+    if(!value)
+      return 0;
+    return value->get_array_length();
+  }
 };
 #endif

diff --git a/src/core/symbols.hpp b/src/core/symbols.hpp
index 5992a67..7654ebe 100644
--- a/src/core/symbols.hpp
+++ b/src/core/symbols.hpp
@@ -125,10 +125,6 @@ class variable
   /// \brief whether the variable is readonly
   bool readonly;
 
-  /// \var private::null_value
-  /// \brief whether the variable is null
-  bool null_value;
-
 public:
   /// \brief retrieve variable name
   /// \return const string value of variable name
@@ -142,9 +138,10 @@ public:
            const T& v,
            bool ro=false,
            bool is_null=false)
-    : name(name), readonly(ro), null_value(is_null)
+    : name(name), readonly(ro)
   {
-    value[0] = v;
+    if(!is_null)
+        value[0] = v;
   }
 
   /// \brief retrieve actual value of the variable, if index is out of bound,
@@ -190,8 +187,10 @@ public:
     if(readonly)
       throw interpreter_exception(get_name() + " is readonly variable");
 
-    null_value = is_null;
-    value[index] = new_value;
+    if(is_null)
+        value.erase(index);
+    else
+        value[index] = new_value;
   }
 
   /// \brief get the length of a variable
@@ -211,9 +210,9 @@ public:
 
   /// \brief check whether the value of the variable is null
   /// \return whether the value of the variable is null
-  bool is_null() const
+  bool is_null(const unsigned index=0) const
   {
-    return null_value;
+    return value.find(index) == value.end();
   }
 };
 
@@ -222,8 +221,8 @@ template <>
 inline variable::variable<>(const std::string& name,
                             const std::map<int, std::string>& v,
                             bool ro,
-                            bool is_null)
-    : name(name), value(v.begin(), v.end()), readonly(ro), null_value(is_null)
+                            bool)
+    : name(name), value(v.begin(), v.end()), readonly(ro)
 {
 }
 

diff --git a/src/core/tests/interpreter_test.cpp b/src/core/tests/interpreter_test.cpp
index 9bb561a..fbf073e 100644
--- a/src/core/tests/interpreter_test.cpp
+++ b/src/core/tests/interpreter_test.cpp
@@ -59,9 +59,16 @@ TEST(interpreter, is_unset_or_null)
 {
   interpreter walker;
   walker.define("foo", "hello");
-  EXPECT_FALSE(walker.is_unset_or_null("foo"));
+  EXPECT_FALSE(walker.is_unset_or_null("foo", 0));
   walker.define("foo", "hello", false, true);
-  EXPECT_TRUE(walker.is_unset_or_null("foo"));
+  EXPECT_TRUE(walker.is_unset_or_null("foo", 0));
+
+  std::map<int, std::string> values = {{0, "1"}, {1, "2"}, {2, "3"}};
+  walker.define("bar", values);
+  EXPECT_FALSE(walker.is_unset_or_null("bar", 0));
+  EXPECT_FALSE(walker.is_unset_or_null("bar", 1));
+  EXPECT_FALSE(walker.is_unset_or_null("bar", 2));
+  EXPECT_TRUE(walker.is_unset_or_null("bar", 3));
 }
 
 TEST(interpreter, is_unset)
@@ -134,5 +141,5 @@ TEST(interpreter, get_array_values)
 TEST(interperter, substring_expansion_exception)
 {
   interpreter walker;
-  EXPECT_THROW(walker.do_substring_expansion("", 0, -1), interpreter_exception);
+  EXPECT_THROW(walker.do_substring_expansion("", 0, -1, 0), interpreter_exception);
 }



             reply	other threads:[~2011-04-14  4:50 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-14  4:50 Petteri Räty [this message]
  -- strict thread matches above, loose matches on Subject: below --
2012-06-03  9:08 [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/, src/core/tests/ Petteri Räty
2011-06-03 12:43 Petteri Räty
2011-05-23 14:34 Petteri Räty
2011-05-22 21:00 Petteri Räty
2011-04-28  6:19 Petteri Räty
2011-04-06 15:07 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=60fe984fb2c868848a8fb71fe2272a24a78d350a.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