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

commit:     b7a822f06696cb0a8bb6f37a7fdb083309d95f0a
Author:     Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Mon Jun  6 10:06:29 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Sat Jun 11 08:24:47 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=b7a822f0

Walker: support array offset expansion

* is removed from var_name as most expansions don't support it. Parser
grammar is adjusted to generate better AST.

---
 bashast/bashast.g                 |   12 +++--
 bashast/gunit/array.gunit         |   12 +++---
 bashast/libbashWalker.g           |   19 ++++++--
 scripts/var_expansion.bash        |    3 +
 scripts/var_expansion.bash.result |    6 ++-
 src/core/interpreter.cpp          |   88 ++++++++++++++++++++++---------------
 src/core/interpreter.h            |   18 ++++++++
 test/script_compiler.sh           |    5 ++-
 8 files changed, 110 insertions(+), 53 deletions(-)

diff --git a/bashast/bashast.g b/bashast/bashast.g
index bea3740..e9f71d7 100644
--- a/bashast/bashast.g
+++ b/bashast/bashast.g
@@ -315,15 +315,17 @@ parameter_replace_operator
 //either directly or through array
 var_name
 	:	num
+	|	name LSQUARE AT RSQUARE -> ^(ARRAY name AT)
+	|	name LSQUARE TIMES RSQUARE -> ^(ARRAY name TIMES)
 	|	var_name_no_digit
-	|	TIMES
 	|	DOLLAR
-	|	AT;
+	|	TIMES
+	|	AT
+	|	POUND;
 //Inside arithmetic we can't allow digits
 var_name_no_digit
-	:	name^ LSQUARE! (AT|TIMES|explicit_arithmetic) RSQUARE!
-	|	name
-	|	POUND;
+	:	name^ LSQUARE! (explicit_arithmetic) RSQUARE!
+	|	name;
 //with bang the array syntax is used for array indexes
 var_name_for_bang
 	:	num|name|POUND;

diff --git a/bashast/gunit/array.gunit b/bashast/gunit/array.gunit
index caa2615..b4077bf 100644
--- a/bashast/gunit/array.gunit
+++ b/bashast/gunit/array.gunit
@@ -39,11 +39,11 @@ var_ref:
 "${asdf[4]//pattern}" -> (VAR_REF (REPLACE_ALL (asdf 4) (STRING pattern)))
 "${asdf}" -> (VAR_REF asdf)
 "${#asdf[0]}" -> (VAR_REF (# (asdf 0)))
-"${asdf[@]}" -> (VAR_REF (asdf @))
-"${asdf[*]}" -> (VAR_REF (asdf *))
+"${asdf[@]}" -> (VAR_REF (ARRAY asdf @))
+"${asdf[*]}" -> (VAR_REF (ARRAY asdf *))
 "${#asdf[@]}" -> (VAR_REF (# (asdf ARRAY_SIZE)))
 "${#asdf[*]}" -> (VAR_REF (# (asdf ARRAY_SIZE)))
-"${asdf[@]:0:1}" -> (VAR_REF (OFFSET (asdf @) 0 1))
-"${asdf[*]#path}" -> (VAR_REF (LAZY_REMOVE_AT_START (asdf *) (STRING path)))
-"${asdf[@]%word}" ->  (VAR_REF (LAZY_REMOVE_AT_END (asdf @) (STRING word)))
-"${asdf[*]/pattern/string}" -> (VAR_REF (REPLACE_FIRST (asdf *) (STRING pattern) (STRING string)))
+"${asdf[@]:0:1}" -> (VAR_REF (OFFSET (ARRAY asdf @) 0 1))
+"${asdf[*]#path}" -> (VAR_REF (LAZY_REMOVE_AT_START (ARRAY asdf *) (STRING path)))
+"${asdf[@]%word}" ->  (VAR_REF (LAZY_REMOVE_AT_END (ARRAY asdf @) (STRING word)))
+"${asdf[*]/pattern/string}" -> (VAR_REF (REPLACE_FIRST (ARRAY asdf *) (STRING pattern) (STRING string)))

diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 9fff16f..9cb578f 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -342,8 +342,13 @@ var_name returns[std::string libbash_value, unsigned index]
 	|name {
 		$libbash_value = $name.libbash_value;
 		$index = $name.index;
-	}
-	|TIMES { $libbash_value = "*"; };
+	};
+
+array_name returns[std::string libbash_value]
+	:^(ARRAY name (AT|TIMES)) { $libbash_value = $name.libbash_value; }
+	// We do not care the difference between TIMES and AT for now
+	|TIMES { $libbash_value = "*"; }
+	|AT { $libbash_value = "@"; };
 
 var_expansion returns[std::string libbash_value]
 @declarations {
@@ -360,6 +365,12 @@ var_expansion returns[std::string libbash_value]
 	|^(USE_ALTERNATE_WHEN_UNSET_OR_NULL var_name libbash_word=word) {
 		libbash_value = walker->do_alternate_expansion($var_name.libbash_value, libbash_word, $var_name.index);
 	}
+	|(^(OFFSET array_name arithmetics arithmetics)) => ^(OFFSET libbash_name=array_name offset=arithmetics length=arithmetics) {
+		libbash_value = walker->do_subarray_expansion(libbash_name, offset, length);
+	}
+	|(^(OFFSET array_name offset=arithmetics)) => ^(OFFSET libbash_name=array_name offset=arithmetics) {
+		libbash_value = walker->do_subarray_expansion(libbash_name, offset);
+	}
 	|(^(OFFSET var_name arithmetics arithmetics)) => ^(OFFSET var_name offset=arithmetics length=arithmetics) {
 		libbash_value = walker->do_substring_expansion($var_name.libbash_value, offset, length, $var_name.index);
 	}
@@ -432,8 +443,8 @@ var_ref [bool double_quoted] returns[std::string libbash_value]
 	|^(VAR_REF libbash_string=num) {
 		$libbash_value = walker->resolve<std::string>(libbash_string);
 	}
-	|^(VAR_REF ^(libbash_string=name_base AT)) { walker->get_all_elements(libbash_string, $libbash_value); }
-	|^(VAR_REF ^(libbash_string=name_base TIMES)) {
+	|^(VAR_REF ^(ARRAY libbash_string=name_base AT)) { walker->get_all_elements(libbash_string, $libbash_value); }
+	|^(VAR_REF ^(ARRAY libbash_string=name_base TIMES)) {
 		if(double_quoted)
 			walker->get_all_elements_IFS_joined(libbash_string, $libbash_value);
 		else

diff --git a/scripts/var_expansion.bash b/scripts/var_expansion.bash
index d38d8aa..c3f41d3 100644
--- a/scripts/var_expansion.bash
+++ b/scripts/var_expansion.bash
@@ -97,3 +97,6 @@ echo ${target/*}
 echo ${target/'*'}
 echo ${target/"*"}
 : ${FOO089:=}
+ARRAY=(1 2 3 4 5)
+echo ${ARRAY[@]:1}
+echo ${ARRAY[@]:1:3}

diff --git a/scripts/var_expansion.bash.result b/scripts/var_expansion.bash.result
index c3f30c8..299d975 100644
--- a/scripts/var_expansion.bash.result
+++ b/scripts/var_expansion.bash.result
@@ -1,7 +1,9 @@
 
 abcabc
 abcabc
-ARRAY=hi hello 1 2 3
+2 3 4 5
+2 3 4
+ARRAY=1 2 3 4 5
 ARRAY2=hello
 EAPI=3
 EAPI4=4
@@ -91,6 +93,6 @@ FOO084=1 2 3 4 5
 FOO085=1 2
 FOO086=5
 FOO087=4 5
-FOO088=filename 1 2 3 4 5
+FOO088=@srcdir@/scripts/var_expansion.bash 1 2 3 4 5
 FOO089=
 target=abc*abc

diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
index 6922df9..fd5e75a 100644
--- a/src/core/interpreter.cpp
+++ b/src/core/interpreter.cpp
@@ -138,46 +138,16 @@ bool interpreter::is_unset_or_null(const std::string& name,
     return i->second->is_null(index);
 }
 
-// This method temporarily supports array offset expansion for $* and $@.
-// That logic will be refactored and applied to normal array variables in future.
 std::string interpreter::get_substring(const std::string& name,
                                        long long offset,
                                        unsigned length,
                                        const unsigned index) const
 {
-  if(name != "*" && name != "@")
-  {
-    std::string value = resolve<std::string>(name, index);
-    if(!get_real_offset(offset, boost::numeric_cast<unsigned>(value.size())))
-      return "";
-    // After get_real_offset, we know offset can be cast to unsigned.
-    return value.substr(boost::numeric_cast<std::string::size_type>(offset), length);
-  }
-  else
-  {
-    std::vector<std::string> array;
-    // ${*:1} has the same content as ${*}, ${*:0} contains current script name as the first element
-    if(offset > 0)
-      offset--;
-    else if(offset == 0)
-      // Need to replace this with the real script name
-      array.push_back("filename");
-    // We do not support arrays that have size bigger than numeric_limits<unsigned>::max()
-    if(resolve_array(name, array) && get_real_offset(offset, boost::numeric_cast<unsigned>(array.size())))
-    {
-      // We do not support arrays that have size bigger than numeric_limits<unsigned>::max()
-      // After get_real_offset, we know offset can be cast to unsigned.
-      unsigned max_length = boost::numeric_cast<unsigned>(array.size()) - boost::numeric_cast<unsigned>(offset);
-      if(length > max_length)
-        length = max_length;
-
-      auto start = array.begin() + boost::numeric_cast<std::vector<std::string>::difference_type>(offset);
-      auto end = array.begin() + boost::numeric_cast<std::vector<std::string>::difference_type>(offset + length);
-      return boost::algorithm::join(std::vector<std::string>(start, end), resolve<std::string>("IFS").substr(0, 1));
-    }
-    else
-      return "";
-  }
+  std::string value = resolve<std::string>(name, index);
+  if(!get_real_offset(offset, boost::numeric_cast<unsigned>(value.size())))
+    return "";
+  // After get_real_offset, we know offset can be cast to unsigned.
+  return value.substr(boost::numeric_cast<std::string::size_type>(offset), length);
 }
 
 const std::string interpreter::do_substring_expansion(const std::string& name,
@@ -198,6 +168,54 @@ const std::string interpreter::do_substring_expansion(const std::string& name,
   return get_substring(name, offset, boost::numeric_cast<unsigned>(length), index);
 }
 
+std::string interpreter::get_subarray(const std::string& name,
+                                      long long offset,
+                                      unsigned length) const
+{
+  std::vector<std::string> array;
+  if(name == "*" || name == "@")
+  {
+    // ${*:1} has the same content as ${*}, ${*:0} contains current script name as the first element
+    if(offset > 0)
+      offset--;
+    else if(offset == 0)
+      array.push_back(resolve<std::string>("0"));
+  }
+  // We do not support arrays that have size bigger than numeric_limits<unsigned>::max()
+  if(resolve_array(name, array) && get_real_offset(offset, boost::numeric_cast<unsigned>(array.size())))
+  {
+    // We do not support arrays that have size bigger than numeric_limits<unsigned>::max()
+    // After get_real_offset, we know offset can be cast to unsigned.
+    unsigned max_length = boost::numeric_cast<unsigned>(array.size()) - boost::numeric_cast<unsigned>(offset);
+    if(length > max_length)
+      length = max_length;
+
+    auto start = array.begin() + boost::numeric_cast<std::vector<std::string>::difference_type>(offset);
+    auto end = array.begin() + boost::numeric_cast<std::vector<std::string>::difference_type>(offset + length);
+    return boost::algorithm::join(std::vector<std::string>(start, end), resolve<std::string>("IFS").substr(0, 1));
+  }
+  else
+  {
+    return "";
+  }
+}
+
+const std::string interpreter::do_subarray_expansion(const std::string& name,
+                                                     long long offset) const
+{
+  return get_subarray(name, offset, std::numeric_limits<unsigned>::max());
+}
+
+const std::string interpreter::do_subarray_expansion(const std::string& name,
+                                                     long long offset,
+                                                     int length) const
+{
+  if(length < 0)
+    throw interpreter_exception("length of substring expression should be greater or equal to zero");
+
+  return get_subarray(name, offset, boost::numeric_cast<unsigned>(length));
+}
+
 std::string interpreter::do_replace_expansion(const std::string& name,
                                               std::function<void(std::string&)> replacer,
                                               const unsigned index) const

diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 6aefc4c..6fdfcbe 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -98,6 +98,10 @@ class interpreter: public boost::noncopyable
                             long long offset,
                             unsigned length,
                             const unsigned index) const;
+
+  std::string get_subarray(const std::string& name,
+                           long long offset,
+                           unsigned length) const;
 public:
 
   typedef std::map<std::string, bool>::const_iterator option_iterator;
@@ -658,6 +662,20 @@ public:
                                            int length,
                                            const unsigned index) const;
 
+  /// \brief perform subarray expansion
+  /// \param the offset of the subarray
+  /// \return the expansion result
+  const std::string do_subarray_expansion(const std::string& name,
+                                          long long offset) const;
+
+  /// \brief perform subarray expansion
+  /// \param the offset of the subarray
+  /// \param the length of the subarray
+  /// \return the expansion result
+  const std::string do_subarray_expansion(const std::string& name,
+                                          long long offset,
+                                          int length) const;
+
   /// \brief perform replacement expansion
   /// \param the name of the varaible that needs to be expanded
   /// \param the function object used to perform expansion

diff --git a/test/script_compiler.sh b/test/script_compiler.sh
index 021855e..6ff5672 100755
--- a/test/script_compiler.sh
+++ b/test/script_compiler.sh
@@ -1,11 +1,14 @@
 #!/bin/sh
 
 declare -i error=0
+result=$(mktemp)
 
 for script in $@
 do
-    ./variable_printer $script 2>&1 | diff -u $script.result -
+    sed "s/@srcdir@/$srcdir/" $script.result > $result
+    ./variable_printer $script 2>&1 | diff -u $result -
     error+=$?
 done
 
+rm -rf $result
 exit $error



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

only message in thread, other threads:[~2011-06-11  8:53 UTC | newest]

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