Home | History | Annotate | Download | only in androidmk
      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