blob: ce2f279650162bc35542fc398fb8d668f723356c [file] [log] [blame]
package main
import (
"fmt"
"strings"
mkparser "android/soong/androidmk/parser"
bpparser "github.com/google/blueprint/parser"
)
func stringToStringValue(s string) *bpparser.Value {
return &bpparser.Value{
Type: bpparser.String,
StringValue: s,
}
}
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,
ListValue: []bpparser.Value{*val1},
}
} else if val2.Type == bpparser.String && val1.Type == bpparser.List {
val2 = &bpparser.Value{
Type: bpparser.List,
ListValue: []bpparser.Value{*val1},
}
} else if val1.Type != val2.Type {
return nil, fmt.Errorf("cannot add mismatched types")
}
return &bpparser.Value{
Type: val1.Type,
Expression: &bpparser.Expression{
Operator: '+',
Args: [2]bpparser.Value{*val1, *val2},
},
}, nil
}
func makeToStringExpression(ms *mkparser.MakeString, scope mkparser.Scope) (*bpparser.Value, error) {
var val *bpparser.Value
var err error
if ms.Strings[0] != "" {
val = stringToStringValue(ms.Strings[0])
}
for i, s := range ms.Strings[1:] {
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),
}
val, err = addValues(val, tmp)
if err != nil {
return nil, err
}
}
if s != "" {
tmp := stringToStringValue(s)
val, err = addValues(val, tmp)
if err != nil {
return nil, err
}
}
}
return val, nil
}
func stringToListValue(s string) *bpparser.Value {
list := strings.Fields(s)
valList := make([]bpparser.Value, len(list))
for i, l := range list {
valList[i] = bpparser.Value{
Type: bpparser.String,
StringValue: l,
}
}
return &bpparser.Value{
Type: bpparser.List,
ListValue: valList,
}
}
func makeToListExpression(ms *mkparser.MakeString, scope mkparser.Scope) (*bpparser.Value, error) {
fields := ms.Split(" \t")
var listOfListValues []*bpparser.Value
listValue := &bpparser.Value{
Type: bpparser.List,
}
for _, f := range fields {
if len(f.Variables) == 1 && f.Strings[0] == "" && f.Strings[1] == "" {
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, scope)
if err != nil {
return nil, err
}
if s == nil {
continue
}
listValue.ListValue = append(listValue.ListValue, *s)
}
}
if len(listValue.ListValue) > 0 {
listOfListValues = append(listOfListValues, listValue)
}
if len(listOfListValues) == 0 {
return listValue, nil
}
val := listOfListValues[0]
for _, tmp := range listOfListValues[1:] {
var err error
val, err = addValues(val, tmp)
if err != nil {
return nil, err
}
}
return val, nil
}
func stringToBoolValue(s string) (*bpparser.Value, error) {
var b bool
s = strings.TrimSpace(s)
switch s {
case "true":
b = true
case "false", "":
b = false
case "-frtti": // HACK for LOCAL_RTTI_VALUE
b = true
default:
return nil, fmt.Errorf("unexpected bool value %s", s)
}
return &bpparser.Value{
Type: bpparser.Bool,
BoolValue: b,
}, nil
}
func makeToBoolExpression(ms *mkparser.MakeString) (*bpparser.Value, error) {
if !ms.Const() {
if len(ms.Variables) == 1 && ms.Strings[0] == "" && ms.Strings[1] == "" {
name := ms.Variables[0].Name
if !name.Const() {
return nil, fmt.Errorf("unsupported non-const variable name")
}
return &bpparser.Value{
Type: bpparser.Bool,
Variable: name.Value(nil),
}, nil
} else {
return nil, fmt.Errorf("non-const bool expression %s", ms.Dump())
}
}
return stringToBoolValue(ms.Value(nil))
}