aboutsummaryrefslogtreecommitdiffstats
path: root/androidmk
diff options
context:
space:
mode:
authorandroid-build-prod (mdb) <android-build-team-robot@google.com>2018-05-08 01:05:10 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-05-08 01:05:10 +0000
commit720f04b96488a55ecc3ee70f50ca6d1bbe43ffac (patch)
tree50d678bf591cdccb2148a2f2dc70be112674a9b3 /androidmk
parentdde8cb961589782c8cd3566560193de804d40fb5 (diff)
parentd6989f2e5225145a26af0844c11b310dfbe76483 (diff)
downloadbuild_soong-720f04b96488a55ecc3ee70f50ca6d1bbe43ffac.tar.gz
build_soong-720f04b96488a55ecc3ee70f50ca6d1bbe43ffac.tar.bz2
build_soong-720f04b96488a55ecc3ee70f50ca6d1bbe43ffac.zip
Merge changes I52f88bfd,I4263b7d5
* changes: Fix usage of bytes.NewBuffer in bpfix Add a dependency fixer for proto deps
Diffstat (limited to 'androidmk')
-rw-r--r--androidmk/Android.bp2
-rw-r--r--androidmk/parser/make_strings.go81
-rw-r--r--androidmk/parser/make_strings_test.go72
-rw-r--r--androidmk/parser/parser.go15
-rw-r--r--androidmk/parser/parser_test.go61
-rw-r--r--androidmk/parser/scope.go2
6 files changed, 225 insertions, 8 deletions
diff --git a/androidmk/Android.bp b/androidmk/Android.bp
index 442452f8..1d939b0c 100644
--- a/androidmk/Android.bp
+++ b/androidmk/Android.bp
@@ -44,6 +44,6 @@ bootstrap_go_package {
],
testSrcs: [
"parser/make_strings_test.go",
+ "parser/parser_test.go",
],
}
-
diff --git a/androidmk/parser/make_strings.go b/androidmk/parser/make_strings.go
index e6885a8c..4b782a23 100644
--- a/androidmk/parser/make_strings.go
+++ b/androidmk/parser/make_strings.go
@@ -90,10 +90,10 @@ func (ms *MakeString) Value(scope Scope) string {
if len(ms.Strings) == 0 {
return ""
} else {
- ret := ms.Strings[0]
+ ret := unescape(ms.Strings[0])
for i := range ms.Strings[1:] {
ret += ms.Variables[i].Value(scope)
- ret += ms.Strings[i+1]
+ ret += unescape(ms.Strings[i+1])
}
return ret
}
@@ -125,6 +125,16 @@ func (ms *MakeString) Split(sep string) []*MakeString {
}
func (ms *MakeString) SplitN(sep string, n int) []*MakeString {
+ return ms.splitNFunc(n, func(s string, n int) []string {
+ return splitAnyN(s, sep, n)
+ })
+}
+
+func (ms *MakeString) Words() []*MakeString {
+ return ms.splitNFunc(-1, splitWords)
+}
+
+func (ms *MakeString) splitNFunc(n int, splitFunc func(s string, n int) []string) []*MakeString {
ret := []*MakeString{}
curMs := SimpleMakeString("", ms.Pos())
@@ -133,7 +143,7 @@ func (ms *MakeString) SplitN(sep string, n int) []*MakeString {
var s string
for i, s = range ms.Strings {
if n != 0 {
- split := splitAnyN(s, sep, n)
+ split := splitFunc(s, n)
if n != -1 {
if len(split) > n {
panic("oops!")
@@ -156,7 +166,9 @@ func (ms *MakeString) SplitN(sep string, n int) []*MakeString {
}
}
- ret = append(ret, curMs)
+ if !curMs.Empty() {
+ ret = append(ret, curMs)
+ }
return ret
}
@@ -206,3 +218,64 @@ func splitAnyN(s, sep string, n int) []string {
ret = append(ret, s)
return ret
}
+
+func splitWords(s string, n int) []string {
+ ret := []string{}
+ preserve := ""
+ for n == -1 || n > 1 {
+ index := strings.IndexAny(s, " \t")
+ if index == 0 && len(preserve) == 0 {
+ s = s[1:]
+ } else if index >= 0 {
+ escapeCount := 0
+ for i := index - 1; i >= 0; i-- {
+ if s[i] != '\\' {
+ break
+ }
+ escapeCount += 1
+ }
+
+ if escapeCount%2 == 1 {
+ preserve += s[0 : index+1]
+ s = s[index+1:]
+ continue
+ }
+
+ ret = append(ret, preserve+s[0:index])
+ s = s[index+1:]
+ preserve = ""
+ if n > 0 {
+ n--
+ }
+ } else {
+ break
+ }
+ }
+ if preserve != "" || s != "" || len(ret) == 0 {
+ ret = append(ret, preserve+s)
+ }
+ return ret
+}
+
+func unescape(s string) string {
+ ret := ""
+ for {
+ index := strings.IndexByte(s, '\\')
+ if index < 0 {
+ break
+ }
+
+ if index+1 == len(s) {
+ break
+ }
+
+ switch s[index+1] {
+ case ' ', '\\', '#', ':', '*', '[', '|', '\t', '\n', '\r':
+ ret += s[:index] + s[index+1:index+2]
+ default:
+ ret += s[:index+2]
+ }
+ s = s[index+2:]
+ }
+ return ret + s
+}
diff --git a/androidmk/parser/make_strings_test.go b/androidmk/parser/make_strings_test.go
index 8ad3d74c..6995e891 100644
--- a/androidmk/parser/make_strings_test.go
+++ b/androidmk/parser/make_strings_test.go
@@ -99,6 +99,78 @@ func TestMakeStringSplitN(t *testing.T) {
}
}
+var valueTestCases = []struct {
+ in *MakeString
+ expected string
+}{
+ {
+ in: SimpleMakeString("a b", NoPos),
+ expected: "a b",
+ },
+ {
+ in: SimpleMakeString("a\\ \\\tb\\\\", NoPos),
+ expected: "a \tb\\",
+ },
+ {
+ in: SimpleMakeString("a\\b\\", NoPos),
+ expected: "a\\b\\",
+ },
+}
+
+func TestMakeStringValue(t *testing.T) {
+ for _, test := range valueTestCases {
+ got := test.in.Value(nil)
+ if got != test.expected {
+ t.Errorf("\nwith: %q\nwant: %q\n got: %q", test.in.Dump(), test.expected, got)
+ }
+ }
+}
+
+var splitWordsTestCases = []struct {
+ in *MakeString
+ expected []*MakeString
+}{
+ {
+ in: SimpleMakeString("", NoPos),
+ expected: []*MakeString{},
+ },
+ {
+ in: SimpleMakeString(" a b\\ c d", NoPos),
+ expected: []*MakeString{
+ SimpleMakeString("a", NoPos),
+ SimpleMakeString("b\\ c", NoPos),
+ SimpleMakeString("d", NoPos),
+ },
+ },
+ {
+ in: SimpleMakeString(" a\tb\\\t\\ c d ", NoPos),
+ expected: []*MakeString{
+ SimpleMakeString("a", NoPos),
+ SimpleMakeString("b\\\t\\ c", NoPos),
+ SimpleMakeString("d", NoPos),
+ },
+ },
+ {
+ in: SimpleMakeString(`a\\ b\\\ c d`, NoPos),
+ expected: []*MakeString{
+ SimpleMakeString(`a\\`, NoPos),
+ SimpleMakeString(`b\\\ c`, NoPos),
+ SimpleMakeString("d", NoPos),
+ },
+ },
+}
+
+func TestMakeStringWords(t *testing.T) {
+ for _, test := range splitWordsTestCases {
+ got := test.in.Words()
+ gotString := dumpArray(got)
+ expectedString := dumpArray(test.expected)
+ if gotString != expectedString {
+ t.Errorf("with:\n%q\nexpected:\n%s\ngot:\n%s", test.in.Dump(), expectedString, gotString)
+ }
+ }
+}
+
func dumpArray(a []*MakeString) string {
ret := make([]string, len(a))
diff --git a/androidmk/parser/parser.go b/androidmk/parser/parser.go
index 89ee308f..89c1af90 100644
--- a/androidmk/parser/parser.go
+++ b/androidmk/parser/parser.go
@@ -35,6 +35,10 @@ func (e *ParseError) Error() string {
return fmt.Sprintf("%s: %s", e.Pos, e.Err)
}
+const builtinDollar = "__builtin_dollar"
+
+var builtinDollarName = SimpleMakeString(builtinDollar, NoPos)
+
func (p *parser) Parse() ([]Node, []error) {
defer func() {
if r := recover(); r != nil {
@@ -326,7 +330,11 @@ loop:
case '$':
var variable Variable
variable = p.parseVariable()
- value.appendVariable(variable)
+ if variable.Name == builtinDollarName {
+ value.appendString("$")
+ } else {
+ value.appendVariable(variable)
+ }
case scanner.EOF:
break loop
case '(':
@@ -357,7 +365,8 @@ func (p *parser) parseVariable() Variable {
case '{':
return p.parseBracketedVariable('{', '}', pos)
case '$':
- name = SimpleMakeString("__builtin_dollar", NoPos)
+ name = builtinDollarName
+ p.accept(p.tok)
case scanner.EOF:
p.errorf("expected variable name, found %s",
scanner.TokenString(p.tok))
@@ -457,6 +466,8 @@ func (p *parser) parseRulePrerequisites(target *MakeString) (*MakeString, bool)
case '=':
p.parseAssignment("=", target, prerequisites)
return nil, true
+ case scanner.EOF:
+ // do nothing
default:
p.errorf("unexpected token %s after rule prerequisites", scanner.TokenString(p.tok))
}
diff --git a/androidmk/parser/parser_test.go b/androidmk/parser/parser_test.go
new file mode 100644
index 00000000..f562c29e
--- /dev/null
+++ b/androidmk/parser/parser_test.go
@@ -0,0 +1,61 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package parser
+
+import (
+ "bytes"
+ "testing"
+)
+
+var parserTestCases = []struct {
+ name string
+ in string
+ out []Node
+}{
+ {
+ name: "Escaped $",
+ in: `a$$ b: c`,
+ out: []Node{
+ &Rule{
+ Target: SimpleMakeString("a$ b", NoPos),
+ Prerequisites: SimpleMakeString("c", NoPos),
+ },
+ },
+ },
+}
+
+func TestParse(t *testing.T) {
+ for _, test := range parserTestCases {
+ t.Run(test.name, func(t *testing.T) {
+ p := NewParser(test.name, bytes.NewBufferString(test.in))
+ got, errs := p.Parse()
+
+ if len(errs) != 0 {
+ t.Fatalf("Unexpected errors while parsing: %v", errs)
+ }
+
+ if len(got) != len(test.out) {
+ t.Fatalf("length mismatch, expected %d nodes, got %d", len(test.out), len(got))
+ }
+
+ for i := range got {
+ if got[i].Dump() != test.out[i].Dump() {
+ t.Errorf("incorrect node %d:\nexpected: %#v (%s)\n got: %#v (%s)",
+ i, test.out[i], test.out[i].Dump(), got[i], got[i].Dump())
+ }
+ }
+ })
+ }
+}
diff --git a/androidmk/parser/scope.go b/androidmk/parser/scope.go
index 7a514fae..167e470b 100644
--- a/androidmk/parser/scope.go
+++ b/androidmk/parser/scope.go
@@ -71,7 +71,7 @@ var builtinScope map[string]string
func init() {
builtinScope := make(map[string]string)
- builtinScope["__builtin_dollar"] = "$"
+ builtinScope[builtinDollar] = "$"
}
func (v Variable) EvalFunction(scope Scope) (string, bool) {