diff --git a/v2/build/property.jam b/v2/build/property.jam index 21b4e389b..d8971cf4a 100644 --- a/v2/build/property.jam +++ b/v2/build/property.jam @@ -9,6 +9,7 @@ import sequence : unique ; import errors : error ; import feature ; import regex ; +import string ; import sequence ; import set ; import path ; @@ -192,6 +193,30 @@ local rule path-order ( x y ) } } +local rule abbreviate-dashed ( string ) +{ + local r ; + for local part in [ regex.split $(string) - ] + { + r += [ string.abbreviate $(part) ] ; + } + return $(r:J=-) ; +} + +local rule identity ( string ) +{ + return $(string) ; +} + +if --abbreviate-paths in [ modules.peek : ARGV ] +{ + .abbrev = abbreviate-dashed ; +} +else +{ + .abbrev = identity ; +} + # Returns a path which represents the given expanded property set. rule as-path ( properties * ) { @@ -211,12 +236,10 @@ rule as-path ( properties * ) if $(p:G) { local f = [ ungrist $(p:G) ] ; - components += $(f)-$(p:G=) ; - } - else - { - components += $(p) ; + p = $(f)-$(p:G=) ; } + + components += [ $(.abbrev) $(p) ] ; } $(entry) = $(components:J=/) ; @@ -528,7 +551,7 @@ local rule __test__ ( ) import feature : feature subfeature compose ; # local rules must be explicitly re-imported - import property : path-order ; + import property : path-order abbreviate-dashed ; feature.prepare-test property-test-temp ; @@ -598,7 +621,10 @@ local rule __test__ ( ) : as-path gcc off off debug : $(test-space) ; - + + assert.result optmz-off : abbreviate-dashed optimization-off ; + assert.result rntm-lnk-sttc : abbreviate-dashed runtime-link-static ; + try ; validate value : $(test-space) ; catch "Invalid property 'value': unknown feature 'feature'." ; diff --git a/v2/util/string.jam b/v2/util/string.jam index dc19b2d13..e51c0b8ba 100644 --- a/v2/util/string.jam +++ b/v2/util/string.jam @@ -50,6 +50,57 @@ rule chars ( return $(result) ; } +# Apply a set of standard transformations to string to produce an +# abbreviation no more than 5 characters long +# +rule abbreviate ( string ) +{ + local r = $(.abbreviated-$(string)) ; + if $(r) + { + return $(r) ; + } + # Anything less than 4 characters gets no abbreviation + else if ! [ MATCH (....) : $(string) ] + { + $(.abbreviated-$(string)) = $(string) ; + return $(string) ; + } + else + { + # Separate the initial letter in case it's a vowel + local s1 = [ MATCH ^(.)(.*) : $(string) ] ; + + # drop trailing "ing" + local s2 = [ MATCH ^(.*)ing$ : $(s1[2]) ] ; + s2 ?= $(s1[2]) ; + + # Reduce all doubled characters to one + local last = "" ; + for local c in [ chars $(s2) ] + { + if $(c) != $(last) + { + r += $(c) ; + last = $(c) ; + } + } + s2 = $(r:J="") ; + + # Chop all vowels out of the remainder + s2 = [ regex.replace $(s2) [AEIOUaeiou] "" ] ; + + # Shorten remaining consonants to 4 characters + s2 = [ MATCH ^(.?.?.?.?) : $(s2) ] ; + + # Glue the initial character back on to the front + s2 = $(s1[1])$(s2) ; + + $(.abbreviated-$(string)) = $(s2) ; + return $(s2) ; + } +} + # Concatenates the given strings, inserting the given separator # between each string. # @@ -101,6 +152,15 @@ rule __test__ ( ) import assert ; assert.result a b c : chars abc ; + assert.result rntm : abbreviate runtime ; + assert.result ovrld : abbreviate overload ; + assert.result dbg : abbreviate debugging ; + assert.result async : abbreviate asynchronous ; + assert.result pop : abbreviate pop ; + assert.result aaa : abbreviate aaa ; + assert.result qck : abbreviate quack ; + assert.result sttc : abbreviate static ; + # check boundary cases assert.result a : chars a ; assert.result : chars "" ;