1// Copyright 2017 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package androidmk 16 17import ( 18 "fmt" 19 "strings" 20 21 mkparser "android/soong/androidmk/parser" 22 23 bpparser "github.com/google/blueprint/parser" 24) 25 26func stringToStringValue(s string) bpparser.Expression { 27 return &bpparser.String{ 28 Value: s, 29 } 30} 31 32func stringListToStringValueList(list []string) []bpparser.Expression { 33 valList := make([]bpparser.Expression, len(list)) 34 for i, l := range list { 35 valList[i] = stringToStringValue(l) 36 } 37 return valList 38} 39 40func addValues(val1, val2 bpparser.Expression) (bpparser.Expression, error) { 41 if val1 == nil { 42 return val2, nil 43 } 44 45 if val1.Type() == bpparser.StringType && val2.Type() == bpparser.ListType { 46 val1 = &bpparser.List{ 47 Values: []bpparser.Expression{val1}, 48 } 49 } else if val2.Type() == bpparser.StringType && val1.Type() == bpparser.ListType { 50 val2 = &bpparser.List{ 51 Values: []bpparser.Expression{val1}, 52 } 53 } else if val1.Type() != val2.Type() { 54 return nil, fmt.Errorf("cannot add mismatched types") 55 } 56 57 return &bpparser.Operator{ 58 Operator: '+', 59 Args: [2]bpparser.Expression{val1, val2}, 60 }, nil 61} 62 63func makeToStringExpression(ms *mkparser.MakeString, file *bpFile) (bpparser.Expression, error) { 64 var val bpparser.Expression 65 var err error 66 67 if ms.Strings[0] != "" { 68 val = stringToStringValue(ms.Strings[0]) 69 } 70 71 for i, s := range ms.Strings[1:] { 72 if ret, ok := ms.Variables[i].EvalFunction(file.scope); ok { 73 if len(ret) > 1 { 74 return nil, fmt.Errorf("Unexpected list value %s", ms.Dump()) 75 } 76 val, err = addValues(val, stringToStringValue(ret[0])) 77 } else { 78 name, err := extractVariableName(ms.Variables[i].Name, file) 79 if err != nil { 80 return nil, err 81 } 82 tmp := &bpparser.Variable{ 83 Name: name, 84 Value: &bpparser.String{}, 85 } 86 87 if tmp.Name == "TOP" { 88 if s[0] == '/' { 89 s = s[1:] 90 } else { 91 s = "." + s 92 } 93 } else { 94 val, err = addValues(val, tmp) 95 if err != nil { 96 return nil, err 97 } 98 } 99 } 100 101 if s != "" { 102 tmp := stringToStringValue(s) 103 val, err = addValues(val, tmp) 104 if err != nil { 105 return nil, err 106 } 107 } 108 } 109 110 return val, nil 111} 112 113func stringToListValue(s string) bpparser.Expression { 114 list := strings.Fields(s) 115 valList := make([]bpparser.Expression, len(list)) 116 for i, l := range list { 117 valList[i] = &bpparser.String{ 118 Value: l, 119 } 120 } 121 return &bpparser.List{ 122 Values: valList, 123 } 124 125} 126 127func makeToListExpression(ms *mkparser.MakeString, file *bpFile) (bpparser.Expression, error) { 128 fields := ms.Split(" \t") 129 130 var listOfListValues []bpparser.Expression 131 132 listValue := &bpparser.List{} 133 134 for _, f := range fields { 135 if len(f.Variables) == 1 && f.Strings[0] == "" && f.Strings[1] == "" { 136 if ret, ok := f.Variables[0].EvalFunction(file.scope); ok { 137 listValue.Values = append(listValue.Values, stringListToStringValueList(ret)...) 138 } else { 139 name, err := extractVariableName(f.Variables[0].Name, file) 140 if err != nil { 141 return nil, err 142 } 143 if name == "TOP" { 144 listValue.Values = append(listValue.Values, &bpparser.String{ 145 Value: ".", 146 }) 147 } else { 148 if len(listValue.Values) > 0 { 149 listOfListValues = append(listOfListValues, listValue) 150 } 151 listOfListValues = append(listOfListValues, &bpparser.Variable{ 152 Name: name, 153 Value: &bpparser.List{}, 154 }) 155 listValue = &bpparser.List{} 156 } 157 } 158 } else { 159 s, err := makeToStringExpression(f, file) 160 if err != nil { 161 return nil, err 162 } 163 if s == nil { 164 continue 165 } 166 167 listValue.Values = append(listValue.Values, s) 168 } 169 } 170 171 if len(listValue.Values) > 0 { 172 listOfListValues = append(listOfListValues, listValue) 173 } 174 175 if len(listOfListValues) == 0 { 176 return listValue, nil 177 } 178 179 val := listOfListValues[0] 180 for _, tmp := range listOfListValues[1:] { 181 var err error 182 val, err = addValues(val, tmp) 183 if err != nil { 184 return nil, err 185 } 186 } 187 188 return val, nil 189} 190 191func stringToBoolValue(s string) (bpparser.Expression, error) { 192 var b bool 193 s = strings.TrimSpace(s) 194 switch s { 195 case "true": 196 b = true 197 case "false", "": 198 b = false 199 case "-frtti": // HACK for LOCAL_RTTI_VALUE 200 b = true 201 default: 202 return nil, fmt.Errorf("unexpected bool value %s", s) 203 } 204 return &bpparser.Bool{ 205 Value: b, 206 }, nil 207} 208 209func makeToBoolExpression(ms *mkparser.MakeString, file *bpFile) (bpparser.Expression, error) { 210 if !ms.Const() { 211 if len(ms.Variables) == 1 && ms.Strings[0] == "" && ms.Strings[1] == "" { 212 name, err := extractVariableName(ms.Variables[0].Name, file) 213 if err != nil { 214 return nil, err 215 } 216 return &bpparser.Variable{ 217 Name: name, 218 Value: &bpparser.Bool{}, 219 }, nil 220 } else { 221 return nil, fmt.Errorf("non-const bool expression %s", ms.Dump()) 222 } 223 } 224 225 return stringToBoolValue(ms.Value(nil)) 226} 227 228func extractVariableName(name *mkparser.MakeString, file *bpFile) (string, error) { 229 if !name.Const() { 230 return "", fmt.Errorf("Unsupported non-const variable name %s", name.Dump()) 231 } 232 233 variableName := name.Value(nil) 234 235 if newName, ok := file.variableRenames[variableName]; ok { 236 variableName = newName 237 } 238 239 return variableName, nil 240} 241