From f62f474ed336e1279505371946ae90e83b5252d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Ferdinand=20Rivera=20Morell?= Date: Thu, 17 Dec 2020 08:41:47 -0600 Subject: [PATCH] Fix use of mutiple conflicting @() in one action. In the case where multiple @() substitutions happen in one action the dynamic choice of file vs content would apply to all. This would cause problems as some of them might not be command options. This change adds an ":O=" options specifier to variables that can control what type of @() substitution can happen for each expansion. By specifying "O:=FC" one can select to allow either file or content expansion making that @() instance dynamic. When not specified the default is as if "O:=F". --- src/engine/function.cpp | 99 +++++++++++++++++++++++++++------------ src/tools/clang-linux.jam | 4 +- src/tools/msvc.jam | 19 ++++---- 3 files changed, 80 insertions(+), 42 deletions(-) diff --git a/src/engine/function.cpp b/src/engine/function.cpp index 8e5422ec0..434b6ba8d 100644 --- a/src/engine/function.cpp +++ b/src/engine/function.cpp @@ -622,23 +622,27 @@ typedef struct typedef struct { - PATHNAME f; /* :GDBSMR -- pieces */ - char parent; /* :P -- go to parent directory */ - char filemods; /* one of the above applied */ - char downshift; /* :L -- downshift result */ - char upshift; /* :U -- upshift result */ - char to_slashes; /* :T -- convert "\" to "/" */ - char to_windows; /* :W -- convert cygwin to native paths */ - PATHPART empty; /* :E -- default for empties */ - PATHPART join; /* :J -- join list with char */ - PATHPART prefix; /* :< */ - PATHPART postfix; /* :> */ + PATHNAME f; /* :GDBSMR -- pieces */ + PATHPART empty; /* :E -- default for empties */ + PATHPART join; /* :J -- join list with char */ + PATHPART prefix; /* :< */ + PATHPART postfix; /* :> */ + bool parent:1; /* :P -- go to parent directory */ + bool filemods:1; /* one of the above applied */ + bool downshift:1; /* :L -- downshift result */ + bool upshift:1; /* :U -- upshift result */ + bool to_slashes:1; /* :T -- convert "\" to "/" */ + bool to_windows:1; /* :W -- convert cygwin to native paths */ + bool opt_file:1; /* :O=F -- replace @() with the file part */ + bool opt_content:1; /* :O=C -- repalce @() with the content (E) part */ } VAR_EDITS; struct VAR_EXPANDED { LIST * value = L0; LIST * inner = L0; + bool opt_file:1; + bool opt_content:1; }; static VAR_EXPANDED apply_modifiers_impl( LIST * result, string * buf, @@ -688,6 +692,7 @@ static int32_t var_edit_parse( char const * mods, VAR_EDITS * edits, int32_t hav while ( *mods ) { PATHPART * fp; + bool opt = false; switch ( *mods++ ) { @@ -706,6 +711,7 @@ static int32_t var_edit_parse( char const * mods, VAR_EDITS * edits, int32_t hav case 'W': edits->to_windows = 1; continue; case '<': fp = &edits->prefix; goto strval; case '>': fp = &edits->postfix; goto strval; + case 'O': opt = true; goto strval; default: continue; /* Should complain, but so what... */ } @@ -735,17 +741,35 @@ static int32_t var_edit_parse( char const * mods, VAR_EDITS * edits, int32_t hav } strval: - /* Handle :X=value, or :X */ - if ( *mods != '=' ) + /* Handle :O=??? */ + if ( opt ) { - fp->ptr = ""; - fp->len = 0; + if ( *mods == '=' ) + { + for (++mods; *mods; ++mods) + { + switch ( *mods ) + { + case 'F': edits->opt_file = true; break; + case 'C': edits->opt_content = true; break; + } + } + } } else { - fp->ptr = ++mods; - fp->len = int32_t(strlen( mods )); - mods += fp->len; + /* Handle :X=value, or :X */ + if ( *mods != '=' ) + { + fp->ptr = ""; + fp->len = 0; + } + else + { + fp->ptr = ++mods; + fp->len = int32_t(strlen( mods )); + mods += fp->len; + } } } @@ -1150,6 +1174,13 @@ static VAR_EXPANDED apply_modifiers_impl( LIST * result, string * buf, expanded.value = apply_modifiers_prepost( L0, buf, edits, n, list_begin( modified ), list_end( modified ) ); expanded.inner = modified; + expanded.opt_file = false; + expanded.opt_content = false; + for ( int32_t i = 0; i < n; ++i ) + { + expanded.opt_file |= edits[i].opt_file; + expanded.opt_content |= edits[i].opt_content; + } return expanded; } @@ -3970,21 +4001,27 @@ LIST * function_execute_write_file( { LIST * filename_or_contents_result = nullptr; - LIST * response_file_sub = function_get_named_variable( - function, frame, constant_RESPONSE_FILE_SUB ); - char response_file_sub_c - = response_file_sub && list_front( response_file_sub ) - ? object_str( list_front( response_file_sub ) )[0] - : 'f'; - list_free( response_file_sub ); - const char * contents_str = object_str( list_front( contents ) ); - if ( response_file_sub_c == 'a' ) + char response_file_sub_c = 'f'; + if ( filename.opt_file && filename.opt_content ) { - if ( int32_t( strlen( contents_str ) + 256 ) > shell_maxline() ) - response_file_sub_c = 'f'; - else - response_file_sub_c = 'c'; + LIST * response_file_sub = function_get_named_variable( + function, frame, constant_RESPONSE_FILE_SUB ); + if ( response_file_sub && list_front( response_file_sub ) ) + response_file_sub_c = object_str( list_front( response_file_sub ) )[0]; + list_free( response_file_sub ); + const char * contents_str = object_str( list_front( contents ) ); + if ( response_file_sub_c == 'a' ) + { + if ( int32_t( strlen( contents_str ) + 256 ) > shell_maxline() ) + response_file_sub_c = 'f'; + else + response_file_sub_c = 'c'; + } } + else if ( filename.opt_file ) + response_file_sub_c = 'f'; + else if ( filename.opt_content ) + response_file_sub_c = 'c'; if ( response_file_sub_c == 'c' ) { filename_or_contents_result = list_copy( contents ); diff --git a/src/tools/clang-linux.jam b/src/tools/clang-linux.jam index aaeb2dc71..ca3bbcfd3 100644 --- a/src/tools/clang-linux.jam +++ b/src/tools/clang-linux.jam @@ -223,9 +223,9 @@ rule link.dll ( targets * : sources * : properties * ) { } actions link bind LIBRARIES { - "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" @($(<[1]:T).rsp:<=@":>=":E=-Wl,-R$(_)-Wl,"$(RPATH)" -Wl,-rpath-link$(_)-Wl,"$(RPATH_LINK)" $(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP)) $(OPTIONS) $(USER_OPTIONS) + "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" @($(<[1]:T).rsp:O=FC:<=@":>=":E=-Wl,-R$(_)-Wl,"$(RPATH)" -Wl,-rpath-link$(_)-Wl,"$(RPATH_LINK)" $(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP)) $(OPTIONS) $(USER_OPTIONS) } actions link.dll bind LIBRARIES { - "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" @($(<[1]:T).rsp:<=@":>=":E=-Wl,-R$(_)-Wl,"$(RPATH)" $(SONAME_OPT)$(<[1]:D=) -shared $(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP)) $(OPTIONS) $(USER_OPTIONS) + "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" @($(<[1]:T).rsp:O=FC:<=@":>=":E=-Wl,-R$(_)-Wl,"$(RPATH)" $(SONAME_OPT)$(<[1]:D=) -shared $(START-GROUP) "$(>:T)" "$(LIBRARIES:T)" $(FINDLIBS-ST-PFX:T) -l$(FINDLIBS-ST:T) $(FINDLIBS-SA-PFX:T) -l$(FINDLIBS-SA:T) $(END-GROUP)) $(OPTIONS) $(USER_OPTIONS) } diff --git a/src/tools/msvc.jam b/src/tools/msvc.jam index 8c1f92316..6f47851b6 100644 --- a/src/tools/msvc.jam +++ b/src/tools/msvc.jam @@ -587,7 +587,7 @@ if [ os.name ] in NT actions archive { if exist "$(<[1])" DEL "$(<[1])" - $(.SETUP) $(.LD) $(AROPTIONS) /out:"$(<[1])" @($(<[1]:W).rsp:<=@":>=":E="$(>)" $(LIBRARIES_MENTIONED_BY_FILE) "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib") + $(.SETUP) $(.LD) $(AROPTIONS) /out:"$(<[1])" @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>)" $(LIBRARIES_MENTIONED_BY_FILE) "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib") } } else @@ -595,7 +595,7 @@ else actions archive { $(.RM) "$(<[1])" - $(.SETUP) $(.LD) $(AROPTIONS) /out:"$(<[1])" @($(<[1]:W).rsp:<=@":>=":E="$(>)" $(LIBRARIES_MENTIONED_BY_FILE) "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib") + $(.SETUP) $(.LD) $(AROPTIONS) /out:"$(<[1])" @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>)" $(LIBRARIES_MENTIONED_BY_FILE) "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib") } } @@ -668,12 +668,12 @@ toolset.flags msvc YLOPTION : "-Yl" ; # actions compile-c-c++ bind PDB_NAME { - $(.SETUP) $(.CC) @($(<[1]:W).rsp:<=@":>=":E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE)) $(.CC.FILTER) + $(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE)) $(.CC.FILTER) } actions preprocess-c-c++ bind PDB_NAME { - $(.SETUP) $(.CC) @($(<[1]:W).rsp:<=@":>=":E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)" + $(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)" } rule compile-c-c++ ( targets + : sources * ) @@ -700,7 +700,7 @@ rule preprocess-c-c++ ( targets + : sources * ) # syntax highlighting in the messy N-quoted code below. actions compile-c-c++-pch { - $(.SETUP) $(.CC) @($(<[1]:W).rsp:<=@":>=":E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE)) @($(<[1]:W).cpp:<=":>=":E=#include $(.escaped-double-quote)$(>[1]:D=)$(.escaped-double-quote)$(.nl)) $(.CC.FILTER) + $(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE)) @($(<[1]:W).cpp:<=":>=":E=$(.hash)include $(.escaped-double-quote)$(>[1]:D=)$(.escaped-double-quote)$(.nl)) $(.CC.FILTER) } @@ -709,7 +709,7 @@ actions compile-c-c++-pch # given as one of the source parameters. actions compile-c-c++-pch-s { - $(.SETUP) $(.CC) @($(<[1]:W).rsp:<=@":>=":E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE)) $(.CC.FILTER) + $(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE)) $(.CC.FILTER) } @@ -754,7 +754,7 @@ rule compile.idl ( targets + : sources * : properties * ) # actions compile.idl { - $(.SETUP) $(.IDL) /nologo @($(<[1]:W).rsp:<=@":>=":E="$(>:W)" -D$(DEFINES) "-I$(INCLUDES:W)" -U$(UNDEFS) $(MIDLFLAGS) /tlb "$(<[1]:W)" /h "$(<[2]:W)" /iid "$(<[3]:W)" /proxy "$(<[4]:W)" /dlldata "$(<[5]:W)") + $(.SETUP) $(.IDL) /nologo @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>:W)" -D$(DEFINES) "-I$(INCLUDES:W)" -U$(UNDEFS) $(MIDLFLAGS) /tlb "$(<[1]:W)" /h "$(<[2]:W)" /iid "$(<[3]:W)" /proxy "$(<[4]:W)" /dlldata "$(<[5]:W)") $(.TOUCH_FILE) "$(<[4]:W)" $(.TOUCH_FILE) "$(<[5]:W)" } @@ -846,7 +846,7 @@ rule link.dll ( targets + : sources * : properties * ) { actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE MANIFEST_FILE { - $(.SETUP) $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" /MANIFESTINPUT:"$(MANIFEST_FILE)" $(OPTIONS) @($(<[1]:W).rsp:<=@":>=":E="$(>)" $(LIBRARIES_MENTIONED_BY_FILE) $(LIBRARIES) "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib") + $(.SETUP) $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" /MANIFESTINPUT:"$(MANIFEST_FILE)" $(OPTIONS) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>)" $(LIBRARIES_MENTIONED_BY_FILE) $(LIBRARIES) "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib") } actions manifest @@ -861,7 +861,7 @@ rule link.dll ( targets + : sources * : properties * ) actions link.dll bind IMPORT_LIB DEF_FILE LIBRARIES_MENTIONED_BY_FILE MANIFEST_FILE { - $(.SETUP) $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(IMPORT_LIB:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" /MANIFESTINPUT:"$(MANIFEST_FILE)" $(OPTIONS) @($(<[1]:W).rsp:<=@":>=":E="$(>)" $(LIBRARIES_MENTIONED_BY_FILE) $(LIBRARIES) "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib") + $(.SETUP) $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(IMPORT_LIB:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" /MANIFESTINPUT:"$(MANIFEST_FILE)" $(OPTIONS) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>)" $(LIBRARIES_MENTIONED_BY_FILE) $(LIBRARIES) "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib") } actions manifest.dll @@ -1998,6 +1998,7 @@ if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] _ = " " ; .ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ; .escaped-double-quote = "\"" ; +.hash = "\#" ; .TOUCH_FILE = [ common.file-touch-command ] ; # List of all registered configurations.