androidmk: support translating all-java-files-under

Change-Id: I4c343f6d8d23d42dddc256ff022016b595bb3841
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 9de0197..cba5124 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -2,6 +2,8 @@
 
 import (
 	"android/soong/androidmk/parser"
+	"fmt"
+	"strings"
 )
 
 const (
@@ -103,6 +105,15 @@
 	return "."
 }
 
+func allJavaFilesUnder(args []string) string {
+	dir := ""
+	if len(args) > 0 {
+		dir = strings.TrimSpace(args[0])
+	}
+
+	return fmt.Sprintf("%s/**/*.java", dir)
+}
+
 var moduleTypes = map[string]string{
 	"BUILD_SHARED_LIBRARY":      "cc_library_shared",
 	"BUILD_STATIC_LIBRARY":      "cc_library_static",
@@ -127,6 +138,7 @@
 	globalScope := parser.NewScope(nil)
 	globalScope.Set("CLEAR_VARS", clear_vars)
 	globalScope.SetFunc("my-dir", mydir)
+	globalScope.SetFunc("all-java-files-under", allJavaFilesUnder)
 
 	for k, v := range moduleTypes {
 		globalScope.Set(k, v)
diff --git a/androidmk/cmd/androidmk/androidmk.go b/androidmk/cmd/androidmk/androidmk.go
index 8ac58bf..178ce09 100644
--- a/androidmk/cmd/androidmk/androidmk.go
+++ b/androidmk/cmd/androidmk/androidmk.go
@@ -343,9 +343,9 @@
 	var err error
 	switch typ {
 	case bpparser.List:
-		exp, err = makeToListExpression(val)
+		exp, err = makeToListExpression(val, file.scope)
 	case bpparser.String:
-		exp, err = makeToStringExpression(val)
+		exp, err = makeToStringExpression(val, file.scope)
 	case bpparser.Bool:
 		exp, err = makeToBoolExpression(val)
 	default:
diff --git a/androidmk/cmd/androidmk/values.go b/androidmk/cmd/androidmk/values.go
index 927c44a..ce2f279 100644
--- a/androidmk/cmd/androidmk/values.go
+++ b/androidmk/cmd/androidmk/values.go
@@ -17,6 +17,10 @@
 }
 
 func addValues(val1, val2 *bpparser.Value) (*bpparser.Value, error) {
+	if val1 == nil {
+		return val2, nil
+	}
+
 	if val1.Type == bpparser.String && val2.Type == bpparser.List {
 		val1 = &bpparser.Value{
 			Type:      bpparser.List,
@@ -40,7 +44,7 @@
 	}, nil
 }
 
-func makeToStringExpression(ms *mkparser.MakeString) (*bpparser.Value, error) {
+func makeToStringExpression(ms *mkparser.MakeString, scope mkparser.Scope) (*bpparser.Value, error) {
 	var val *bpparser.Value
 	var err error
 
@@ -49,22 +53,22 @@
 	}
 
 	for i, s := range ms.Strings[1:] {
-		name := ms.Variables[i].Name
-		if !name.Const() {
-			return nil, fmt.Errorf("Unsupported non-const variable name %s", name.Dump())
-		}
-		tmp := &bpparser.Value{
-			Type:     bpparser.String,
-			Variable: name.Value(nil),
-		}
+		if ret, ok := ms.Variables[i].EvalFunction(scope); ok {
+			val, err = addValues(val, stringToStringValue(ret))
+		} else {
+			name := ms.Variables[i].Name
+			if !name.Const() {
+				return nil, fmt.Errorf("Unsupported non-const variable name %s", name.Dump())
+			}
+			tmp := &bpparser.Value{
+				Type:     bpparser.String,
+				Variable: name.Value(nil),
+			}
 
-		if val != nil {
 			val, err = addValues(val, tmp)
 			if err != nil {
 				return nil, err
 			}
-		} else {
-			val = tmp
 		}
 
 		if s != "" {
@@ -95,7 +99,7 @@
 
 }
 
-func makeToListExpression(ms *mkparser.MakeString) (*bpparser.Value, error) {
+func makeToListExpression(ms *mkparser.MakeString, scope mkparser.Scope) (*bpparser.Value, error) {
 	fields := ms.Split(" \t")
 
 	var listOfListValues []*bpparser.Value
@@ -106,22 +110,29 @@
 
 	for _, f := range fields {
 		if len(f.Variables) == 1 && f.Strings[0] == "" && f.Strings[1] == "" {
-			// Variable by itself, variable is probably a list
-			if !f.Variables[0].Name.Const() {
-				return nil, fmt.Errorf("unsupported non-const variable name")
-			}
-			if len(listValue.ListValue) > 0 {
-				listOfListValues = append(listOfListValues, listValue)
-			}
-			listOfListValues = append(listOfListValues, &bpparser.Value{
-				Type:     bpparser.List,
-				Variable: f.Variables[0].Name.Value(nil),
-			})
-			listValue = &bpparser.Value{
-				Type: bpparser.List,
+			if ret, ok := f.Variables[0].EvalFunction(scope); ok {
+				listValue.ListValue = append(listValue.ListValue, bpparser.Value{
+					Type:        bpparser.String,
+					StringValue: ret,
+				})
+			} else {
+				// Variable by itself, variable is probably a list
+				if !f.Variables[0].Name.Const() {
+					return nil, fmt.Errorf("unsupported non-const variable name")
+				}
+				if len(listValue.ListValue) > 0 {
+					listOfListValues = append(listOfListValues, listValue)
+				}
+				listOfListValues = append(listOfListValues, &bpparser.Value{
+					Type:     bpparser.List,
+					Variable: f.Variables[0].Name.Value(nil),
+				})
+				listValue = &bpparser.Value{
+					Type: bpparser.List,
+				}
 			}
 		} else {
-			s, err := makeToStringExpression(f)
+			s, err := makeToStringExpression(f, scope)
 			if err != nil {
 				return nil, err
 			}
diff --git a/androidmk/parser/scope.go b/androidmk/parser/scope.go
index 742ad38..5e94ea5 100644
--- a/androidmk/parser/scope.go
+++ b/androidmk/parser/scope.go
@@ -58,7 +58,7 @@
 	builtinScope["__builtin_dollar"] = "$"
 }
 
-func (v Variable) Value(scope Scope) string {
+func (v Variable) EvalFunction(scope Scope) (string, bool) {
 	f := v.Name.SplitN(" \t", 2)
 	if len(f) > 1 && f[0].Const() {
 		fname := f[0].Value(nil)
@@ -70,13 +70,20 @@
 			}
 
 			if fname == "call" {
-				return scope.Call(argVals[0], argVals[1:])
+				return scope.Call(argVals[0], argVals[1:]), true
 			} else {
-				return "__builtin_func:" + fname + " " + strings.Join(argVals, " ")
+				return "__builtin_func:" + fname + " " + strings.Join(argVals, " "), true
 			}
 		}
 	}
 
+	return "", false
+}
+
+func (v Variable) Value(scope Scope) string {
+	if ret, ok := v.EvalFunction(scope); ok {
+		return ret
+	}
 	return scope.Get(v.Name.Value(scope))
 }