// Copyright 2017 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 androidmk import ( "fmt" "strings" mkparser "android/soong/androidmk/parser" bpparser "github.com/google/blueprint/parser" ) func stringToStringValue(s string) bpparser.Expression { return &bpparser.String{ Value: s, } } func stringListToStringValueList(list []string) []bpparser.Expression { valList := make([]bpparser.Expression, len(list)) for i, l := range list { valList[i] = stringToStringValue(l) } return valList } func addValues(val1, val2 bpparser.Expression) (bpparser.Expression, error) { if val1 == nil { return val2, nil } if val1.Type() == bpparser.StringType && val2.Type() == bpparser.ListType { val1 = &bpparser.List{ Values: []bpparser.Expression{val1}, } } else if val2.Type() == bpparser.StringType && val1.Type() == bpparser.ListType { val2 = &bpparser.List{ Values: []bpparser.Expression{val1}, } } else if val1.Type() != val2.Type() { return nil, fmt.Errorf("cannot add mismatched types") } return &bpparser.Operator{ Operator: '+', Args: [2]bpparser.Expression{val1, val2}, }, nil } func makeToStringExpression(ms *mkparser.MakeString, file *bpFile) (bpparser.Expression, error) { var val bpparser.Expression 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(file.scope); ok { if len(ret) > 1 { return nil, fmt.Errorf("Unexpected list value %s", ms.Dump()) } val, err = addValues(val, stringToStringValue(ret[0])) } else { name, err := extractVariableName(ms.Variables[i].Name, file) if err != nil { return nil, err } tmp := &bpparser.Variable{ Name: name, Value: &bpparser.String{}, } if tmp.Name == "TOP" { if s[0] == '/' { s = s[1:] } else { s = "." + s } } else { 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.Expression { list := strings.Fields(s) valList := make([]bpparser.Expression, len(list)) for i, l := range list { valList[i] = &bpparser.String{ Value: l, } } return &bpparser.List{ Values: valList, } } func makeToListExpression(ms *mkparser.MakeString, file *bpFile) (bpparser.Expression, error) { fields := ms.Split(" \t") var listOfListValues []bpparser.Expression listValue := &bpparser.List{} for _, f := range fields { if len(f.Variables) == 1 && f.Strings[0] == "" && f.Strings[1] == "" { if ret, ok := f.Variables[0].EvalFunction(file.scope); ok { listValue.Values = append(listValue.Values, stringListToStringValueList(ret)...) } else { name, err := extractVariableName(f.Variables[0].Name, file) if err != nil { return nil, err } if name == "TOP" { listValue.Values = append(listValue.Values, &bpparser.String{ Value: ".", }) } else { if len(listValue.Values) > 0 { listOfListValues = append(listOfListValues, listValue) } listOfListValues = append(listOfListValues, &bpparser.Variable{ Name: name, Value: &bpparser.List{}, }) listValue = &bpparser.List{} } } } else { s, err := makeToStringExpression(f, file) if err != nil { return nil, err } if s == nil { continue } listValue.Values = append(listValue.Values, s) } } if len(listValue.Values) > 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.Expression, 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.Bool{ Value: b, }, nil } func makeToBoolExpression(ms *mkparser.MakeString, file *bpFile) (bpparser.Expression, error) { if !ms.Const() { if len(ms.Variables) == 1 && ms.Strings[0] == "" && ms.Strings[1] == "" { name, err := extractVariableName(ms.Variables[0].Name, file) if err != nil { return nil, err } return &bpparser.Variable{ Name: name, Value: &bpparser.Bool{}, }, nil } else { return nil, fmt.Errorf("non-const bool expression %s", ms.Dump()) } } return stringToBoolValue(ms.Value(nil)) } func extractVariableName(name *mkparser.MakeString, file *bpFile) (string, error) { if !name.Const() { return "", fmt.Errorf("Unsupported non-const variable name %s", name.Dump()) } variableName := name.Value(nil) if newName, ok := file.variableRenames[variableName]; ok { variableName = newName } return variableName, nil }