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 15 package main 16 17 import ( 18 "fmt" 19 "strings" 20 21 mkparser "android/soong/androidmk/parser" 22 23 bpparser "github.com/google/blueprint/parser" 24 ) 25 26 func stringToStringValue(s string) bpparser.Expression { 27 return &bpparser.String{ 28 Value: s, 29 } 30 } 31 32 func addValues(val1, val2 bpparser.Expression) (bpparser.Expression, error) { 33 if val1 == nil { 34 return val2, nil 35 } 36 37 if val1.Type() == bpparser.StringType && val2.Type() == bpparser.ListType { 38 val1 = &bpparser.List{ 39 Values: []bpparser.Expression{val1}, 40 } 41 } else if val2.Type() == bpparser.StringType && val1.Type() == bpparser.ListType { 42 val2 = &bpparser.List{ 43 Values: []bpparser.Expression{val1}, 44 } 45 } else if val1.Type() != val2.Type() { 46 return nil, fmt.Errorf("cannot add mismatched types") 47 } 48 49 return &bpparser.Operator{ 50 Operator: '+', 51 Args: [2]bpparser.Expression{val1, val2}, 52 }, nil 53 } 54 55 func makeToStringExpression(ms *mkparser.MakeString, scope mkparser.Scope) (bpparser.Expression, error) { 56 57 var val bpparser.Expression 58 var err error 59 60 if ms.Strings[0] != "" { 61 val = stringToStringValue(ms.Strings[0]) 62 } 63 64 for i, s := range ms.Strings[1:] { 65 if ret, ok := ms.Variables[i].EvalFunction(scope); ok { 66 val, err = addValues(val, stringToStringValue(ret)) 67 } else { 68 name := ms.Variables[i].Name 69 if !name.Const() { 70 return nil, fmt.Errorf("Unsupported non-const variable name %s", name.Dump()) 71 } 72 tmp := &bpparser.Variable{ 73 Name: name.Value(nil), 74 Value: &bpparser.String{}, 75 } 76 77 if tmp.Name == "TOP" { 78 if s[0] == '/' { 79 s = s[1:] 80 } else { 81 s = "." + s 82 } 83 } else { 84 val, err = addValues(val, tmp) 85 if err != nil { 86 return nil, err 87 } 88 } 89 } 90 91 if s != "" { 92 tmp := stringToStringValue(s) 93 val, err = addValues(val, tmp) 94 if err != nil { 95 return nil, err 96 } 97 } 98 } 99 100 return val, nil 101 } 102 103 func stringToListValue(s string) bpparser.Expression { 104 list := strings.Fields(s) 105 valList := make([]bpparser.Expression, len(list)) 106 for i, l := range list { 107 valList[i] = &bpparser.String{ 108 Value: l, 109 } 110 } 111 return &bpparser.List{ 112 Values: valList, 113 } 114 115 } 116 117 func makeToListExpression(ms *mkparser.MakeString, scope mkparser.Scope) (bpparser.Expression, error) { 118 119 fields := ms.Split(" \t") 120 121 var listOfListValues []bpparser.Expression 122 123 listValue := &bpparser.List{} 124 125 for _, f := range fields { 126 if len(f.Variables) == 1 && f.Strings[0] == "" && f.Strings[1] == "" { 127 if ret, ok := f.Variables[0].EvalFunction(scope); ok { 128 listValue.Values = append(listValue.Values, &bpparser.String{ 129 Value: ret, 130 }) 131 } else { 132 // Variable by itself, variable is probably a list 133 if !f.Variables[0].Name.Const() { 134 return nil, fmt.Errorf("unsupported non-const variable name") 135 } 136 if f.Variables[0].Name.Value(nil) == "TOP" { 137 listValue.Values = append(listValue.Values, &bpparser.String{ 138 Value: ".", 139 }) 140 } else { 141 if len(listValue.Values) > 0 { 142 listOfListValues = append(listOfListValues, listValue) 143 } 144 listOfListValues = append(listOfListValues, &bpparser.Variable{ 145 Name: f.Variables[0].Name.Value(nil), 146 Value: &bpparser.List{}, 147 }) 148 listValue = &bpparser.List{} 149 } 150 } 151 } else { 152 s, err := makeToStringExpression(f, scope) 153 if err != nil { 154 return nil, err 155 } 156 if s == nil { 157 continue 158 } 159 160 listValue.Values = append(listValue.Values, s) 161 } 162 } 163 164 if len(listValue.Values) > 0 { 165 listOfListValues = append(listOfListValues, listValue) 166 } 167 168 if len(listOfListValues) == 0 { 169 return listValue, nil 170 } 171 172 val := listOfListValues[0] 173 for _, tmp := range listOfListValues[1:] { 174 var err error 175 val, err = addValues(val, tmp) 176 if err != nil { 177 return nil, err 178 } 179 } 180 181 return val, nil 182 } 183 184 func stringToBoolValue(s string) (bpparser.Expression, error) { 185 var b bool 186 s = strings.TrimSpace(s) 187 switch s { 188 case "true": 189 b = true 190 case "false", "": 191 b = false 192 case "-frtti": // HACK for LOCAL_RTTI_VALUE 193 b = true 194 default: 195 return nil, fmt.Errorf("unexpected bool value %s", s) 196 } 197 return &bpparser.Bool{ 198 Value: b, 199 }, nil 200 } 201 202 func makeToBoolExpression(ms *mkparser.MakeString) (bpparser.Expression, error) { 203 if !ms.Const() { 204 if len(ms.Variables) == 1 && ms.Strings[0] == "" && ms.Strings[1] == "" { 205 name := ms.Variables[0].Name 206 if !name.Const() { 207 return nil, fmt.Errorf("unsupported non-const variable name") 208 } 209 return &bpparser.Variable{ 210 Name: name.Value(nil), 211 Value: &bpparser.Bool{}, 212 }, nil 213 } else { 214 return nil, fmt.Errorf("non-const bool expression %s", ms.Dump()) 215 } 216 } 217 218 return stringToBoolValue(ms.Value(nil)) 219 } 220