diff --git a/src/engine/value.h b/src/engine/value.h index 3a9d628df..ba9c3819c 100644 --- a/src/engine/value.h +++ b/src/engine/value.h @@ -121,6 +121,9 @@ struct value_ref inline value_ref(const std::string & s) : val(value::make(s.c_str())) {} + inline value_ref(const string_view & sv) + : val(value::make(sv)) + {} inline ~value_ref() { diff --git a/src/engine/variable.cpp b/src/engine/variable.cpp index 13bcbba54..7eea22166 100644 --- a/src/engine/variable.cpp +++ b/src/engine/variable.cpp @@ -40,6 +40,8 @@ #include "pathsys.h" #include "jam_strings.h" #include "output.h" +#include "strview.h" +#include "value.h" #include #include @@ -71,88 +73,66 @@ static void var_dump( OBJECT * symbol, LIST * value, const char * what ); * Otherwise, split the value at blanks. */ -void var_defines( struct module_t * module, const char * const * e, int preprocess ) +void var_defines(struct module_t * module, const char * const * e, int preprocess) { - string buf[ 1 ]; + for (; *e; ++e) + { + ::b2::string_view def(*e); + ::b2::string_view var(def.begin(), def.find('=')); + ::b2::string_view val(def.begin() + var.size() + 1); + b2::jam::variable jam_var { module, + std::string { var.begin(), var.end() }.c_str() }; + // std::printf(">> var_defines: *e = %s\n", *e); + // for (auto v : jam_var.get()) + // { + // std::printf(" '%s'\n", v->str()); + // } - string_new( buf ); + // No value to set var with. + if (var.size() == def.size()) continue; - for ( ; *e; ++e ) - { - const char * val; + // Skip pre-processing, to just set the raw value. + if (preprocess == 0) + { + jam_var = ::b2::list_ref { ::b2::value_ref { val } }; + continue; + } - if ( ( val = strchr( *e, '=' ) ) -#if defined( OS_MAC ) - /* On the mac (MPW), the var=val is actually var\0val */ - /* Think different. */ - || ( val = *e + strlen( *e ) ) -#endif - ) - { - LIST * l = L0; - int32_t const len = int32_t(strlen( val + 1 )); - int const quoted = ( val[ 1 ] == '"' ) && ( val[ len ] == '"' ) && - ( len > 1 ); + // Quoted values do not get separator-split. But do get unquoted. + if (val.size() >= 2 && val.front() == '"' && val.back() == '"') + { + jam_var = ::b2::list_ref { ::b2::value_ref { + val.substr(1, val.size() - 2) } }; + continue; + } - if ( quoted && preprocess ) - { - string_append_range( buf, val + 2, val + len ); - l = list_push_back( l, object_new( buf->value ) ); - string_truncate( buf, 0 ); - } - else - { - const char * p; - const char * pp; - char split = -#if defined( OPT_NO_EXTERNAL_VARIABLE_SPLIT ) - '\0' -#elif defined( OS_MAC ) - ',' -#else - ' ' -#endif - ; - - /* Split *PATH at :'s, not spaces. */ - if ( val - 4 >= *e ) - { - if ( !strncmp( val - 4, "PATH", 4 ) || - !strncmp( val - 4, "Path", 4 ) || - !strncmp( val - 4, "path", 4 ) ) - split = SPLITPATH; - } - - /* Do the split. */ - for - ( - pp = val + 1; - preprocess && ( ( p = strchr( pp, split ) ) != 0 ); - pp = p + 1 - ) - { - string_append_range( buf, pp, p ); - l = list_push_back( l, object_new( buf->value ) ); - string_truncate( buf, 0 ); - } - - l = list_push_back( l, object_new( pp ) ); - } - - /* Get name. */ - string_append_range( buf, *e, val ); - { - OBJECT * varname = object_new( buf->value ); - var_set( module, varname, l, VAR_SET ); - object_free( varname ); - } - string_truncate( buf, 0 ); - } - } - string_free( buf ); + // Split on separator, either space or path. + jam_var = ::b2::list_cref {}; + { + char split = ' '; + /* Split *PATH at :'s, not spaces. */ + if (var.ends_with("PATH") + || var.ends_with("Path" || var.ends_with("path"))) + split = SPLITPATH; + /* Do the split. */ + for (::b2::string_view::size_type p0 = 0; p0 < val.size();) + { + auto p1 = val.find(split, p0); + if (p1 == val.npos) + { + jam_var += ::b2::value_ref { val.substr(p0) }; + p0 = val.npos; + } + else + { + jam_var += ::b2::value_ref { val.substr(p0, p1 - p0) }; + p0 = p1 + 1; + } + } + } + } } - /* Last returned variable value saved so we may clear it in var_done(). */ static LIST * saved_var = L0; diff --git a/src/engine/variable.h b/src/engine/variable.h index d96ee2471..6cbc0edbb 100644 --- a/src/engine/variable.h +++ b/src/engine/variable.h @@ -71,6 +71,9 @@ struct variable inline variable(const std::string & m, const std::string & v) : variable(m.c_str(), v.c_str()) {} + inline variable(struct module_t * m, const std::string & v) + : variable(m, v.c_str()) + {} // Refer to variable in global/root module. inline explicit variable(const char * v)