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