Home | History | Annotate | Download | only in core
      1 # Copyright (C) 2009 The Android Open Source Project
      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 
     16 # Common utility functions.
     17 #
     18 # NOTE: All the functions here should be purely functional, i.e. avoid
     19 #       using global variables or depend on the file system / environment
     20 #       variables. This makes testing easier.
     21 
     22 # -----------------------------------------------------------------------------
     23 # Macro    : empty
     24 # Returns  : an empty macro
     25 # Usage    : $(empty)
     26 # -----------------------------------------------------------------------------
     27 empty :=
     28 
     29 # -----------------------------------------------------------------------------
     30 # Macro    : space
     31 # Returns  : a single space
     32 # Usage    : $(space)
     33 # -----------------------------------------------------------------------------
     34 space  := $(empty) $(empty)
     35 
     36 space4 := $(space)$(space)$(space)$(space)
     37 
     38 # -----------------------------------------------------------------------------
     39 # Macro    : comma
     40 # Returns  : a single comma
     41 # Usage    : $(comma)
     42 # -----------------------------------------------------------------------------
     43 comma := ,
     44 
     45 # -----------------------------------------------------------------------------
     46 # Function : remove-duplicates
     47 # Arguments: a list
     48 # Returns  : the list with duplicate items removed, order is preserved.
     49 # Usage    : $(call remove-duplicates, <LIST>)
     50 # Note     : This is equivalent to the 'uniq' function provided by GMSL,
     51 #            however this implementation is non-recursive and *much*
     52 #            faster. It will also not explode the stack with a lot of
     53 #            items like 'uniq' does.
     54 # -----------------------------------------------------------------------------
     55 remove-duplicates = $(strip \
     56   $(eval __uniq_ret :=) \
     57   $(foreach __uniq_item,$1,\
     58     $(if $(findstring $(__uniq_item),$(__uniq_ret)),,\
     59       $(eval __uniq_ret += $(__uniq_item))\
     60     )\
     61   )\
     62   $(__uniq_ret))
     63 
     64 -test-remove-duplicates = \
     65   $(call test-expect,,$(call remove-duplicates))\
     66   $(call test-expect,foo bar,$(call remove-duplicates,foo bar))\
     67   $(call test-expect,foo bar,$(call remove-duplicates,foo bar foo bar))\
     68   $(call test-expect,foo bar,$(call remove-duplicates,foo foo bar bar bar))
     69 
     70 # -----------------------------------------------------------------------------
     71 # Function : clear-vars
     72 # Arguments: 1: list of variable names
     73 #            2: file where the variable should be defined
     74 # Returns  : None
     75 # Usage    : $(call clear-vars, VAR1 VAR2 VAR3...)
     76 # Rationale: Clears/undefines all variables in argument list
     77 # -----------------------------------------------------------------------------
     78 clear-vars = $(foreach __varname,$1,$(eval $(__varname) := $(empty)))
     79 
     80 # -----------------------------------------------------------------------------
     81 # Function : filter-by
     82 # Arguments: 1: list
     83 #            2: predicate function, will be called as $(call $2,<name>)
     84 #               and it this returns a non-empty value, then <name>
     85 #               will be appended to the result.
     86 # Returns  : elements of $1 that satisfy the predicate function $2
     87 # -----------------------------------------------------------------------------
     88 filter-by = $(strip \
     89   $(foreach __filter_by_n,$1,\
     90     $(if $(call $2,$(__filter_by_n)),$(__filter_by_n))))
     91 
     92 -test-filter-by = \
     93     $(eval -local-func = $$(call seq,foo,$$1))\
     94     $(call test-expect,,$(call filter-by,,-local-func))\
     95     $(call test-expect,foo,$(call filter-by,foo,-local-func))\
     96     $(call test-expect,foo,$(call filter-by,foo bar,-local-func))\
     97     $(call test-expect,foo foo,$(call filter-by,aaa foo bar foo,-local-func))\
     98     $(eval -local-func = $$(call sne,foo,$$1))\
     99     $(call test-expect,,$(call filter-by,,-local-func))\
    100     $(call test-expect,,$(call filter-by,foo,-local-func))\
    101     $(call test-expect,bar,$(call filter-by,foo bar,-local-func))\
    102     $(call test-expect,aaa bar,$(call filter-by,aaa foo bar,-local-func))
    103 
    104 # -----------------------------------------------------------------------------
    105 # Function : filter-out-by
    106 # Arguments: 1: list
    107 #            2: predicate function, will be called as $(call $2,<name>)
    108 #               and it this returns an empty value, then <name>
    109 #               will be appended to the result.
    110 # Returns  : elements of $1 that do not satisfy the predicate function $2
    111 # -----------------------------------------------------------------------------
    112 filter-out-by = $(strip \
    113   $(foreach __filter_out_by_n,$1,\
    114     $(if $(call $2,$(__filter_out_by_n)),,$(__filter_out_by_n))))
    115 
    116 -test-filter-out-by = \
    117     $(eval -local-func = $$(call seq,foo,$$1))\
    118     $(call test-expect,,$(call filter-out-by,,-local-func))\
    119     $(call test-expect,,$(call filter-out-by,foo,-local-func))\
    120     $(call test-expect,bar,$(call filter-out-by,foo bar,-local-func))\
    121     $(call test-expect,aaa bar,$(call filter-out-by,aaa foo bar foo,-local-func))\
    122     $(eval -local-func = $$(call sne,foo,$$1))\
    123     $(call test-expect,,$(call filter-out-by,,-local-func))\
    124     $(call test-expect,foo,$(call filter-out-by,foo,-local-func))\
    125     $(call test-expect,foo,$(call filter-out-by,foo bar,-local-func))\
    126     $(call test-expect,foo foo,$(call filter-out-by,aaa foo bar foo,-local-func))
    127 
    128 # -----------------------------------------------------------------------------
    129 # Function : find-first
    130 # Arguments: 1: list
    131 #            2: predicate function, will be called as $(call $2,<name>).
    132 # Returns  : the first item of $1 that satisfies the predicate.
    133 # -----------------------------------------------------------------------------
    134 find-first = $(firstword $(call filter-by,$1,$2))
    135 
    136 -test-find-first.empty = \
    137     $(eval -local-pred = $$(call seq,foo,$$1))\
    138     $(call test-expect,,$(call find-first,,-local-pred))\
    139     $(call test-expect,,$(call find-first,bar,-local-pred))
    140 
    141 -test-find-first.simple = \
    142     $(eval -local-pred = $$(call seq,foo,$$1))\
    143     $(call test-expect,foo,$(call find-first,foo,-local-pred))\
    144     $(call test-expect,foo,$(call find-first,aaa foo bar,-local-pred))\
    145     $(call test-expect,foo,$(call find-first,aaa foo foo bar,-local-pred))
    146 
    147 # -----------------------------------------------------------------------------
    148 # Function : parent-dir
    149 # Arguments: 1: path
    150 # Returns  : Parent dir or path of $1, with final separator removed.
    151 # -----------------------------------------------------------------------------
    152 parent-dir = $(patsubst %/,%,$(dir $(1:%/=%)))
    153 
    154 -test-parent-dir = \
    155   $(call test-expect,,$(call parent-dir))\
    156   $(call test-expect,.,$(call parent-dir,foo))\
    157   $(call test-expect,foo,$(call parent-dir,foo/bar))\
    158   $(call test-expect,foo,$(call parent-dir,foo/bar/))
    159 
    160 # -----------------------------------------------------------------------------
    161 # Strip any 'lib' prefix in front of a given string.
    162 #
    163 # Function : strip-lib-prefix
    164 # Arguments: 1: module name
    165 # Returns  : module name, without any 'lib' prefix if any
    166 # Usage    : $(call strip-lib-prefix,$(LOCAL_MODULE))
    167 # -----------------------------------------------------------------------------
    168 strip-lib-prefix = $(1:lib%=%)
    169 
    170 -test-strip-lib-prefix = \
    171   $(call test-expect,,$(call strip-lib-prefix,))\
    172   $(call test-expect,foo,$(call strip-lib-prefix,foo))\
    173   $(call test-expect,foo,$(call strip-lib-prefix,libfoo))\
    174   $(call test-expect,nolibfoo,$(call strip-lib-prefix,nolibfoo))\
    175   $(call test-expect,foolib,$(call strip-lib-prefix,foolib))\
    176   $(call test-expect,foo bar,$(call strip-lib-prefix,libfoo libbar))
    177 
    178 # -----------------------------------------------------------------------------
    179 # Left-justify input string with spaces to fill a width of 15.
    180 # Function: left-justify-quoted-15
    181 # Arguments: 1: Input text
    182 # Returns: A quoted string that can be used in command scripts to print
    183 #          the left-justified input with host-echo.
    184 #
    185 # Usage:  ---->@$(call host-echo, $(call left-justify-quoted-15,$(_TEXT)): Do stuff)
    186 #         Where ----> is a TAB character.
    187 # -----------------------------------------------------------------------------
    188 left-justify-quoted-15 = $(call -left-justify,$1,xxxxxxxxxxxxxxx)
    189 
    190 -test-left-justify-quoted-15 = \
    191   $(call test-expect,"               ",$(call left-justify-quoted-15,))\
    192   $(call test-expect,"Foo Bar        ",$(call left-justify-quoted-15,Foo Bar))\
    193   $(call test-expect,"Very long string over 15 characters wide",$(strip \
    194     $(call left-justify-quoted-15,Very long string over 15 characters wide)))
    195 
    196 # Used internally to compute a quoted left-justified text string.
    197 # $1: Input string.
    198 # $2: A series of contiguous x's, its length determines the full width to justify to.
    199 # Return: A quoted string with the input text left-justified appropriately.
    200 -left-justify = $(strip \
    201     $(eval __lj_temp := $(subst $(space),x,$1))\
    202     $(foreach __lj_a,$(__gmsl_characters),$(eval __lj_temp := $$(subst $$(__lj_a),x,$(__lj_temp))))\
    203     $(eval __lj_margin := $$(call -justification-margin,$(__lj_temp),$2)))"$1$(subst x,$(space),$(__lj_margin))"
    204 
    205 -test-left-justify = \
    206   $(call test-expect,"",$(call -left-justify,,))\
    207   $(call test-expect,"foo",$(call -left-justify,foo,xxx))\
    208   $(call test-expect,"foo ",$(call -left-justify,foo,xxxx))\
    209   $(call test-expect,"foo   ",$(call -left-justify,foo,xxxxxx))\
    210   $(call test-expect,"foo         ",$(call -left-justify,foo,xxxxxxxxxxxx))\
    211   $(call test-expect,"very long string",$(call -left-justify,very long string,xxx))\
    212 
    213 # Used internally to compute a justification margin.
    214 # Expects $1 to be defined to a string of consecutive x's (e.g. 'xxxx')
    215 # Expects $2 to be defined to a maximum string of x's (e.g. 'xxxxxxxxx')
    216 # Returns a string of x's such as $1 + $(result) is equal to $2
    217 # If $1 is larger than $2, return empty string..
    218 -justification-margin = $(strip \
    219     $(if $2,\
    220       $(if $1,\
    221         $(call -justification-margin-inner,$1,$2),\
    222         $2\
    223       ),\
    224     $1))
    225 
    226 -justification-margin-inner = $(if $(findstring $2,$1),,x$(call -justification-margin-inner,x$1,$2))
    227 
    228 -test-justification-margin = \
    229   $(call test-expect,,$(call -justification-margin,,))\
    230   $(call test-expect,,$(call -justification-margin,xxx,xxx))\
    231   $(call test-expect,xxxxxx,$(call -justification-margin,,xxxxxx))\
    232   $(call test-expect,xxxxx,$(call -justification-margin,x,xxxxxx))\
    233   $(call test-expect,xxxx,$(call -justification-margin,xx,xxxxxx))\
    234   $(call test-expect,xxx,$(call -justification-margin,xxx,xxxxxx))\
    235   $(call test-expect,xx,$(call -justification-margin,xxxx,xxxxxx))\
    236   $(call test-expect,x,$(call -justification-margin,xxxxx,xxxxxx))\
    237   $(call test-expect,,$(call -justification-margin,xxxxxx,xxxxxx))\
    238   $(call test-expect,,$(call -justification-margin,xxxxxxxxxxx,xxxxxx))\
    239 
    240