📄 feature.jam
字号:
$(feature).default = $(values[1]) ;
}
$(feature).values += $(values) ;
}
# Checks that value-string is a valid value-string for the given feature.
rule validate-value-string ( feature value-string )
{
if ! (
free in $($(feature).attributes)
|| ( $(value-string) in $(feature).values )
)
{
local values = $(value-string) ;
if $($(feature).subfeatures)
{
values = [ regex.split $(value-string) - ] ;
}
if ! ( $(values[1]) in $($(feature).values) )
{
error \"$(values[1])\" is not a known value of feature $(feature)
: legal values: \"$($(feature).values)\" ;
}
for local v in $(values[2-])
{
# this will validate any subfeature values in value-string
implied-subfeature $(feature) $(v) : $(values[1]) ;
}
}
}
# Extends the given subfeature with the subvalues. If the optional
# value-string is provided, the subvalues are only valid for the given
# value of the feature. Thus, you could say that
# <target-platform>mingw is specifc to <toolset>gcc-2.95.2 as follows:
#
# extend-subfeature toolset gcc-2.95.2 : target-platform : mingw ;
#
rule extend-subfeature (
feature # The feature whose subfeature is being extended
value-string ? # If supplied, specifies a specific value of the
# main feature for which the new subfeature values
# are valid
: subfeature # The name of the subfeature
: subvalues * # The additional values of the subfeature being defined.
)
{
feature = [ grist $(feature) ] ;
validate-feature $(feature) ;
if $(value-string)
{
validate-value-string $(feature) $(value-string) ;
}
local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
local f = [ utility.ungrist $(feature) ] ;
extend $(f)-$(subfeature-name) : $(subvalues) ;
# provide a way to get from the given feature or property and
# subfeature value to the subfeature name.
$(feature)$(value-string:E="")<>$(subvalues).subfeature = $(subfeature-name) ;
}
# Can be called three ways:
#
# 1. extend feature : values *
# 2. extend <feature> subfeature : values *
# 3. extend <feature>value-string subfeature : values *
#
# * Form 1 adds the given values to the given feature
# * Forms 2 and 3 add subfeature values to the given feature
# * Form 3 adds the subfeature values as specific to the given
# property value-string.
#
rule extend ( feature-or-property subfeature ? : values * )
{
local
feature # If a property was specified this is its feature
value-string # E.G., the gcc-2.95-2 part of <toolset>gcc-2.95.2
;
# if a property was specified
if $(feature-or-property:G) && $(feature-or-property:G=)
{
# Extract the feature and value-string, if any.
feature = $(feature-or-property:G) ;
value-string = $(feature-or-property:G=) ;
}
else
{
feature = [ grist $(feature-or-property) ] ;
}
# Dispatch to the appropriate handler
if $(subfeature)
{
extend-subfeature $(feature) $(value-string)
: $(subfeature) : $(values) ;
}
else
{
# If no subfeature was specified, we didn't expect to see a
# value-string
if $(value-string)
{
error can only be specify a property as the first argument
when extending a subfeature
: usage:
: " extend" feature ":" values...
: " | extend" <feature>value-string subfeature ":" values...
;
}
extend-feature $(feature) : $(values) ;
}
}
local rule get-subfeature-name ( subfeature value-string ? )
{
local prefix = $(value-string): ;
return $(prefix:E="")$(subfeature) ;
}
# Declares a subfeature
rule subfeature (
feature # Root feature that is not a subfeature
value-string ? # A value-string specifying which feature or
# subfeature values this subfeature is specific to,
# if any
: subfeature # The name of the subfeature being declared
: subvalues * # The allowed values of this subfeature
: attributes * # The attributes of the subfeature
)
{
feature = [ grist $(feature) ] ;
validate-feature $(feature) ;
# Add grist to the subfeature name if a value-string was supplied
local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
if $(subfeature-name) in $($(feature).subfeatures)
{
error \"$(subfeature)\" already declared as a subfeature of \"$(feature)\"
"specific to "$(value-string) ;
}
$(feature).subfeatures += $(subfeature-name) ;
# First declare the subfeature as a feature in its own right
local f = [ utility.ungrist $(feature) ] ;
feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ;
# Now make sure the subfeature values are known.
extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ;
}
# Set the components of the given composite property
rule compose ( composite-property : component-properties * )
{
local feature = $(composite-property:G) ;
if ! ( composite in [ attributes $(feature) ] )
{
error "$(feature)" is not a composite feature ;
}
$(composite-property).components ?= ;
if $($(composite-property).components)
{
error components of "$(composite-property)" already set:
$($(composite-property).components) ;
}
if $(composite-property) in $(components)
{
errror composite property "$(composite-property)" cannot have itself as a component ;
}
$(composite-property).components = $(component-properties) ;
}
local rule has-attribute ( attribute property )
{
if $(attribute) in [ attributes [ get-feature $(property) ] ]
{
return true ;
}
}
local rule expand-composite ( property )
{
return $(property)
[ sequence.transform expand-composite : $($(property).components) ] ;
}
# return all values of the given feature specified by the given property set.
rule get-values ( feature : properties * )
{
local result ;
for local p in $(properties)
{
if $(p:G) = $(feature)
{
result += $(p:G=) ;
}
}
return $(result) ;
}
rule free-features ( )
{
return $(free.features) ;
}
# Expand all composite properties in the set so that all components
# are explicitly expressed.
rule expand-composites ( properties * )
{
local explicit-features = $(properties:G) ;
local result ;
# now expand composite features
for local p in $(properties)
{
local expanded = [ expand-composite $(p) ] ;
for local x in $(expanded)
{
if ! $(x) in $(result)
{
local f = $(x:G) ;
if $(f) in $(free.features)
{
result += $(x) ;
}
else if ! $(x) in $(properties) # x is the result of expansion
{
if ! $(f) in $(explicit-features) # not explicitly-specified
{
if $(f) in $(result:G)
{
error expansions of composite features result in conflicting
values for $(f)
: values: [ get-values $(f) : $(result) ] $(x:G=)
: one contributing composite property was $(p) ;
}
else
{
result += $(x) ;
}
}
}
else if $(f) in $(result:G)
{
error explicitly-specified values of non-free feature
$(f) conflict :
"existing values:" [ get-values $(f) : $(properties) ] :
"value from expanding " $(p) ":" (x:G=) ;
}
else
{
result += $(x) ;
}
}
}
}
return $(result) ;
}
# Return true iff f is an ordinary subfeature of the parent-property's
# feature, or if f is a subfeature fo the parent-property's feature
# specific to the parent-property's value
local rule is-subfeature-of ( parent-property f )
{
if subfeature in $($(f).attributes)
{
local specific-subfeature = [ MATCH <(.*):(.*)> : $(f) ] ;
if $(specific-subfeature)
{
# The feature has the form
# <topfeature-topvalue:subfeature>,
# e.g. <toolset-msvc:version>
local feature-value = [ split-top-feature $(specific-subfeature[1]) ] ;
if <$(feature-value[1])>$(feature-value[2]) = $(parent-property)
{
return true ;
}
}
else
{
# The feature has the form <topfeature-subfeature>,
# e.g. <toolset-version>
local top-sub = [ split-top-feature [ utility.ungrist $(f) ] ] ;
if $(top-sub[2]) && <$(top-sub[1])> = $(parent-property:G)
{
return true ;
}
}
}
}
# as above, for subproperties
local rule is-subproperty-of ( parent-property p )
{
return [ is-subfeature-of $(parent-property) $(p:G) ] ;
}
# Given a property, return the subset of features consisting of all
# ordinary subfeatures of the property's feature, and all specific
# subfeatures of the property's feature which are conditional on the
# property's value.
local rule select-subfeatures ( parent-property : features * )
{
return [ sequence.filter is-subfeature-of $(parent-property) : $(features) ] ;
}
# as above, for subproperties
local rule select-subproperties ( parent-property : properties * )
{
return [ sequence.filter is-subproperty-of $(parent-property) : $(properties) ] ;
}
# Given a property set which may consist of composite and implicit
# properties and combined subfeature values, returns an expanded,
# normalized property set with all implicit features expressed
# explicitly, all subfeature values individually expressed, and all
# components of composite properties expanded. Non-free features
# directly expressed in the input properties cause any values of
# those features due to composite feature expansion to be dropped. If
# two values of a given non-free feature are directly expressed in the
# input, an error is issued.
rule expand ( properties * )
{
local expanded = [ expand-subfeatures $(properties) ] ;
return [ expand-composites $(expanded) ] ;
}
# Helper rule for minimize, below - return true iff property's feature
# is present in the contents of the variable named by feature-set-var.
local rule in-features ( feature-set-var property )
{
if $(property:G) in $($(feature-set-var))
{
return true ;
}
}
# Helper for minimize, below - returns the list with
# the same properties, but where all subfeatures
# are in the end of the list
local rule move-subfeatures-to-the-end ( properties * )
{
local x1 ;
local x2 ;
for local p in $(properties)
{
if subfeature in $($(p:G).attributes)
{
x2 += $(p) ;
}
else
{
x1 += $(p) ;
}
}
return $(x1) $(x2) ;
}
# Given an expanded property set, eliminate all redundancy: properties
# which are elements of other (composite) properties in the set will
# be eliminated. Non-symmetric properties equal to default values will be
# eliminated, unless the override a value from some composite property.
# Implicit properties will be expressed without feature
# grist, and sub-property values will be expressed as elements joined
# to the corresponding main property.
rule minimize ( properties * )
{
# Precondition checking
local implicits = [ set.intersection $(p:G=) : $(p:G) ] ;
if $(implicits)
{
error minimize requires an expanded property set, but \"$(implicits[1])\"
appears to be the value of an un-expanded implicit feature ;
}
# remove properties implied by composite features
local components = $($(properties).components) ;
local x = [ set.difference $(properties) : $(components) ] ;
# handle subfeatures and implicit features
x = [ move-subfeatures-to-the-end $(x) ] ;
local result ;
while $(x)
{
local p fullp = $(x[1]) ;
local f = $(p:G) ;
local v = $(p:G=) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -