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