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 main 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, scope mkparser.Scope) (bpparser.Expression, error) { 64 65 var val bpparser.Expression 66 var err error 67 68 if ms.Strings[0] != "" { 69 val = stringToStringValue(ms.Strings[0]) 70 } 71 72 for i, s := range ms.Strings[1:] { 73 if ret, ok := ms.Variables[i].EvalFunction(scope); ok { 74 if len(ret) > 1 { 75 return nil, fmt.Errorf("Unexpected list value %s", ms.Dump()) 76 } 77 val, err = addValues(val, stringToStringValue(ret[0])) 78 } else { 79 name := ms.Variables[i].Name 80 if !name.Const() { 81 return nil, fmt.Errorf("Unsupported non-const variable name %s", name.Dump()) 82 } 83 tmp := &bpparser.Variable{ 84 Name: name.Value(nil), 85 Value: &bpparser.String{}, 86 } 87 88 if tmp.Name == "TOP" { 89 if s[0] == '/' { 90 s = s[1:] 91 } else { 92 s = "." + s 93 } 94 } else { 95 val, err = addValues(val, tmp) 96 if err != nil { 97 return nil, err 98 } 99 } 100 } 101 102 if s != "" { 103 tmp := stringToStringValue(s) 104 val, err = addValues(val, tmp) 105 if err != nil { 106 return nil, err 107 } 108 } 109 } 110 111 return val, nil 112} 113 114func stringToListValue(s string) bpparser.Expression { 115 list := strings.Fields(s) 116 valList := make([]bpparser.Expression, len(list)) 117 for i, l := range list { 118 valList[i] = &bpparser.String{ 119 Value: l, 120 } 121 } 122 return &bpparser.List{ 123 Values: valList, 124 } 125 126} 127 128func makeToListExpression(ms *mkparser.MakeString, scope mkparser.Scope) (bpparser.Expression, error) { 129 130 fields := ms.Split(" \t") 131 132 var listOfListValues []bpparser.Expression 133 134 listValue := &bpparser.List{} 135 136 for _, f := range fields { 137 if len(f.Variables) == 1 && f.Strings[0] == "" && f.Strings[1] == "" { 138 if ret, ok := f.Variables[0].EvalFunction(scope); ok { 139 listValue.Values = append(listValue.Values, stringListToStringValueList(ret)...) 140 } else { 141 // Variable by itself, variable is probably a list 142 if !f.Variables[0].Name.Const() { 143 return nil, fmt.Errorf("unsupported non-const variable name") 144 } 145 if f.Variables[0].Name.Value(nil) == "TOP" { 146 listValue.Values = append(listValue.Values, &bpparser.String{ 147 Value: ".", 148 }) 149 } else { 150 if len(listValue.Values) > 0 { 151 listOfListValues = append(listOfListValues, listValue) 152 } 153 listOfListValues = append(listOfListValues, &bpparser.Variable{ 154 Name: f.Variables[0].Name.Value(nil), 155 Value: &bpparser.List{}, 156 }) 157 listValue = &bpparser.List{} 158 } 159 } 160 } else { 161 s, err := makeToStringExpression(f, scope) 162 if err != nil { 163 return nil, err 164 } 165 if s == nil { 166 continue 167 } 168 169 listValue.Values = append(listValue.Values, s) 170 } 171 } 172 173 if len(listValue.Values) > 0 { 174 listOfListValues = append(listOfListValues, listValue) 175 } 176 177 if len(listOfListValues) == 0 { 178 return listValue, nil 179 } 180 181 val := listOfListValues[0] 182 for _, tmp := range listOfListValues[1:] { 183 var err error 184 val, err = addValues(val, tmp) 185 if err != nil { 186 return nil, err 187 } 188 } 189 190 return val, nil 191} 192 193func stringToBoolValue(s string) (bpparser.Expression, error) { 194 var b bool 195 s = strings.TrimSpace(s) 196 switch s { 197 case "true": 198 b = true 199 case "false", "": 200 b = false 201 case "-frtti": // HACK for LOCAL_RTTI_VALUE 202 b = true 203 default: 204 return nil, fmt.Errorf("unexpected bool value %s", s) 205 } 206 return &bpparser.Bool{ 207 Value: b, 208 }, nil 209} 210 211func makeToBoolExpression(ms *mkparser.MakeString) (bpparser.Expression, error) { 212 if !ms.Const() { 213 if len(ms.Variables) == 1 && ms.Strings[0] == "" && ms.Strings[1] == "" { 214 name := ms.Variables[0].Name 215 if !name.Const() { 216 return nil, fmt.Errorf("unsupported non-const variable name") 217 } 218 return &bpparser.Variable{ 219 Name: name.Value(nil), 220 Value: &bpparser.Bool{}, 221 }, nil 222 } else { 223 return nil, fmt.Errorf("non-const bool expression %s", ms.Dump()) 224 } 225 } 226 227 return stringToBoolValue(ms.Value(nil)) 228} 229