From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1QVJwG-0000CG-6i for garchives@archives.gentoo.org; Sat, 11 Jun 2011 08:53:04 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 25E161C034; Sat, 11 Jun 2011 08:52:17 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id C5E701C01D for ; Sat, 11 Jun 2011 08:52:16 +0000 (UTC) Received: from pelican.gentoo.org (unknown [66.219.59.40]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 67C201B403B for ; Sat, 11 Jun 2011 08:52:15 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by pelican.gentoo.org (Postfix) with ESMTP id 8350C8004B for ; Sat, 11 Jun 2011 08:52:14 +0000 (UTC) From: "Petteri Räty" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Petteri Räty" Message-ID: Subject: [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/, test/, bashast/gunit/ X-VCS-Repository: proj/libbash X-VCS-Files: bashast/bashast.g bashast/gunit/array.gunit bashast/libbashWalker.g scripts/var_expansion.bash scripts/var_expansion.bash.result src/core/interpreter.cpp src/core/interpreter.h test/script_compiler.sh X-VCS-Directories: scripts/ src/core/ bashast/ test/ bashast/gunit/ X-VCS-Committer: betelgeuse X-VCS-Committer-Name: Petteri Räty X-VCS-Revision: b7a822f06696cb0a8bb6f37a7fdb083309d95f0a Date: Sat, 11 Jun 2011 08:52:14 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: X-Archives-Hash: 2887d793ac6d0ffa78c379a12602dcf9 commit: b7a822f06696cb0a8bb6f37a7fdb083309d95f0a Author: Mu Qiao gentoo org> AuthorDate: Mon Jun 6 10:06:29 2011 +0000 Commit: Petteri R=C3=A4ty gentoo org> CommitDate: Sat Jun 11 08:24:47 2011 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/libbash.git;a= =3Dcommit;h=3Db7a822f0 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 pat= h))) -"${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 *) (STRI= NG path))) +"${asdf[@]%word}" -> (VAR_REF (LAZY_REMOVE_AT_END (ARRAY asdf @) (STRIN= G word))) +"${asdf[*]/pattern/string}" -> (VAR_REF (REPLACE_FIRST (ARRAY asdf *) (S= TRING 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 =3D $name.libbash_value; $index =3D $name.index; - } - |TIMES { $libbash_value =3D "*"; }; + }; + +array_name returns[std::string libbash_value] + :^(ARRAY name (AT|TIMES)) { $libbash_value =3D $name.libbash_value; } + // We do not care the difference between TIMES and AT for now + |TIMES { $libbash_value =3D "*"; } + |AT { $libbash_value =3D "@"; }; =20 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=3Dword) { libbash_value =3D walker->do_alternate_expansion($var_name.libbash_val= ue, libbash_word, $var_name.index); } + |(^(OFFSET array_name arithmetics arithmetics)) =3D> ^(OFFSET libbash_n= ame=3Darray_name offset=3Darithmetics length=3Darithmetics) { + libbash_value =3D walker->do_subarray_expansion(libbash_name, offset, = length); + } + |(^(OFFSET array_name offset=3Darithmetics)) =3D> ^(OFFSET libbash_name= =3Darray_name offset=3Darithmetics) { + libbash_value =3D walker->do_subarray_expansion(libbash_name, offset); + } |(^(OFFSET var_name arithmetics arithmetics)) =3D> ^(OFFSET var_name of= fset=3Darithmetics length=3Darithmetics) { libbash_value =3D walker->do_substring_expansion($var_name.libbash_val= ue, offset, length, $var_name.index); } @@ -432,8 +443,8 @@ var_ref [bool double_quoted] returns[std::string libb= ash_value] |^(VAR_REF libbash_string=3Dnum) { $libbash_value =3D walker->resolve(libbash_string); } - |^(VAR_REF ^(libbash_string=3Dname_base AT)) { walker->get_all_elements= (libbash_string, $libbash_value); } - |^(VAR_REF ^(libbash_string=3Dname_base TIMES)) { + |^(VAR_REF ^(ARRAY libbash_string=3Dname_base AT)) { walker->get_all_el= ements(libbash_string, $libbash_value); } + |^(VAR_REF ^(ARRAY libbash_string=3Dname_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:=3D} +ARRAY=3D(1 2 3 4 5) +echo ${ARRAY[@]:1} +echo ${ARRAY[@]:1:3} diff --git a/scripts/var_expansion.bash.result b/scripts/var_expansion.ba= sh.result index c3f30c8..299d975 100644 --- a/scripts/var_expansion.bash.result +++ b/scripts/var_expansion.bash.result @@ -1,7 +1,9 @@ =20 abcabc abcabc -ARRAY=3Dhi hello 1 2 3 +2 3 4 5 +2 3 4 +ARRAY=3D1 2 3 4 5 ARRAY2=3Dhello EAPI=3D3 EAPI4=3D4 @@ -91,6 +93,6 @@ FOO084=3D1 2 3 4 5 FOO085=3D1 2 FOO086=3D5 FOO087=3D4 5 -FOO088=3Dfilename 1 2 3 4 5 +FOO088=3D@srcdir@/scripts/var_expansion.bash 1 2 3 4 5 FOO089=3D target=3Dabc*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::strin= g& name, return i->second->is_null(index); } =20 -// This method temporarily supports array offset expansion for $* and $@= . -// That logic will be refactored and applied to normal array variables i= n future. std::string interpreter::get_substring(const std::string& name, long long offset, unsigned length, const unsigned index) const { - if(name !=3D "*" && name !=3D "@") - { - std::string value =3D resolve(name, index); - if(!get_real_offset(offset, boost::numeric_cast(value.size= ()))) - return ""; - // After get_real_offset, we know offset can be cast to unsigned. - return value.substr(boost::numeric_cast(offs= et), length); - } - else - { - std::vector array; - // ${*:1} has the same content as ${*}, ${*:0} contains current scri= pt name as the first element - if(offset > 0) - offset--; - else if(offset =3D=3D 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_limit= s::max() - if(resolve_array(name, array) && get_real_offset(offset, boost::nume= ric_cast(array.size()))) - { - // We do not support arrays that have size bigger than numeric_lim= its::max() - // After get_real_offset, we know offset can be cast to unsigned. - unsigned max_length =3D boost::numeric_cast(array.size()= ) - boost::numeric_cast(offset); - if(length > max_length) - length =3D max_length; - - auto start =3D array.begin() + boost::numeric_cast::difference_type>(offset); - auto end =3D array.begin() + boost::numeric_cast::difference_type>(offset + length); - return boost::algorithm::join(std::vector(start, end)= , resolve("IFS").substr(0, 1)); - } - else - return ""; - } + std::string value =3D resolve(name, index); + if(!get_real_offset(offset, boost::numeric_cast(value.size()= ))) + return ""; + // After get_real_offset, we know offset can be cast to unsigned. + return value.substr(boost::numeric_cast(offset= ), length); } =20 const std::string interpreter::do_substring_expansion(const std::string&= name, @@ -198,6 +168,54 @@ const std::string interpreter::do_substring_expansio= n(const std::string& name, return get_substring(name, offset, boost::numeric_cast(lengt= h), index); } =20 +std::string interpreter::get_subarray(const std::string& name, + long long offset, + unsigned length) const +{ + std::vector array; + if(name =3D=3D "*" || name =3D=3D "@") + { + // ${*:1} has the same content as ${*}, ${*:0} contains current scri= pt name as the first element + if(offset > 0) + offset--; + else if(offset =3D=3D 0) + array.push_back(resolve("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::numeri= c_cast(array.size()))) + { + // We do not support arrays that have size bigger than numeric_limit= s::max() + // After get_real_offset, we know offset can be cast to unsigned. + unsigned max_length =3D boost::numeric_cast(array.size()) = - boost::numeric_cast(offset); + if(length > max_length) + length =3D max_length; + + auto start =3D array.begin() + boost::numeric_cast::difference_type>(offset); + auto end =3D array.begin() + boost::numeric_cast::difference_type>(offset + length); + return boost::algorithm::join(std::vector(start, end), = resolve("IFS").substr(0, 1)); + } + else + { + return ""; + } +} + +const std::string interpreter::do_subarray_expansion(const std::string& = name, + long long offset) c= onst +{ + return get_subarray(name, offset, std::numeric_limits::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 b= e greater or equal to zero"); + + return get_subarray(name, offset, boost::numeric_cast(length= )); +} + std::string interpreter::do_replace_expansion(const std::string& name, std::function replacer, const unsigned index) cons= t 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: =20 typedef std::map::const_iterator option_iterator; @@ -658,6 +662,20 @@ public: int length, const unsigned index) const; =20 + /// \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 =20 declare -i error=3D0 +result=3D$(mktemp) =20 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+=3D$? done =20 +rm -rf $result exit $error