📄 feature.jam
字号:
# Copyright 2001, 2002, 2003 Dave Abrahams# Copyright 2002, 2006 Rene Rivera# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus# Distributed under the Boost Software License, Version 1.0.# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)import assert : * ;import "class" : * ;import errors : lol->list ;import indirect ;import modules ;import regex ;import sequence ;import set ;import utility ;local rule setup ( ){ .all-attributes = implicit composite optional symmetric free incidental path dependency propagated link-incompatible subfeature order-sensitive ; .all-features = ; .all-subfeatures = ; .all-top-features = ; # non-subfeatures .all-implicit-values = ;}setup ;# Prepare a fresh space to test in by moving all global variable settings into# the given temporary module and erasing them here.#rule prepare-test ( temp-module ){ DELETE_MODULE $(temp-module) ; # Transfer globals to temp-module. for local v in [ VARNAMES feature ] { if [ MATCH (\\.) : $(v) ] { modules.poke $(temp-module) : $(v) : $($(v)) ; $(v) = ; } } setup ;}# Clear out all global variables and recover all variables from the given# temporary module.#rule finish-test ( temp-module ){ # Clear globals. for local v in [ VARNAMES feature ] { if [ MATCH (\\.) : $(v) ] { $(v) = ; } } for local v in [ VARNAMES $(temp-module) ] { $(v) = [ modules.peek $(temp-module) : $(v) ] ; } DELETE_MODULE $(temp-module) ;}# Transform features by bracketing any elements which are not already bracketed# by "<>".#local rule grist ( features * ){ local empty = "" ; return $(empty:G=$(features)) ;}# Declare a new feature with the given name, values, and attributes.#rule feature ( name # Feature name. : values * # Allowable values - may be extended later using feature.extend. : attributes * # Feature attributes (e.g. implicit, free, propagated...).){ name = [ grist $(name) ] ; local error ; # Check for any unknown attributes. if ! ( $(attributes) in $(.all-attributes) ) { error = unknown attributes: [ set.difference $(attributes) : $(.all-attributes) ] ; } else if $(name) in $(.all-features) { error = feature already defined: ; } else if implicit in $(attributes) && free in $(attributes) { error = free features cannot also be implicit ; } else if free in $(attributes) && propagated in $(attributes) { error = free features cannot be propagated ; } else { local m = [ MATCH (.*=.*) : $(values) ] ; if $(m[1]) { error = "feature value may not contain '='" ; } } if $(error) { errors.error $(error) : "in" feature declaration: : feature [ lol->list $(1) : $(2) : $(3) ] ; } $(name).values ?= ; $(name).attributes = $(attributes) ; $(name).subfeatures ?= ; $(attributes).features += $(name) ; .all-features += $(name) ; if subfeature in $(attributes) { .all-subfeatures += $(name) ; } else { .all-top-features += $(name) ; } extend $(name) : $(values) ;}# Sets the default value of the given feature, overriding any previous default.#rule set-default ( feature : value ){ local f = [ grist $(feature) ] ; if ! $(value) in $($(f).values) { errors.error "The specified default value, '$(value)' is invalid" : "allowed values are: " $($(f).values) ; } $(f).default = $(value) ;}# Returns the default property values for the given features.#rule defaults ( features * ){ local result ; for local f in $(features) { local gf = $(:E=:G=$(f)) ; local a = $($(gf).attributes) ; if ( free in $(a) ) || ( optional in $(a) ) { } else { result += $(gf)$($(gf).default) ; } } return $(result) ;}# Returns true iff all 'names' elements are valid features.#rule valid ( names + ){ if $(names) in $(.all-features) { return true ; }}# Returns the attibutes of the given feature.#rule attributes ( feature ){ return $($(:E=:G=$(feature)).attributes) ;}# Returns the values of the given feature.#rule values ( feature ){ return $($(:E=:G=$(feature)).values) ;}# Returns true iff 'value-string' is a value-string of an implicit feature.#rule is-implicit-value ( value-string ){ local v = [ regex.split $(value-string) - ] ; local failed ; if ! $(v[1]) in $(.all-implicit-values) { failed = true ; } else { local feature = $($(v[1]).implicit-feature) ; for local subvalue in $(v[2-]) { if ! [ find-implied-subfeature $(feature) $(subvalue) : $(v[1]) ] { failed = true ; } } } if ! $(failed) { return true ; }}# Returns the implicit feature associated with the given implicit value.#rule implied-feature ( implicit-value ){ local components = [ regex.split $(implicit-value) "-" ] ; local feature = $($(components[1]).implicit-feature) ; if ! $(feature) { errors.error \"$(implicit-value)\" is not a value of an implicit feature ; feature = "" ; # Keep testing happy; it expects a result. } return $(feature) ;}local rule find-implied-subfeature ( feature subvalue : value-string ? ){ # Feature should be of the form <feature-name>. if $(feature) != $(feature:G) { errors.error invalid feature $(feature) ; } return $($(feature)$(value-string:E="")<>$(subvalue).subfeature) ;}# Given a feature and a value of one of its subfeatures, find the name of the# subfeature. If value-string is supplied, looks for implied subfeatures that# are specific to that value of feature#rule implied-subfeature ( feature # The main feature name. subvalue # The value of one of its subfeatures. : value-string ? # The value of the main feature.){ local subfeature = [ find-implied-subfeature $(feature) $(subvalue) : $(value-string) ] ; if ! $(subfeature) { value-string ?= "" ; errors.error \"$(subvalue)\" is not a known subfeature value of $(feature)$(value-string) ; } return $(subfeature) ;}# Generate an error if the feature is unknown.#local rule validate-feature ( feature ){ if ! $(feature) in $(.all-features) { errors.error unknown feature \"$(feature)\" ; }}# Given a feature and its value or just a value corresponding to an implicit# feature, returns a property set consisting of all component subfeatures and# their values. For example all the following calls:## expand-subfeatures-aux <toolset>gcc-2.95.2-linux-x86# expand-subfeatures-aux gcc-2.95.2-linux-x86## return:## <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86#local rule expand-subfeatures-aux ( feature ? # Feature name or empty if value corresponds to an # implicit property. : value # Feature value. : dont-validate ? # If set, no value string validation will be done.){ if $(feature) { feature = $(feature) ; } if ! $(feature) { feature = [ implied-feature $(value) ] ; } else { validate-feature $(feature) ; } if ! $(dont-validate) { validate-value-string $(feature) $(value) ; } local components = [ regex.split $(value) "-" ] ; # Get the top-level feature's value. local value = $(components[1]:G=) ; local result = $(components[1]:G=$(feature)) ; local subvalues = $(components[2-]) ; while $(subvalues) { local subvalue = $(subvalues[1]) ; # Pop the head off of subvalues. subvalues = $(subvalues[2-]) ; local subfeature = [ find-implied-subfeature $(feature) $(subvalue) : $(value) ] ; # If no subfeature was found reconstitute the value string and use that. if ! $(subfeature) { result = $(components:J=-) ; result = $(result:G=$(feature)) ; subvalues = ; # Stop looping. } else { local f = [ MATCH ^<(.*)>$ : $(feature) ] ; result += $(subvalue:G=$(f)-$(subfeature)) ; } } return $(result) ;}# Make all elements of properties corresponding to implicit features explicit,# and express all subfeature values as separate properties in their own right.# For example, all of the following properties## gcc-2.95.2-linux-x86# <toolset>gcc-2.95.2-linux-x86## might expand to## <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86#rule expand-subfeatures ( properties * # Property set with elements of the form # <feature>value-string or just value-string in the case # of implicit features. : dont-validate ?){ local result ; for local p in $(properties) { # Don't expand subfeatures in subfeatures if ! [ MATCH "(:)" : $(p:G) ] { result += [ expand-subfeatures-aux $(p:G) : $(p:G=) : $(dont-validate) ] ; } else { result += $(p) ; } } return $(result) ;}# Helper for extend, below. Handles the feature case.#local rule extend-feature ( feature : values * ){ feature = [ grist $(feature) ] ; validate-feature $(feature) ; if implicit in $($(feature).attributes) { for local v in $(values) { if $($(v).implicit-feature) { errors.error $(v) is already associated with the \"$($(v).implicit-feature)\" feature ; } $(v).implicit-feature = $(feature) ; } .all-implicit-values += $(values) ; } if ! $($(feature).values) { # This is the first value specified for this feature so make it be the # default. $(feature).default = $(values[1]) ; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -