* [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